- 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
45 lines
1.9 KiB
JavaScript
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';
|
|
}
|