mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 14:06:27 +00:00
Feat/plugin instance actions (#2209)
* feat(shared): scope plugin action descriptors * feat(plugin-sdk): instance-scoped settings actions * feat(plugins): run instance-scoped actions from the admin settings dialog * feat(admin): instance-scoped plugin actions in the settings dialog * fix(plugins): surface instance actions without instance fields and harden the action gate * docs(plugin-sdk): note that hosts before 4.2.0 ignore action scope * fix(admin): open the dialog for instance actions, explain inactive 404s, guard the save window * docs(wiki): plugin pages for instance actions and the admin panel changes
This commit is contained in:
@@ -454,6 +454,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'إعدادات مستوى الخادم',
|
||||
'admin.plugins.settingsSaved': 'تم حفظ الإعدادات',
|
||||
'admin.plugins.settingsSavedRestarted': 'تم حفظ الإعدادات — تمت إعادة تشغيل الإضافة',
|
||||
'admin.plugins.actions': 'الإجراءات',
|
||||
'admin.plugins.actions.confirm': 'تنفيذ هذا الإجراء؟',
|
||||
'admin.plugins.actions.inactive': 'فعّل الإضافة لتشغيل إجراءاتها',
|
||||
'admin.plugins.requiredMissing': '"{field}" مطلوب',
|
||||
'admin.plugins.cap.readsTrips': 'يقرأ رحلاتك',
|
||||
'admin.plugins.cap.readsUsers': 'يقرأ الملفات الشخصية الأساسية',
|
||||
|
||||
@@ -443,6 +443,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Configurações da instância',
|
||||
'admin.plugins.settingsSaved': 'Configurações salvas',
|
||||
'admin.plugins.settingsSavedRestarted': 'Configurações salvas — plugin reiniciado',
|
||||
'admin.plugins.actions': 'Ações',
|
||||
'admin.plugins.actions.confirm': 'Executar esta ação?',
|
||||
'admin.plugins.actions.inactive': 'Ative o plugin para executar suas ações',
|
||||
'admin.plugins.requiredMissing': '"{field}" é obrigatório',
|
||||
'admin.plugins.cap.readsTrips': 'Lê suas viagens',
|
||||
'admin.plugins.cap.readsUsers': 'Lê perfis básicos',
|
||||
|
||||
@@ -577,6 +577,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Configuració de la instància',
|
||||
'admin.plugins.settingsSaved': 'Configuració desada',
|
||||
'admin.plugins.settingsSavedRestarted': 'Configuració desada — connector reiniciat',
|
||||
'admin.plugins.actions': 'Accions',
|
||||
'admin.plugins.actions.confirm': 'Vols executar aquesta acció?',
|
||||
'admin.plugins.actions.inactive': 'Activa el connector per executar les seves accions',
|
||||
'admin.plugins.requiredMissing': '"{field}" és obligatori',
|
||||
'admin.plugins.cap.readsTrips': 'Llegeix els teus viatges',
|
||||
'admin.plugins.cap.readsUsers': 'Llegeix els perfils bàsics',
|
||||
|
||||
@@ -441,6 +441,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Nastavení instance',
|
||||
'admin.plugins.settingsSaved': 'Nastavení uloženo',
|
||||
'admin.plugins.settingsSavedRestarted': 'Nastavení uloženo — plugin restartován',
|
||||
'admin.plugins.actions': 'Akce',
|
||||
'admin.plugins.actions.confirm': 'Spustit tuto akci?',
|
||||
'admin.plugins.actions.inactive': 'Aktivujte plugin, abyste mohli spouštět jeho akce',
|
||||
'admin.plugins.requiredMissing': '„{field}" je povinné',
|
||||
'admin.plugins.cap.readsTrips': 'Čte vaše cesty',
|
||||
'admin.plugins.cap.readsUsers': 'Čte základní profily',
|
||||
|
||||
@@ -450,6 +450,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Instanz-Einstellungen',
|
||||
'admin.plugins.settingsSaved': 'Einstellungen gespeichert',
|
||||
'admin.plugins.settingsSavedRestarted': 'Einstellungen gespeichert — Plugin neu gestartet',
|
||||
'admin.plugins.actions': 'Aktionen',
|
||||
'admin.plugins.actions.confirm': 'Diese Aktion ausführen?',
|
||||
'admin.plugins.actions.inactive': 'Aktiviere das Plugin, um seine Aktionen auszuführen',
|
||||
'admin.plugins.requiredMissing': '"{field}" ist erforderlich',
|
||||
'admin.plugins.cap.readsTrips': 'Liest deine Reisen',
|
||||
'admin.plugins.cap.readsUsers': 'Liest Basis-Profile',
|
||||
|
||||
@@ -488,6 +488,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Instance settings',
|
||||
'admin.plugins.settingsSaved': 'Settings saved',
|
||||
'admin.plugins.settingsSavedRestarted': 'Settings saved — plugin restarted',
|
||||
'admin.plugins.actions': 'Actions',
|
||||
'admin.plugins.actions.confirm': 'Run this action?',
|
||||
'admin.plugins.actions.inactive': 'Activate the plugin to run its actions',
|
||||
'admin.plugins.requiredMissing': '"{field}" is required',
|
||||
'admin.plugins.cap.readsTrips': 'Reads your trips',
|
||||
'admin.plugins.cap.readsUsers': 'Reads basic profiles',
|
||||
|
||||
@@ -452,6 +452,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Ajustes de la instancia',
|
||||
'admin.plugins.settingsSaved': 'Ajustes guardados',
|
||||
'admin.plugins.settingsSavedRestarted': 'Ajustes guardados — plugin reiniciado',
|
||||
'admin.plugins.actions': 'Acciones',
|
||||
'admin.plugins.actions.confirm': '¿Ejecutar esta acción?',
|
||||
'admin.plugins.actions.inactive': 'Activa el plugin para ejecutar sus acciones',
|
||||
'admin.plugins.requiredMissing': '"{field}" es obligatorio',
|
||||
'admin.plugins.cap.readsTrips': 'Lee tus viajes',
|
||||
'admin.plugins.cap.readsUsers': 'Lee perfiles básicos',
|
||||
|
||||
@@ -455,6 +455,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Paramètres de l’instance',
|
||||
'admin.plugins.settingsSaved': 'Paramètres enregistrés',
|
||||
'admin.plugins.settingsSavedRestarted': 'Paramètres enregistrés — plugin redémarré',
|
||||
'admin.plugins.actions': 'Actions',
|
||||
'admin.plugins.actions.confirm': 'Exécuter cette action ?',
|
||||
'admin.plugins.actions.inactive': 'Activez le plugin pour exécuter ses actions',
|
||||
'admin.plugins.requiredMissing': '« {field} » est obligatoire',
|
||||
'admin.plugins.cap.readsTrips': 'Lit vos voyages',
|
||||
'admin.plugins.cap.readsUsers': 'Lit les profils de base',
|
||||
|
||||
@@ -503,6 +503,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Ρυθμίσεις εγκατάστασης',
|
||||
'admin.plugins.settingsSaved': 'Οι ρυθμίσεις αποθηκεύτηκαν',
|
||||
'admin.plugins.settingsSavedRestarted': 'Οι ρυθμίσεις αποθηκεύτηκαν — το plugin επανεκκινήθηκε',
|
||||
'admin.plugins.actions': 'Ενέργειες',
|
||||
'admin.plugins.actions.confirm': 'Εκτέλεση αυτής της ενέργειας;',
|
||||
'admin.plugins.actions.inactive': 'Ενεργοποιήστε το plugin για να εκτελέσετε τις ενέργειές του',
|
||||
'admin.plugins.requiredMissing': '"{field}" είναι υποχρεωτικό',
|
||||
'admin.plugins.cap.readsTrips': 'Διαβάζει τα ταξίδια σας',
|
||||
'admin.plugins.cap.readsUsers': 'Διαβάζει βασικά προφίλ',
|
||||
|
||||
@@ -455,6 +455,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Példányszintű beállítások',
|
||||
'admin.plugins.settingsSaved': 'Beállítások elmentve',
|
||||
'admin.plugins.settingsSavedRestarted': 'Beállítások elmentve — plugin újraindítva',
|
||||
'admin.plugins.actions': 'Műveletek',
|
||||
'admin.plugins.actions.confirm': 'Végrehajtod ezt a műveletet?',
|
||||
'admin.plugins.actions.inactive': 'Aktiváld a plugint a műveletei futtatásához',
|
||||
'admin.plugins.requiredMissing': '"{field}" kötelező',
|
||||
'admin.plugins.cap.readsTrips': 'Olvassa az utazásaidat',
|
||||
'admin.plugins.cap.readsUsers': 'Olvassa az alapprofilokat',
|
||||
|
||||
@@ -497,6 +497,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Pengaturan instans',
|
||||
'admin.plugins.settingsSaved': 'Pengaturan disimpan',
|
||||
'admin.plugins.settingsSavedRestarted': 'Pengaturan disimpan — plugin dimulai ulang',
|
||||
'admin.plugins.actions': 'Tindakan',
|
||||
'admin.plugins.actions.confirm': 'Jalankan tindakan ini?',
|
||||
'admin.plugins.actions.inactive': 'Aktifkan plugin untuk menjalankan tindakannya',
|
||||
'admin.plugins.requiredMissing': '"{field}" wajib diisi',
|
||||
'admin.plugins.cap.readsTrips': 'Membaca perjalananmu',
|
||||
'admin.plugins.cap.readsUsers': 'Membaca profil dasar',
|
||||
|
||||
@@ -450,6 +450,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Impostazioni dell’istanza',
|
||||
'admin.plugins.settingsSaved': 'Impostazioni salvate',
|
||||
'admin.plugins.settingsSavedRestarted': 'Impostazioni salvate — plugin riavviato',
|
||||
'admin.plugins.actions': 'Azioni',
|
||||
'admin.plugins.actions.confirm': 'Eseguire questa azione?',
|
||||
'admin.plugins.actions.inactive': 'Attiva il plugin per eseguire le sue azioni',
|
||||
'admin.plugins.requiredMissing': '"{field}" è obbligatorio',
|
||||
'admin.plugins.cap.readsTrips': 'Legge i tuoi viaggi',
|
||||
'admin.plugins.cap.readsUsers': 'Legge i profili di base',
|
||||
|
||||
@@ -462,6 +462,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'インスタンス設定',
|
||||
'admin.plugins.settingsSaved': '設定を保存しました',
|
||||
'admin.plugins.settingsSavedRestarted': '設定を保存しました — プラグインを再起動しました',
|
||||
'admin.plugins.actions': 'アクション',
|
||||
'admin.plugins.actions.confirm': 'このアクションを実行しますか?',
|
||||
'admin.plugins.actions.inactive': 'アクションを実行するにはプラグインを有効化してください',
|
||||
'admin.plugins.requiredMissing': '「{field}」は必須です',
|
||||
'admin.plugins.cap.readsTrips': '旅行を読み取り',
|
||||
'admin.plugins.cap.readsUsers': '基本プロフィールを読み取り',
|
||||
|
||||
@@ -462,6 +462,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': '인스턴스 설정',
|
||||
'admin.plugins.settingsSaved': '설정이 저장되었습니다',
|
||||
'admin.plugins.settingsSavedRestarted': '설정이 저장되었습니다 — 플러그인이 다시 시작되었습니다',
|
||||
'admin.plugins.actions': '작업',
|
||||
'admin.plugins.actions.confirm': '이 작업을 실행할까요?',
|
||||
'admin.plugins.actions.inactive': '작업을 실행하려면 플러그인을 활성화하세요',
|
||||
'admin.plugins.requiredMissing': '"{field}"은(는) 필수입니다',
|
||||
'admin.plugins.cap.readsTrips': '여행 읽기',
|
||||
'admin.plugins.cap.readsUsers': '기본 프로필 읽기',
|
||||
|
||||
@@ -449,6 +449,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Instantie-instellingen',
|
||||
'admin.plugins.settingsSaved': 'Instellingen opgeslagen',
|
||||
'admin.plugins.settingsSavedRestarted': 'Instellingen opgeslagen — plugin opnieuw gestart',
|
||||
'admin.plugins.actions': 'Acties',
|
||||
'admin.plugins.actions.confirm': 'Deze actie uitvoeren?',
|
||||
'admin.plugins.actions.inactive': 'Activeer de plugin om de acties uit te voeren',
|
||||
'admin.plugins.requiredMissing': '"{field}" is vereist',
|
||||
'admin.plugins.cap.readsTrips': 'Leest je reizen',
|
||||
'admin.plugins.cap.readsUsers': 'Leest basisprofielen',
|
||||
|
||||
@@ -447,6 +447,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Ustawienia instancji',
|
||||
'admin.plugins.settingsSaved': 'Ustawienia zapisane',
|
||||
'admin.plugins.settingsSavedRestarted': 'Ustawienia zapisane — wtyczka została uruchomiona ponownie',
|
||||
'admin.plugins.actions': 'Akcje',
|
||||
'admin.plugins.actions.confirm': 'Wykonać tę akcję?',
|
||||
'admin.plugins.actions.inactive': 'Aktywuj wtyczkę, aby uruchomić jej akcje',
|
||||
'admin.plugins.requiredMissing': '"{field}" jest wymagane',
|
||||
'admin.plugins.cap.readsTrips': 'Odczytuje Twoje podróże',
|
||||
'admin.plugins.cap.readsUsers': 'Odczytuje podstawowe profile',
|
||||
|
||||
@@ -451,6 +451,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Настройки экземпляра',
|
||||
'admin.plugins.settingsSaved': 'Настройки сохранены',
|
||||
'admin.plugins.settingsSavedRestarted': 'Настройки сохранены — плагин перезапущен',
|
||||
'admin.plugins.actions': 'Действия',
|
||||
'admin.plugins.actions.confirm': 'Выполнить это действие?',
|
||||
'admin.plugins.actions.inactive': 'Активируйте плагин, чтобы выполнять его действия',
|
||||
'admin.plugins.requiredMissing': '«{field}» обязательно',
|
||||
'admin.plugins.cap.readsTrips': 'Читает ваши поездки',
|
||||
'admin.plugins.cap.readsUsers': 'Читает основные профили',
|
||||
|
||||
@@ -508,6 +508,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Instansinställningar',
|
||||
'admin.plugins.settingsSaved': 'Inställningarna har sparats',
|
||||
'admin.plugins.settingsSavedRestarted': 'Inställningarna har sparats — pluginet har startats om',
|
||||
'admin.plugins.actions': 'Åtgärder',
|
||||
'admin.plugins.actions.confirm': 'Kör den här åtgärden?',
|
||||
'admin.plugins.actions.inactive': 'Aktivera pluginet för att köra dess åtgärder',
|
||||
'admin.plugins.requiredMissing': '"{field}" krävs',
|
||||
'admin.plugins.cap.readsTrips': 'Läser dina resor',
|
||||
'admin.plugins.cap.readsUsers': 'Läser grundläggande profiler',
|
||||
|
||||
@@ -494,6 +494,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Örnek ayarları',
|
||||
'admin.plugins.settingsSaved': 'Ayarlar kaydedildi',
|
||||
'admin.plugins.settingsSavedRestarted': 'Ayarlar kaydedildi — eklenti yeniden başlatıldı',
|
||||
'admin.plugins.actions': 'Eylemler',
|
||||
'admin.plugins.actions.confirm': 'Bu eylem çalıştırılsın mı?',
|
||||
'admin.plugins.actions.inactive': 'Eylemlerini çalıştırmak için eklentiyi etkinleştirin',
|
||||
'admin.plugins.requiredMissing': '"{field}" gerekli',
|
||||
'admin.plugins.cap.readsTrips': 'Seyahatlerinizi okur',
|
||||
'admin.plugins.cap.readsUsers': 'Temel profilleri okur',
|
||||
|
||||
@@ -448,6 +448,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Налаштування інстансу',
|
||||
'admin.plugins.settingsSaved': 'Налаштування збережено',
|
||||
'admin.plugins.settingsSavedRestarted': 'Налаштування збережено — плагін перезапущено',
|
||||
'admin.plugins.actions': 'Дії',
|
||||
'admin.plugins.actions.confirm': 'Виконати цю дію?',
|
||||
'admin.plugins.actions.inactive': 'Активуйте плагін, щоб виконувати його дії',
|
||||
'admin.plugins.requiredMissing': '«{field}» обов’язкове',
|
||||
'admin.plugins.cap.readsTrips': 'Читає ваші подорожі',
|
||||
'admin.plugins.cap.readsUsers': 'Читає базові профілі',
|
||||
|
||||
@@ -450,6 +450,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': 'Cài đặt toàn hệ thống',
|
||||
'admin.plugins.settingsSaved': 'Đã lưu cài đặt',
|
||||
'admin.plugins.settingsSavedRestarted': 'Đã lưu cài đặt — đã khởi động lại plugin',
|
||||
'admin.plugins.actions': 'Hành động',
|
||||
'admin.plugins.actions.confirm': 'Chạy hành động này?',
|
||||
'admin.plugins.actions.inactive': 'Kích hoạt plugin để chạy các hành động của nó',
|
||||
'admin.plugins.requiredMissing': '"{field}" là bắt buộc',
|
||||
'admin.plugins.cap.readsTrips': 'Đọc chuyến đi của bạn',
|
||||
'admin.plugins.cap.readsUsers': 'Đọc hồ sơ cơ bản',
|
||||
|
||||
@@ -444,6 +444,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': '執行個體設定',
|
||||
'admin.plugins.settingsSaved': '設定已儲存',
|
||||
'admin.plugins.settingsSavedRestarted': '設定已儲存 — 外掛已重新啟動',
|
||||
'admin.plugins.actions': '操作',
|
||||
'admin.plugins.actions.confirm': '執行此操作?',
|
||||
'admin.plugins.actions.inactive': '啟用外掛以執行其操作',
|
||||
'admin.plugins.requiredMissing': '「{field}」為必填項',
|
||||
'admin.plugins.cap.readsTrips': '讀取你的行程',
|
||||
'admin.plugins.cap.readsUsers': '讀取基本個人資料',
|
||||
|
||||
@@ -404,6 +404,9 @@ const admin: TranslationStrings = {
|
||||
'admin.plugins.instanceSettings': '实例设置',
|
||||
'admin.plugins.settingsSaved': '设置已保存',
|
||||
'admin.plugins.settingsSavedRestarted': '设置已保存 — 插件已重启',
|
||||
'admin.plugins.actions': '操作',
|
||||
'admin.plugins.actions.confirm': '执行此操作?',
|
||||
'admin.plugins.actions.inactive': '激活插件以运行其操作',
|
||||
'admin.plugins.requiredMissing': '「{field}」为必填项',
|
||||
'admin.plugins.cap.readsTrips': '读取你的旅行',
|
||||
'admin.plugins.cap.readsUsers': '读取基本个人资料',
|
||||
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
pluginEgressHostsRequestSchema,
|
||||
pluginUserSettingsUpdateRequestSchema,
|
||||
pluginRouteRequestSchema,
|
||||
pluginActionDescriptorSchema,
|
||||
pluginActionResultSchema,
|
||||
} from './plugins.schema';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
@@ -70,6 +72,7 @@ describe('instance-config wire shapes', () => {
|
||||
},
|
||||
],
|
||||
config: { apiUrl: 'https://x.example', apiKey: '••••••••' },
|
||||
actions: [],
|
||||
};
|
||||
expect(pluginInstanceConfigResponseSchema.parse(res).fields).toHaveLength(1);
|
||||
});
|
||||
@@ -139,3 +142,33 @@ describe('admin body contracts stay loose by doctrine', () => {
|
||||
expect(pluginRouteRequestSchema.safeParse({ anything: [1, 2, 3] }).success).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('plugin action contracts', () => {
|
||||
it('SHARED-PLUG-ACT-001: a descriptor carries key/label/danger/scope and an optional hint', () => {
|
||||
expect(
|
||||
pluginActionDescriptorSchema.parse({ key: 'purge', label: 'Purge cache', danger: true, scope: 'instance' }),
|
||||
).toEqual({ key: 'purge', label: 'Purge cache', danger: true, scope: 'instance' });
|
||||
expect(pluginActionDescriptorSchema.parse({ key: 'a', label: 'A', hint: 'h', danger: false, scope: 'user' }).hint).toBe('h');
|
||||
});
|
||||
|
||||
it('SHARED-PLUG-ACT-002: refuses a scope outside user|instance and a missing scope', () => {
|
||||
expect(pluginActionDescriptorSchema.safeParse({ key: 'a', label: 'A', danger: false, scope: 'global' }).success).toBe(false);
|
||||
expect(pluginActionDescriptorSchema.safeParse({ key: 'a', label: 'A', danger: false }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('SHARED-PLUG-ACT-003: a result is ok plus an optional message', () => {
|
||||
expect(pluginActionResultSchema.parse({ ok: true })).toEqual({ ok: true });
|
||||
expect(pluginActionResultSchema.parse({ ok: false, message: 'nope' })).toEqual({ ok: false, message: 'nope' });
|
||||
expect(pluginActionResultSchema.safeParse({ message: 'x' }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('SHARED-PLUG-ACT-004: the instance config response now lists instance actions', () => {
|
||||
const r = pluginInstanceConfigResponseSchema.parse({
|
||||
fields: [],
|
||||
config: {},
|
||||
actions: [{ key: 'ping', label: 'Ping', danger: false, scope: 'instance' }],
|
||||
});
|
||||
expect(r.actions).toHaveLength(1);
|
||||
expect(pluginInstanceConfigResponseSchema.safeParse({ fields: [], config: {} }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,11 +31,37 @@ export const pluginSettingsFieldSchema = z.object({
|
||||
});
|
||||
export type PluginSettingsField = z.infer<typeof pluginSettingsFieldSchema>;
|
||||
|
||||
/**
|
||||
* A settings-form action button a plugin declared in its manifest (`actions`). Which
|
||||
* form renders it is the `scope`, exactly like a settings field: `'user'` on the user
|
||||
* Settings tab (runs as the clicking user), `'instance'` in the admin instance-settings
|
||||
* dialog (runs as the clicking admin). One action lives in exactly one form.
|
||||
*/
|
||||
export const pluginActionScopeSchema = z.enum(['user', 'instance']);
|
||||
export type PluginActionScope = z.infer<typeof pluginActionScopeSchema>;
|
||||
|
||||
export const pluginActionDescriptorSchema = z.object({
|
||||
key: z.string(),
|
||||
label: z.string(),
|
||||
hint: z.string().optional(),
|
||||
danger: z.boolean(),
|
||||
scope: pluginActionScopeSchema,
|
||||
});
|
||||
export type PluginActionDescriptor = z.infer<typeof pluginActionDescriptorSchema>;
|
||||
|
||||
/** What an action answers, after the host bounded the plugin-supplied message. */
|
||||
export const pluginActionResultSchema = z.object({
|
||||
ok: z.boolean(),
|
||||
message: z.string().optional(),
|
||||
});
|
||||
export type PluginActionResult = z.infer<typeof pluginActionResultSchema>;
|
||||
|
||||
/** GET /api/admin/plugins/:id/config — the declared `scope:'instance'` fields
|
||||
* plus the stored values, secrets masked. */
|
||||
* plus the stored values, secrets masked, plus the `scope:'instance'` actions. */
|
||||
export const pluginInstanceConfigResponseSchema = z.object({
|
||||
fields: z.array(pluginSettingsFieldSchema),
|
||||
config: z.record(z.string(), z.unknown()),
|
||||
actions: z.array(pluginActionDescriptorSchema),
|
||||
});
|
||||
export type PluginInstanceConfigResponse = z.infer<typeof pluginInstanceConfigResponseSchema>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user