@oktis-works/plugin-runtime 0.5.10 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/bootstrap.d.ts +86 -21
  2. package/dist/bootstrap.d.ts.map +1 -1
  3. package/dist/bootstrap.js +254 -42
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/content-query.d.ts +29 -0
  6. package/dist/content-query.d.ts.map +1 -0
  7. package/dist/content-query.js +109 -0
  8. package/dist/content-query.js.map +1 -0
  9. package/dist/hook-registry.d.ts +21 -21
  10. package/dist/hook-registry.d.ts.map +1 -1
  11. package/dist/hook-registry.js +26 -26
  12. package/dist/hook-registry.js.map +1 -1
  13. package/dist/http.d.ts +49 -0
  14. package/dist/http.d.ts.map +1 -0
  15. package/dist/http.js +313 -0
  16. package/dist/http.js.map +1 -0
  17. package/dist/i18n.d.ts +16 -0
  18. package/dist/i18n.d.ts.map +1 -0
  19. package/dist/i18n.js +73 -0
  20. package/dist/i18n.js.map +1 -0
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/loader.js +3 -3
  26. package/dist/loader.js.map +1 -1
  27. package/dist/manifest.d.ts +11 -6
  28. package/dist/manifest.d.ts.map +1 -1
  29. package/dist/manifest.js +227 -17
  30. package/dist/manifest.js.map +1 -1
  31. package/dist/plugin-api.d.ts +191 -38
  32. package/dist/plugin-api.d.ts.map +1 -1
  33. package/dist/plugin-api.js +572 -10
  34. package/dist/plugin-api.js.map +1 -1
  35. package/dist/plugin-migrations.d.ts +15 -0
  36. package/dist/plugin-migrations.d.ts.map +1 -0
  37. package/dist/plugin-migrations.js +68 -0
  38. package/dist/plugin-migrations.js.map +1 -0
  39. package/dist/sandbox.d.ts +13 -11
  40. package/dist/sandbox.d.ts.map +1 -1
  41. package/dist/sandbox.js +11 -9
  42. package/dist/sandbox.js.map +1 -1
  43. package/dist/style-isolation.d.ts +3 -3
  44. package/dist/style-isolation.js +6 -6
  45. package/dist/style-isolation.js.map +1 -1
  46. package/package.json +7 -6
package/dist/manifest.js CHANGED
@@ -1,22 +1,220 @@
1
- // @oktis-works/plugin-runtime - Fonte única de leitura de manifesto de plugin
1
+ // @oktis-works/plugin-runtime - Single source of truth for reading plugin manifests
2
2
  //
3
- // Antes havia duas fontes de verdade divergentes:
4
- // - o loader lia `package.json` primeiro, depois `manifest.json`;
5
- // - o sync (admin) e a CLI liam só `manifest.json`.
6
- // Um plugin no formato npm era descoberto pelo runtime mas nunca chegava ao
7
- // banco (invisível no admin). Aqui tudo passa por `readPluginManifest`:
3
+ // Historically:
4
+ // - the admin sync and the CLI read only `manifest.json`;
5
+ // - npm plugins could skip it and live off `package.json` (fields then came
6
+ // from the database — invisible in the admin). Everything now goes through
7
+ // `readPluginManifest`:
8
8
  //
9
- // - **precedência**: `manifest.json` (canônico do OkCMS) vence `package.json`
10
- // (formato npm); campos ausentes em `manifest.json` são preenchidos do npm;
11
- // - **validação**: `name`/`version` obrigatórios; `type` explícito ≠ 'plugin'
12
- // é rejeitado (ex.: theme.json/manifest de tema dentro de plugins/);
13
- // - `strict` (sync/instalação) exige mais que `main` e devolve `issues`
9
+ // - **precedence**: `manifest.json` (the OkCMS canonical) wins over
10
+ // `package.json` (npm format); fields missing from `manifest.json` are
11
+ // filled from npm;
12
+ // - **validation**: `name`/`version` required; an explicit `type` other than
13
+ // 'plugin' is rejected (e.g. a theme.json/manifest inside plugins/);
14
+ // - `strict` (sync/install) demands more than `main` and returns `issues`.
14
15
  // para o chamador decidir; o loader usa `strict = false` (leniente).
15
16
  import { readFile } from 'node:fs/promises';
16
17
  import { join } from 'node:path';
18
+ import { validatePermissions } from '@oktis-works/plugin-sdk';
17
19
  function isRecord(value) {
18
20
  return typeof value === 'object' && value !== null && !Array.isArray(value);
19
21
  }
22
+ function isString(value) {
23
+ return typeof value === 'string' && value.trim().length > 0;
24
+ }
25
+ /**
26
+ * Valida os campos do schema v2 (tudo opcional — um manifesto v1 continua
27
+ * valid). Returns the found issues; empty = valid.
28
+ */
29
+ export function validateManifestV2(merged) {
30
+ const issues = [];
31
+ const manifestVersion = merged['manifestVersion'];
32
+ if (manifestVersion !== undefined && manifestVersion !== 1 && manifestVersion !== 2) {
33
+ issues.push(`manifestVersion "${String(manifestVersion)}" invalid (expected 1 or 2)`);
34
+ }
35
+ // Permissions: unknown ones are rejected (the plugin-sdk catalog).
36
+ const permissions = merged['permissions'];
37
+ if (Array.isArray(permissions)) {
38
+ for (const unknown of validatePermissions(permissions.filter(isString))) {
39
+ issues.push(`unknown permission "${unknown}"`);
40
+ }
41
+ }
42
+ const blocks = merged['blocks'];
43
+ if (Array.isArray(blocks)) {
44
+ for (const block of blocks) {
45
+ if (!isRecord(block) || !isString(block['type']) || !isString(block['label']) || !isString(block['icon']) || !isString(block['adminComponentPath'])) {
46
+ issues.push('block missing valid type/label/icon/adminComponentPath');
47
+ }
48
+ }
49
+ }
50
+ const patterns = merged['patterns'];
51
+ if (Array.isArray(patterns)) {
52
+ for (const pattern of patterns) {
53
+ if (!isRecord(pattern) || !isString(pattern['name']) || !isString(pattern['label']) || !isString(pattern['content']) || pattern['content'].length === 0) {
54
+ issues.push('pattern missing valid name/label/content');
55
+ }
56
+ }
57
+ }
58
+ const locales = merged['locales'];
59
+ if (locales !== undefined) {
60
+ if (!Array.isArray(locales) || !locales.every(isString)) {
61
+ issues.push('locales must be an array of file paths');
62
+ }
63
+ else if (locales.some((path) => path.includes('..') || path.startsWith('/'))) {
64
+ issues.push('locales with paths outside the plugin directory');
65
+ }
66
+ }
67
+ const postTypes = merged['postTypes'];
68
+ if (Array.isArray(postTypes)) {
69
+ for (const postType of postTypes) {
70
+ if (!isRecord(postType) || !isString(postType['key']) || !isString(postType['label'])) {
71
+ issues.push('postType missing valid key/label');
72
+ }
73
+ }
74
+ }
75
+ const taxonomies = merged['taxonomies'];
76
+ if (Array.isArray(taxonomies)) {
77
+ for (const taxonomy of taxonomies) {
78
+ if (!isRecord(taxonomy) || !isString(taxonomy['key']) || !isString(taxonomy['label']) || !Array.isArray(taxonomy['postTypes'])) {
79
+ issues.push('taxonomy missing valid key/label/postTypes');
80
+ }
81
+ }
82
+ }
83
+ const scheduleJobs = merged['scheduleJobs'];
84
+ if (Array.isArray(scheduleJobs)) {
85
+ for (const job of scheduleJobs) {
86
+ if (!isRecord(job) || !isString(job['name'])) {
87
+ issues.push('scheduleJob missing a name');
88
+ continue;
89
+ }
90
+ const hasEvery = typeof job['every'] === 'number' && job['every'] > 0;
91
+ const hasCron = isString(job['cron']);
92
+ if (hasEvery === hasCron) {
93
+ issues.push(`scheduleJob "${job['name']}" requires exactly one of: every | cron`);
94
+ }
95
+ }
96
+ }
97
+ const httpPolicy = merged['httpPolicy'];
98
+ if (httpPolicy !== undefined) {
99
+ if (!isRecord(httpPolicy)) {
100
+ issues.push('httpPolicy invalid');
101
+ }
102
+ else if (httpPolicy['allowHosts'] !== undefined && !Array.isArray(httpPolicy['allowHosts'])) {
103
+ issues.push('httpPolicy.allowHosts must be an array of hosts');
104
+ }
105
+ }
106
+ const rateLimit = merged['rateLimit'];
107
+ if (rateLimit !== undefined) {
108
+ if (!isRecord(rateLimit)) {
109
+ issues.push('rateLimit invalid');
110
+ }
111
+ else if (rateLimit['rpm'] !== undefined && !(typeof rateLimit['rpm'] === 'number' && rateLimit['rpm'] > 0)) {
112
+ issues.push('rateLimit.rpm must be a positive number');
113
+ }
114
+ }
115
+ const migrations = merged['migrations'];
116
+ if (migrations !== undefined) {
117
+ if (!Array.isArray(migrations) || !migrations.every(isString)) {
118
+ issues.push('migrations must be an array of valid SQL paths');
119
+ }
120
+ else if (migrations.some((path) => path.includes('..') || path.startsWith('/'))) {
121
+ issues.push('migrations with paths outside the plugin directory');
122
+ }
123
+ }
124
+ // Declarative admin UI slots (FEAT-098 / DECI-027): identity is mandatory,
125
+ // capability is mandatory on menus (slot-level capability gating) and
126
+ // metaBoxes need a non-empty screens array. context/priority/render/mode,
127
+ // when present, must be known values (the endpoint merge applies defaults).
128
+ const admin = merged['admin'];
129
+ if (admin !== undefined) {
130
+ if (!isRecord(admin)) {
131
+ issues.push('admin must be an object');
132
+ }
133
+ else {
134
+ const checkList = (key, fields) => {
135
+ const list = admin[key];
136
+ if (list === undefined)
137
+ return;
138
+ if (!Array.isArray(list)) {
139
+ issues.push(`admin.${key} must be an array`);
140
+ return;
141
+ }
142
+ list.forEach((entry, index) => {
143
+ if (!isRecord(entry) || fields.some((field) => !isString(entry[field]) || entry[field].length === 0)) {
144
+ issues.push(`admin.${key}[${index}] missing valid ${fields.join('/')}`);
145
+ }
146
+ });
147
+ };
148
+ checkList('menuPages', ['slug', 'label', 'capability']);
149
+ checkList('submenuPages', ['parentSlug', 'slug', 'label', 'capability']);
150
+ checkList('dashboardWidgets', ['id', 'title', 'componentId']);
151
+ checkList('metaBoxes', ['id', 'title', 'componentId']);
152
+ checkList('columns', ['contentType', 'key', 'label']);
153
+ checkList('columnRenderers', ['contentType', 'key', 'componentId']);
154
+ checkList('actionLinks', ['label', 'url']);
155
+ checkList('editors', ['id', 'componentId', 'mode']);
156
+ const notices = admin['notices'];
157
+ if (notices !== undefined) {
158
+ if (!Array.isArray(notices)) {
159
+ issues.push('admin.notices must be an array');
160
+ }
161
+ else {
162
+ notices.forEach((entry, index) => {
163
+ if (!isRecord(entry) || !isString(entry['message'])) {
164
+ issues.push(`admin.notices[${index}] missing message`);
165
+ }
166
+ else if (!['info', 'success', 'warning', 'error'].includes(String(entry['level']))) {
167
+ issues.push(`admin.notices[${index}].level invalid`);
168
+ }
169
+ });
170
+ }
171
+ }
172
+ const metaBoxes = admin['metaBoxes'];
173
+ if (Array.isArray(metaBoxes)) {
174
+ metaBoxes.forEach((entry, index) => {
175
+ if (!isRecord(entry))
176
+ return;
177
+ const screens = entry['screens'];
178
+ if (!Array.isArray(screens) || screens.length === 0 || !screens.every(isString)) {
179
+ issues.push(`admin.metaBoxes[${index}].screens must be a non-empty array of strings`);
180
+ }
181
+ if (entry['context'] !== undefined && !['normal', 'side', 'advanced'].includes(String(entry['context']))) {
182
+ issues.push(`admin.metaBoxes[${index}].context invalid`);
183
+ }
184
+ if (entry['priority'] !== undefined && !['high', 'default', 'low'].includes(String(entry['priority']))) {
185
+ issues.push(`admin.metaBoxes[${index}].priority invalid`);
186
+ }
187
+ });
188
+ }
189
+ const widgets = admin['dashboardWidgets'];
190
+ if (Array.isArray(widgets)) {
191
+ widgets.forEach((entry, index) => {
192
+ if (isRecord(entry) && entry['render'] !== undefined && entry['render'] !== 'component') {
193
+ issues.push(`admin.dashboardWidgets[${index}].render invalid (expected "component")`);
194
+ }
195
+ });
196
+ }
197
+ const editors = admin['editors'];
198
+ if (Array.isArray(editors)) {
199
+ editors.forEach((entry, index) => {
200
+ if (!isRecord(entry))
201
+ return;
202
+ const screens = entry['screens'];
203
+ if (!Array.isArray(screens) || screens.length === 0 || !screens.every(isString)) {
204
+ issues.push(`admin.editors[${index}].screens must be a non-empty array of strings`);
205
+ }
206
+ if (entry['mode'] !== undefined && !['replace-body', 'below'].includes(String(entry['mode']))) {
207
+ issues.push(`admin.editors[${index}].mode invalid (expected "replace-body" or "below")`);
208
+ }
209
+ if (entry['priority'] !== undefined && !(typeof entry['priority'] === 'number')) {
210
+ issues.push(`admin.editors[${index}].priority must be a number`);
211
+ }
212
+ });
213
+ }
214
+ }
215
+ }
216
+ return issues;
217
+ }
20
218
  async function readJson(dir, file) {
21
219
  try {
22
220
  const raw = await readFile(join(dir, file), 'utf8');
@@ -28,11 +226,11 @@ async function readJson(dir, file) {
28
226
  }
29
227
  }
30
228
  /**
31
- * Lê o manifesto de um diretório de plugin com precedência única.
229
+ * Reads a plugin directory's manifest with a single precedence rule.
32
230
  *
33
- * @param dir diretório do plugin
231
+ * @param dir the plugin directory
34
232
  * @param options.strict exige `main` e valida `type === 'plugin'` quando
35
- * declarado (usado por sync/instalação/CLI)
233
+ * declared (used by sync/install/CLI)
36
234
  */
37
235
  export async function readPluginManifest(dir, options = {}) {
38
236
  const canonical = await readJson(dir, 'manifest.json');
@@ -51,12 +249,24 @@ export async function readPluginManifest(dir, options = {}) {
51
249
  issues.push('manifest sem "version"');
52
250
  const type = merged['type'];
53
251
  if (type !== undefined && type !== 'plugin') {
54
- issues.push(`type "${String(type)}" não é "plugin"`);
252
+ issues.push(`type "${String(type)}" is not "plugin"`);
55
253
  }
56
254
  const main = merged['main'];
57
255
  if (options.strict && typeof main !== 'string') {
58
256
  issues.push('manifest sem "main" (entrypoint)');
59
257
  }
258
+ // v2 schema fields: in strict mode (sync/install) they block; in the
259
+ // loader (runtime) they only warn — a plugin with a malformed v2 field
260
+ // must not prevent the other plugins from booting.
261
+ const v2Issues = validateManifestV2(merged);
262
+ if (options.strict) {
263
+ issues.push(...v2Issues);
264
+ }
265
+ else {
266
+ for (const issue of v2Issues) {
267
+ console.warn(`[manifest] ${merged['name'] ?? '?'}: ${issue}`);
268
+ }
269
+ }
60
270
  if (issues.length > 0) {
61
271
  return { manifest: null, source, issues };
62
272
  }
@@ -67,8 +277,8 @@ export async function readPluginManifest(dir, options = {}) {
67
277
  };
68
278
  }
69
279
  /**
70
- * Normaliza o manifesto para gravação no banco (mantém só campos conhecidos,
71
- * preservando campos extras legítimos do autor).
280
+ * Normalizes the manifest for database storage (keeps only known fields,
281
+ * preserving the author's legitimate extra fields).
72
282
  */
73
283
  export function normalizePluginManifest(manifest) {
74
284
  return manifest;
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
@@ -1,23 +1,23 @@
1
1
  import type { HookRegistryLike } from '@oktis-works/plugin-sdk';
2
- import type { PluginManifest } from '@oktis-works/plugin-sdk';
3
- /** Contexto disponível para o plugin em cada execução de hook. */
2
+ import type { PluginManifest, PluginFieldTypeManifest, PluginPostTypeDeclaration, PluginTaxonomyDeclaration, PluginBlockManifest, PluginPatternManifest, PluginCacheApi, PluginJobsApi, PluginJobHandler, PluginHttpApi, PluginAdminApi, PluginRolesApi, PluginAssetsApi, PluginI18nApi, PluginHealthApi, PluginHealthCheck, PluginMailApi, PluginContentApi, EnqueuedAsset, AdminExtensionsState } from '@oktis-works/plugin-sdk';
3
+ /** Context available to the plugin on every hook execution. */
4
4
  export interface PluginContext {
5
5
  tenantId: string;
6
6
  userId: string;
7
7
  requestId: string;
8
8
  api: PluginAPI;
9
9
  }
10
- /** Definição de rota registrada pelo plugin. */
10
+ /** Route definition registered by the plugin. */
11
11
  export interface RouteDefinition {
12
12
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
13
13
  path: string;
14
14
  handler: (c: any, api: PluginAPI) => Promise<Response> | Response;
15
15
  /** Middlewares opcionais (ex.: auth, rate-limit). */
16
16
  middleware?: Array<(c: any, next: () => Promise<void>) => Promise<void>>;
17
- /** Permissões exigidas para acessar esta rota. */
17
+ /** Permissions required to access this route. */
18
18
  requiredPermissions?: string[];
19
19
  }
20
- /** Configuração do tenant (para getTenant). */
20
+ /** Tenant configuration (for getTenant). */
21
21
  export interface TenantInfo {
22
22
  id: string;
23
23
  name: string;
@@ -25,20 +25,20 @@ export interface TenantInfo {
25
25
  domain?: string | null;
26
26
  subdomain?: string | null;
27
27
  }
28
- /** Info do usuário (para getUser). */
28
+ /** User info (for getUser). */
29
29
  export interface UserInfo {
30
30
  id: string;
31
31
  email: string;
32
32
  name: string;
33
33
  roles?: string[];
34
34
  }
35
- /** API exposta aos plugins — implementada pelo core e passada via factory. */
35
+ /** API exposed to plugins — implemented by the core and passed via the factory. */
36
36
  export interface PluginAPI {
37
- /** Registra hook de lifecycle (onInstall, onActivate, etc.). */
37
+ /** Registers a lifecycle hook (onInstall, onActivate, etc.). */
38
38
  registerHook(type: string, handler: (context: PluginContext, payload: unknown) => void | Promise<void>): void;
39
- /** Registra rota HTTP exposta pelo plugin. */
39
+ /** Registers an HTTP route exposed by the plugin. */
40
40
  addRoute(route: RouteDefinition): void;
41
- /** Registra campo de conteúdo customizado. */
41
+ /** Registers a custom content field. */
42
42
  addContentField(field: {
43
43
  name: string;
44
44
  type: string;
@@ -46,19 +46,49 @@ export interface PluginAPI {
46
46
  required?: boolean;
47
47
  options?: Record<string, unknown>;
48
48
  }): void;
49
- /** Lê setting do tenant (group/key). */
49
+ /** Registers a new custom field type. */
50
+ addFieldType(definition: PluginFieldTypeManifest): void;
51
+ /** Registers a Custom Post Type (permission post-types:register). */
52
+ addPostType(declaration: PluginPostTypeDeclaration): void;
53
+ /** Registers a Custom Taxonomy (permission taxonomies:register). */
54
+ addTaxonomy(declaration: PluginTaxonomyDeclaration): void;
55
+ /** Registers an editor block (permission blocks:register). Data plane: no table — lives while the plugin is active. */
56
+ registerBlock(block: PluginBlockManifest): void;
57
+ /** Registers an editor pattern (permission patterns:register). Data plane: no table — lives while the plugin is active. */
58
+ registerPattern(pattern: PluginPatternManifest): void;
59
+ /** Per-plugin cache/transient (permissions cache:read/cache:write). */
60
+ readonly cache: PluginCacheApi;
61
+ /** Per-plugin jobs/cron (permission jobs:schedule). */
62
+ readonly jobs: PluginJobsApi;
63
+ /** External HTTP protected against SSRF (permission http:outbound). */
64
+ readonly http: PluginHttpApi;
65
+ /** Slots declarativos do admin (FEAT-098 / DECI-027). */
66
+ readonly admin: PluginAdminApi;
67
+ /** Tenant role management (Item 6 — tenant scope, anti-escalation, audit). */
68
+ readonly roles: PluginRolesApi;
69
+ /** Public-site asset enqueue (Item 8 — permission assets:enqueue). */
70
+ readonly assets: PluginAssetsApi;
71
+ /** Server-side translations (Item 9 — fallback chain locale → base → en). */
72
+ readonly i18n: PluginI18nApi;
73
+ /** Health checks aggregated in /health (Item 14 — permission health:register). */
74
+ readonly health: PluginHealthApi;
75
+ /** Mail sending via the outbox (Item 12 — permission mail:send). */
76
+ readonly mail: PluginMailApi;
77
+ /** Typed content query builder (Item 22 — permission db:query). */
78
+ readonly content: PluginContentApi;
79
+ /** Reads a tenant setting (group/key). */
50
80
  getSetting(key: string, group?: string): Promise<unknown>;
51
- /** Escreve setting do tenant. */
81
+ /** Writes a tenant setting. */
52
82
  setSetting(key: string, value: unknown, group?: string): Promise<void>;
53
- /** Info do tenant atual. */
83
+ /** Current tenant info. */
54
84
  getTenant(): Promise<TenantInfo>;
55
- /** Info do usuário atual. */
85
+ /** Current user info. */
56
86
  getUser(): Promise<UserInfo>;
57
- /** Executa SQL no schema do plugin + RLS do tenant (WP8). */
87
+ /** Executes SQL with tenant RLS (WP8). */
58
88
  query(sql: string, params?: unknown[]): Promise<unknown[]>;
59
- /** Emite evento no barramento interno. */
89
+ /** Emits an event on the internal bus. */
60
90
  emit(eventType: string, payload: Record<string, unknown>): Promise<void>;
61
- /** Hooks WordPress-style (actions/filters) — mantido para compat. */
91
+ /** WordPress-style hooks (actions/filters) — kept for compatibility. */
62
92
  addAction(action: string, callback: (...args: unknown[]) => unknown, options?: {
63
93
  priority?: number;
64
94
  acceptedArgs?: number;
@@ -68,24 +98,24 @@ export interface PluginAPI {
68
98
  acceptedArgs?: number;
69
99
  }): void;
70
100
  removeAction(action: string, callback: (...args: unknown[]) => unknown, priority?: number): boolean;
71
- removeFilter(filter: string, callback: (...args: unknown[]) => unknown, priority?: number): boolean;
101
+ removeFilter(filter: string, callback: (value: unknown, ...args: unknown[]) => unknown, priority?: number): boolean;
72
102
  hasAction(action: string, callback?: (...args: unknown[]) => unknown): boolean;
73
103
  hasFilter(filter: string, callback?: (...args: unknown[]) => unknown): boolean;
74
104
  didAction(action: string): number;
75
105
  currentHook(): string | null;
76
106
  }
77
- /** Dependências que o core deve prover para criar a API real. */
107
+ /** Dependencies the core must provide to create the real API. */
78
108
  export interface PluginApiDependencies {
79
- /** Registry de hooks do escopo (tenant ou platform). */
109
+ /** Hook registry of the scope (tenant or platform). */
80
110
  hooks: HookRegistryLike;
81
- /** Manifesto do plugin (para validar permissões no query). */
111
+ /** Plugin manifest (to validate permissions on query). */
82
112
  manifest: PluginManifest;
83
- /** Serviço de settings (get/set por grupo/key). */
113
+ /** Settings service (get/set by group/key). */
84
114
  settings: {
85
115
  get(key: string, group?: string): Promise<unknown>;
86
116
  set(key: string, value: unknown, group?: string): Promise<void>;
87
117
  };
88
- /** Bus de eventos interno. */
118
+ /** Internal event bus. */
89
119
  eventBus: {
90
120
  emit(event: {
91
121
  id: string;
@@ -98,23 +128,23 @@ export interface PluginApiDependencies {
98
128
  createdAt: Date;
99
129
  }): Promise<void>;
100
130
  };
101
- /** Conexão PostgreSQL com RLS já configurado para o tenant. */
131
+ /** PostgreSQL connection with RLS already configured for the tenant. */
102
132
  db: {
103
133
  query(sql: string, params?: unknown[]): Promise<unknown[]>;
104
134
  };
105
- /** Resolvedor do tenantId atual (ALS). */
135
+ /** Current tenantId resolver (ALS). */
106
136
  getTenantId: () => string | null;
107
- /** Resolvedor do userId atual (ALS). */
137
+ /** Current userId resolver (ALS). */
108
138
  getUserId: () => string | null;
109
- /** Resolvedor do requestId atual (ALS). */
139
+ /** Current requestId resolver (ALS). */
110
140
  getRequestId: () => string | null;
111
- /** Consulta tenant por id (para getTenant). */
141
+ /** Tenant lookup by id (for getTenant). */
112
142
  getTenantById: (id: string) => Promise<TenantInfo | null>;
113
- /** Consulta usuário por id (para getUser). */
143
+ /** User lookup by id (for getUser). */
114
144
  getUserById: (id: string) => Promise<UserInfo | null>;
115
- /** Registra rotas do plugin (o core monta no router da API). */
145
+ /** Registers plugin routes (the core mounts them on the API router). */
116
146
  registerRoutes: (routes: RouteDefinition[]) => void;
117
- /** Registra campos de conteúdo do plugin (o core expõe via field-groups). */
147
+ /** Registers plugin content fields (the core exposes them via field groups). */
118
148
  registerContentFields: (fields: Array<{
119
149
  name: string;
120
150
  type: string;
@@ -122,19 +152,113 @@ export interface PluginApiDependencies {
122
152
  required?: boolean;
123
153
  options?: Record<string, unknown>;
124
154
  }>) => void;
125
- /** Permissões concedidas ao plugin (policy já resolvida). */
155
+ /** Registers plugin field types (the core exposes them via the registry). */
156
+ registerFieldTypes: (fieldTypes: PluginFieldTypeManifest[]) => void;
157
+ /** Registers plugin Custom Post Types (the core persists via postTypeRegistry). */
158
+ registerPostTypes?: (postTypes: Array<PluginPostTypeDeclaration & {
159
+ pluginName: string;
160
+ }>) => void;
161
+ /** Registers plugin Custom Taxonomies (the core persists via taxonomyService). */
162
+ registerTaxonomies?: (taxonomies: Array<PluginTaxonomyDeclaration & {
163
+ pluginName: string;
164
+ }>) => void;
165
+ /**
166
+ * Core cache backend (Redis/memory) — RAW operations, no namespace (the
167
+ * plugin/tenant namespace and tags belong to the PluginAPI).
168
+ * Absent → per-process memory fallback (dev/legacy, never throws).
169
+ */
170
+ cache?: {
171
+ get<T>(key: string): Promise<T | null>;
172
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
173
+ del(key: string): Promise<void>;
174
+ };
175
+ /**
176
+ * Core jobs backend (`plugins` queue). Absent → schedule/enqueue/cancel
177
+ * return false (optional queue, never throws — degradation A3).
178
+ */
179
+ jobs?: {
180
+ schedule(jobName: string, spec: {
181
+ every?: number;
182
+ cron?: string;
183
+ }, ctx: {
184
+ pluginName: string;
185
+ tenantId: string | null;
186
+ }): Promise<boolean>;
187
+ cancel(jobName: string, ctx: {
188
+ pluginName: string;
189
+ tenantId: string | null;
190
+ }): Promise<boolean>;
191
+ enqueue(jobName: string, payload: Record<string, unknown>, ctx: {
192
+ pluginName: string;
193
+ tenantId: string | null;
194
+ }): Promise<boolean>;
195
+ };
196
+ /** Permissions granted to the plugin (already-resolved policy). */
126
197
  allowedPermissions: string[];
198
+ /**
199
+ * Backend de roles do core (Item 6 — persiste + audita com anti-escalada).
200
+ * Absent → api.roles throws a clear error (backend not wired).
201
+ */
202
+ roles?: {
203
+ add(input: {
204
+ tenantId: string;
205
+ pluginName: string;
206
+ name: string;
207
+ slug?: string;
208
+ permissions?: string[];
209
+ }): Promise<{
210
+ id: string;
211
+ name: string;
212
+ slug: string;
213
+ permissions: string[];
214
+ }>;
215
+ remove(input: {
216
+ tenantId: string;
217
+ pluginName: string;
218
+ slug: string;
219
+ }): Promise<boolean>;
220
+ addPermission(input: {
221
+ tenantId: string;
222
+ pluginName: string;
223
+ slug: string;
224
+ permission: string;
225
+ }): Promise<boolean>;
226
+ };
227
+ /**
228
+ * Backend de mail do core (Item 12 — outbox + rate limit + audit).
229
+ * Absent → api.mail.send returns false (queue unavailable, like jobs).
230
+ */
231
+ mail?: {
232
+ send(input: {
233
+ tenantId: string | null;
234
+ pluginName: string;
235
+ to: string;
236
+ subject: string;
237
+ html?: string;
238
+ text?: string;
239
+ template?: string;
240
+ params?: Record<string, unknown>;
241
+ }): Promise<boolean>;
242
+ };
243
+ /**
244
+ * Audit backend (Item 18 — sensitive plugin operations → audit_log).
245
+ * Ausente → sem auditoria (degrada silenciosamente, nunca bloqueia).
246
+ */
247
+ audit?: {
248
+ record(entry: {
249
+ tenantId?: string | null;
250
+ action: string;
251
+ resourceType: string;
252
+ resourceId?: string;
253
+ changes?: Record<string, unknown>;
254
+ }): Promise<void>;
255
+ };
127
256
  }
128
- /**
129
- * Cria a PluginAPI real a partir das dependências do core.
130
- * Chamado pelo core no bootstrap (não pelo plugin-runtime diretamente).
131
- * Retorna { api: PluginAPI, internal: PluginApiInternal } para separar a API pública dos detalhes internos.
132
- */
133
257
  export declare function createPluginApi(deps: PluginApiDependencies): {
134
258
  api: PluginAPI;
135
259
  internal: PluginApiInternal;
136
260
  };
137
- /** Tipo para o core acessar as rotas/campos registrados internamente. */
261
+ /** Type for the core to access internally registered routes/fields. */
138
262
  export interface PluginApiInternal {
139
263
  getRoutes: () => RouteDefinition[];
140
264
  getFields: () => Array<{
@@ -144,5 +268,34 @@ export interface PluginApiInternal {
144
268
  required?: boolean;
145
269
  options?: Record<string, unknown>;
146
270
  }>;
271
+ getFieldTypes: () => Array<PluginFieldTypeManifest & {
272
+ pluginName: string;
273
+ isPluginType: true;
274
+ }>;
275
+ getPostTypes: () => Array<PluginPostTypeDeclaration & {
276
+ pluginName: string;
277
+ }>;
278
+ getTaxonomies: () => Array<PluginTaxonomyDeclaration & {
279
+ pluginName: string;
280
+ }>;
281
+ /** Job handlers declared via api.jobs.on (dispatched by the worker). */
282
+ getJobHandlers: () => Map<string, PluginJobHandler>;
283
+ /** Declarative slots registered at runtime via api.admin.*. */
284
+ getAdminState: () => AdminExtensionsState;
285
+ /** Blocos do editor registrados em runtime via api.registerBlock. */
286
+ getBlocks: () => Array<PluginBlockManifest & {
287
+ pluginName: string;
288
+ }>;
289
+ /** Patterns do editor registrados em runtime via api.registerPattern. */
290
+ getPatterns: () => Array<PluginPatternManifest & {
291
+ pluginName: string;
292
+ }>;
293
+ /** Assets enfileirados em runtime via api.assets (Item 8). */
294
+ getEnqueuedAssets: () => EnqueuedAsset[];
295
+ /** Health checks registrados em runtime via api.health (Item 14). */
296
+ getHealthChecks: () => Array<{
297
+ name: string;
298
+ check: PluginHealthCheck;
299
+ }>;
147
300
  }
148
301
  //# sourceMappingURL=plugin-api.d.ts.map