Files
Skald-Circle/web/components/shared/plugin-common.js
T
dguiducci ba911ae8cb feat(plugins): plugin pages, per-user config, capabilities gate, mobile/telegram refactors
- Plugin HTTP routes + web pages (plugin-page-host, plugin-catalog, plugin-detail)
- Plugin access grants + per-user config (DB tables + API + frontend forms)
- Capabilities-based guard (caps.rs) replacing role-id checks
- Mobile connector: message routing, payload types, router refactor
- Telegram bot: auth flow, event handling improvements
- Honcho plugin: substantial rework
- Sidebar: plugin pages integration, role-driven visibility
- i18n: new strings for plugins, connectors, capabilities
- Remove unused mascot asset
2026-07-19 20:47:09 +01:00

45 lines
1.9 KiB
JavaScript

// Shared helpers for the plugin pages (`plugins-page`, `plugin-catalog`,
// `plugin-detail`). Kept separate from `connector-common.js` on purpose: the
// plugin model (JSON-Schema config blobs, `plugin_access`) is not the
// connector model (env/api_key manifests).
export async function jf(url, opts) {
const res = await fetch(url, opts);
if (!res.ok) throw new Error(await res.text() || `HTTP ${res.status}`);
const ct = res.headers.get('content-type') || '';
return ct.includes('application/json') ? res.json() : null;
}
/// Normalizes a plugin JSON Schema (`{properties, required}`) into flat field
/// descriptors. Only the scalar types a form can render are supported.
export function schemaFields(schema) {
const props = schema?.properties;
if (!props || typeof props !== 'object') return [];
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
return Object.entries(props).map(([key, p]) => ({
key,
label: p.title || key,
description: p.description || '',
type: p.type === 'boolean' ? 'boolean' : (p.type === 'integer' || p.type === 'number') ? 'number' : 'string',
required: required.has(key),
sensitive: !!p.sensitive,
}));
}
export const hasSchema = (schema) => schemaFields(schema).length > 0;
/// Required config keys with no persisted value yet.
export function missingRequired(p) {
return schemaFields(p.config_schema)
.filter(f => f.required && (p.config?.[f.key] === undefined || p.config?.[f.key] === null || p.config?.[f.key] === ''));
}
/// Admin-catalog health of a plugin: 'off' | 'needs_config' | 'not_running' | 'ok'.
/// Green only when enabled, running and every required config key is set.
export function pluginHealth(p) {
if (!p.enabled) return 'off';
if (missingRequired(p).length) return 'needs_config';
if (!p.running) return 'not_running';
return 'ok';
}