@oktis-works/core 0.5.9 → 0.5.11

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.
@@ -2,29 +2,303 @@
2
2
  //
3
3
  // O PLUGIN.md promete que `register(registry)` é chamado quando o plugin é
4
4
  // carregado — aqui o core cumpre isso para todos os processos (API, web,
5
- // worker, dev): lê os plugins com status ACTIVATED/RUNNING no banco, importa
6
- // o entrypoint e registra os hooks no registry compartilhado.
5
+ // worker, dev). Dois escopos:
6
+ //
7
+ // - **platform** (`syncEnabledPlugins`): plugins `tenant_id IS NULL`,
8
+ // habilitados globalmente → registry platform, carregado no boot;
9
+ // - **tenant** (`ensureTenantPluginsLoaded`): plugins vinculados em
10
+ // `plugin_tenants` (status ENABLED) → registry do tenant, carregado sob
11
+ // demanda na primeira requisição daquele tenant (cache com TTL + LRU).
7
12
  //
8
13
  // Nunca lança: falha de banco, diretório ausente ou plugin quebrado são
9
- // reportadas no resultado, sem derrubar o boot.
10
- import { bootstrapPlugins } from '@oktis-works/plugin-runtime';
14
+ // reportadas no resultado (e persistidas em `plugins.error`), sem derrubar o
15
+ // boot. Falhas ficam visíveis em `getPluginsRuntimeState()` (rota
16
+ // `/api/v1/plugins/runtime` + badge no admin) — não são silenciadas.
17
+ import { bootstrapPlugins, getHookRegistryStore, unloadTenant, getLoadedPluginRoutes, } from '@oktis-works/plugin-runtime';
11
18
  import { getConnection } from '@oktis-works/database';
19
+ import { loadConfig } from '@oktis-works/config';
20
+ import { resolvePluginPermissionPolicy } from '@oktis-works/validation';
12
21
  import { resolveExtensionDirectory } from '../extensions/project-directories.js';
22
+ import { settingsService } from '../settings/service.js';
23
+ import { getEventBus } from '../events/bus.js';
24
+ import { tenantService } from '../tenant/service.js';
25
+ import { userService } from '../user/service.js';
26
+ import { fieldGroupService } from '../fields/service.js';
27
+ import { getCurrentTenantIdSync, getCurrentUserIdSync, getCurrentRequestIdSync } from '../tenant/context.js';
28
+ const pluginRoutesRegistry = new Map();
29
+ /** Registra rotas de um plugin (chamado durante bootstrap). */
30
+ export function registerPluginRoutes(pluginName, routes) {
31
+ if (routes.length === 0)
32
+ return;
33
+ pluginRoutesRegistry.set(pluginName, { pluginName, routes });
34
+ }
35
+ /** Remove rotas de um plugin (quando desativado/desinstalado). */
36
+ export function unregisterPluginRoutes(pluginName) {
37
+ return pluginRoutesRegistry.delete(pluginName);
38
+ }
39
+ /** Obtém todas as rotas registradas para montagem no router da API. */
40
+ export function getRegisteredPluginRoutes() {
41
+ return [...pluginRoutesRegistry.values()];
42
+ }
43
+ /** Estados por escopo — ordem de iteração = LRU. */
44
+ const states = new Map();
45
+ const inflight = new Map();
46
+ const PLATFORM_KEY = 'platform';
47
+ function scopeKey(tenantId) {
48
+ return tenantId ? `tenant:${tenantId}` : PLATFORM_KEY;
49
+ }
50
+ function createApiDeps(tenantId) {
51
+ return {
52
+ settings: {
53
+ get: settingsService.get.bind(settingsService),
54
+ set: async (key, value, group) => {
55
+ await settingsService.set(key, value, group);
56
+ },
57
+ },
58
+ eventBus: {
59
+ emit: async (event) => {
60
+ await getEventBus().emit(event);
61
+ },
62
+ },
63
+ db: {
64
+ query: async (sql, params) => {
65
+ const conn = getConnection();
66
+ return conn.unsafe(sql, params ?? []);
67
+ },
68
+ },
69
+ getTenantId: () => tenantId ?? getCurrentTenantIdSync(),
70
+ getUserId: () => getCurrentUserIdSync(),
71
+ getRequestId: () => getCurrentRequestIdSync(),
72
+ getTenantById: async (id) => {
73
+ const tenant = await tenantService.getById(id);
74
+ return tenant ? { id: tenant.id, name: tenant.name, slug: tenant.slug, domain: tenant.domain, subdomain: tenant.subdomain } : null;
75
+ },
76
+ getUserById: async (id) => {
77
+ const user = await userService.getById(id);
78
+ return user ? { id: user.id, email: user.email, name: user.name, roles: user.roles } : null;
79
+ },
80
+ registerRoutes: (routes) => {
81
+ // As rotas registradas aqui são coletadas no bootstrap pelo próprio
82
+ // PluginAPI (getLoadedPluginRoutes) — neste ponto só registramos o log.
83
+ console.debug(`[PluginAPI] ${routes.length} rota(s) registrada(s) — será coletada no bootstrap`);
84
+ },
85
+ registerContentFields: async (fields) => {
86
+ // Guard explícito: com noUncheckedIndexedAccess, fields[0] é T | undefined
87
+ // mesmo com o length check acima — o desctructuring com verificação
88
+ // deixa o narrowing para o TS e mantém a mesma semântica.
89
+ const firstField = fields[0];
90
+ if (!firstField)
91
+ return;
92
+ try {
93
+ // Cria/atualiza field group do plugin
94
+ const groupKey = `plugin_${firstField.name.split('_')[0]}_fields`; // prefixo baseado no primeiro campo
95
+ const existing = await fieldGroupService.getByKey(groupKey);
96
+ const fieldInputs = fields.map((f, idx) => ({
97
+ type: f.type,
98
+ name: f.name,
99
+ key: f.name,
100
+ label: f.label,
101
+ required: f.required ?? false,
102
+ config: f.options ?? {},
103
+ sortOrder: idx,
104
+ }));
105
+ if (existing) {
106
+ await fieldGroupService.update(existing.id, { fields: fieldInputs });
107
+ }
108
+ else {
109
+ await fieldGroupService.create({
110
+ title: `Campos do Plugin`,
111
+ key: groupKey,
112
+ locationRules: [],
113
+ position: 'normal',
114
+ displayStyle: 'standard',
115
+ active: true,
116
+ fields: fieldInputs,
117
+ });
118
+ }
119
+ console.debug(`[PluginAPI] ${fields.length} campo(s) de conteúdo registrado(s) no field group "${groupKey}"`);
120
+ }
121
+ catch (error) {
122
+ console.error('[PluginAPI] Falha ao registrar campos de conteúdo:', error);
123
+ }
124
+ },
125
+ };
126
+ }
127
+ function runtimeOptions(tenantId) {
128
+ const config = loadConfig();
129
+ const policy = resolvePluginPermissionPolicy(config.plugins.allowedPermissions.length > 0 ? config.plugins.allowedPermissions : null);
130
+ // Resolve o tenantId atual
131
+ const currentTenantId = tenantId ?? getCurrentTenantIdSync();
132
+ return {
133
+ pluginsDir: resolveExtensionDirectory('plugin'),
134
+ sql: getConnection(),
135
+ tenantId: tenantId ?? null,
136
+ permissionPolicy: policy.allowed,
137
+ hookTimeoutMs: config.plugins.hookTimeoutMs,
138
+ // Deps reais da API do plugin
139
+ apiDeps: createApiDeps(currentTenantId),
140
+ };
141
+ }
13
142
  /**
14
- * Sincroniza o registry de hooks com os plugins habilitados no banco.
15
- * Idempotente: pode ser chamada no boot e depois de ativar/desativar um
16
- * plugin pela API (reflete no processo na hora; web/worker no próximo restart).
143
+ * Persiste o resultado da carga em `plugins.error`/`status`:
144
+ * - falha nova → `status = LOAD_FAILED` + mensagem;
145
+ * - sucesso depois de falha → `ACTIVATED` + `error = NULL`.
146
+ * Só grava quando o estado mudou (nada de UPDATE por request). Nunca lança.
17
147
  */
18
- export async function syncEnabledPlugins() {
148
+ async function persistScopeResult(state) {
149
+ const sql = getConnection();
150
+ const previous = state.errors;
151
+ const current = new Map(state.result.failed.map((failure) => [failure.name, failure.error]));
19
152
  try {
20
- return await bootstrapPlugins({
21
- pluginsDir: resolveExtensionDirectory('plugin'),
22
- sql: getConnection(),
23
- });
153
+ for (const [name, error] of current) {
154
+ if (previous.get(name) === error)
155
+ continue;
156
+ await sql.unsafe(`UPDATE plugins SET status = 'LOAD_FAILED', error = $1, updated_at = NOW()
157
+ WHERE name = $2 AND status IN ('ACTIVATED', 'RUNNING', 'LOAD_FAILED')`, [error, name]);
158
+ }
159
+ // Falha resolvida nesta sync → devolve ACTIVATED e limpa a mensagem
160
+ for (const name of previous.keys()) {
161
+ if (current.has(name))
162
+ continue;
163
+ await sql.unsafe(`UPDATE plugins SET status = 'ACTIVATED', error = NULL, updated_at = NOW()
164
+ WHERE name = $1 AND status = 'LOAD_FAILED'`, [name]);
165
+ }
166
+ }
167
+ catch {
168
+ // banco indisponível não pode derrubar a carga — visibilidade fica no estado em memória
169
+ }
170
+ }
171
+ async function syncScope(tenantId, force) {
172
+ const key = scopeKey(tenantId);
173
+ const config = loadConfig();
174
+ const ttlMs = config.plugins.tenantLoadTtlMs;
175
+ const cached = states.get(key);
176
+ if (!force && cached && Date.now() - cached.loadedAt < ttlMs) {
177
+ // LRU: acesso recente sobe na ordem
178
+ states.delete(key);
179
+ states.set(key, cached);
180
+ return cached.result;
181
+ }
182
+ const running = inflight.get(key);
183
+ if (running)
184
+ return running;
185
+ const promise = (async () => {
186
+ try {
187
+ const result = await bootstrapPlugins(runtimeOptions(tenantId));
188
+ // Coleta rotas registradas pelos plugins neste escopo
189
+ const scopeKey = key; // 'platform' ou 'tenant:<id>'
190
+ const pluginRoutes = getLoadedPluginRoutes(scopeKey);
191
+ for (const { pluginName, routes } of pluginRoutes) {
192
+ registerPluginRoutes(pluginName, routes);
193
+ }
194
+ // Remove rotas de plugins que foram descarregados (unloaded)
195
+ for (const pluginName of result.unloaded) {
196
+ unregisterPluginRoutes(pluginName);
197
+ }
198
+ const previousErrors = states.get(key)?.errors ?? new Map();
199
+ const state = {
200
+ key,
201
+ tenantId,
202
+ loadedAt: Date.now(),
203
+ result,
204
+ errors: previousErrors,
205
+ };
206
+ states.set(key, state);
207
+ await persistScopeResult(state);
208
+ state.errors = new Map(result.failed.map((failure) => [failure.name, failure.error]));
209
+ evictOldTenants(config.plugins.maxLoadedTenants);
210
+ return result;
211
+ }
212
+ catch (error) {
213
+ console.warn(`[plugins] sync indisponível (${key}): ${error instanceof Error ? error.message : String(error)}`);
214
+ const fallback = { enabled: [], loaded: [], unloaded: [], failed: [] };
215
+ if (!states.has(key)) {
216
+ states.set(key, { key, tenantId, loadedAt: 0, result: fallback, errors: new Map() });
217
+ }
218
+ return fallback;
219
+ }
220
+ finally {
221
+ inflight.delete(key);
222
+ }
223
+ })();
224
+ inflight.set(key, promise);
225
+ return promise;
226
+ }
227
+ /** Evita crescer sem limite: descarta tenants com carga mais antiga. */
228
+ function evictOldTenants(maxTenants) {
229
+ if (states.size <= maxTenants)
230
+ return;
231
+ for (const [key, state] of [...states.entries()]) {
232
+ if (states.size <= maxTenants)
233
+ break;
234
+ if (state.tenantId === null)
235
+ continue; // platform nunca sai
236
+ states.delete(key);
237
+ unloadTenant(state.tenantId);
238
+ getHookRegistryStore().invalidateTenant(state.tenantId);
239
+ }
240
+ }
241
+ /**
242
+ * Sincroniza o registry **platform** com os plugins habilitados no banco.
243
+ * Force implícito: é a chamada explícita de boot/ativação — reflete o banco
244
+ * na hora. Idempotente e nunca lança.
245
+ */
246
+ export async function syncEnabledPlugins(options = {}) {
247
+ try {
248
+ return await syncScope(null, options.force ?? true);
24
249
  }
25
250
  catch (error) {
26
251
  console.warn(`[plugins] sync indisponível: ${error instanceof Error ? error.message : String(error)}`);
27
252
  return { enabled: [], loaded: [], unloaded: [], failed: [] };
28
253
  }
29
254
  }
255
+ /**
256
+ * Garante que os plugins do tenant estão carregados no registry dele.
257
+ * Chamado sob demanda (middleware/API, web, worker) — com cache de TTL para
258
+ * não bater no banco a cada requisição. Nunca lança.
259
+ */
260
+ export async function ensureTenantPluginsLoaded(tenantId, options = {}) {
261
+ if (!tenantId)
262
+ return { enabled: [], loaded: [], unloaded: [], failed: [] };
263
+ try {
264
+ return await syncScope(tenantId, options.force ?? false);
265
+ }
266
+ catch (error) {
267
+ console.warn(`[plugins] sync do tenant indisponível: ${error instanceof Error ? error.message : String(error)}`);
268
+ return { enabled: [], loaded: [], unloaded: [], failed: [] };
269
+ }
270
+ }
271
+ /**
272
+ * Invalida o cache/registry de um tenant (após ativar/desativar vínculo,
273
+ * desinstalar ou mudar permissões). A próxima requisição do tenant recarrega.
274
+ */
275
+ export function invalidateTenantPlugins(tenantId) {
276
+ if (!tenantId)
277
+ return;
278
+ const key = scopeKey(tenantId);
279
+ states.delete(key);
280
+ inflight.delete(key);
281
+ unloadTenant(tenantId);
282
+ getHookRegistryStore().invalidateTenant(tenantId);
283
+ }
284
+ /** Invalida o escopo platform (após mudanças globais). */
285
+ export function invalidatePlatformPlugins() {
286
+ states.delete(PLATFORM_KEY);
287
+ inflight.delete(PLATFORM_KEY);
288
+ }
289
+ /** Estado de carga por escopo — superfície de observabilidade (WP2). */
290
+ export function getPluginsRuntimeState() {
291
+ return {
292
+ generatedAt: new Date().toISOString(),
293
+ scopes: [...states.values()].map((state) => ({
294
+ scope: state.key,
295
+ tenantId: state.tenantId,
296
+ loadedAt: new Date(state.loadedAt).toISOString(),
297
+ enabled: state.result.enabled,
298
+ loaded: state.result.loaded,
299
+ unloaded: state.result.unloaded,
300
+ failed: state.result.failed,
301
+ })),
302
+ };
303
+ }
30
304
  //# sourceMappingURL=load.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/plugin/load.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,6EAA6E;AAC7E,8DAA8D;AAC9D,EAAE;AACF,wEAAwE;AACxE,gDAAgD;AAEhD,OAAO,EAAE,gBAAgB,EAA8B,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,gBAAgB,CAAC;YAC5B,UAAU,EAAE,yBAAyB,CAAC,QAAQ,CAAC;YAC/C,GAAG,EAAE,aAAa,EAAE;SACrB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CACV,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACzF,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/plugin/load.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,8BAA8B;AAC9B,EAAE;AACF,wEAAwE;AACxE,sEAAsE;AACtE,sEAAsE;AACtE,4EAA4E;AAC5E,2EAA2E;AAC3E,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,kEAAkE;AAClE,qEAAqE;AAErE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,GAGtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAyB7G,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEjE,+DAA+D;AAC/D,MAAM,UAAU,oBAAoB,CAAC,UAAkB,EAAE,MAAyB;IAChF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAChC,oBAAoB,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AACjD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,yBAAyB;IACvC,OAAO,CAAC,GAAG,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC;AAWD,oDAAoD;AACpD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0C,CAAC;AAEnE,MAAM,YAAY,GAAG,UAAU,CAAC;AAEhC,SAAS,QAAQ,CAAC,QAAwB;IACxC,OAAO,QAAQ,CAAC,CAAC,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,QAAuB;IAC5C,OAAO;QACL,QAAQ,EAAE;YACR,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC;YAC9C,GAAG,EAAE,KAAK,EAAE,GAAW,EAAE,KAAc,EAAE,KAAc,EAAE,EAAE;gBACzD,MAAM,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAC/C,CAAC;SACF;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,KAAK,EAAE,KAAyK,EAAE,EAAE;gBACxL,MAAM,WAAW,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;SACF;QACD,EAAE,EAAE;YACF,KAAK,EAAE,KAAK,EAAE,GAAW,EAAE,MAAkB,EAAE,EAAE;gBAC/C,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC;SACF;QACD,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,IAAI,sBAAsB,EAAE;QACvD,SAAS,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE;QACvC,YAAY,EAAE,GAAG,EAAE,CAAC,uBAAuB,EAAE;QAC7C,aAAa,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE;YAClC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC/C,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACrI,CAAC;QACD,WAAW,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE;YAChC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9F,CAAC;QACD,cAAc,EAAE,CAAC,MAAyB,EAAE,EAAE;YAC5C,oEAAoE;YACpE,wEAAwE;YACxE,OAAO,CAAC,KAAK,CAAC,eAAe,MAAM,CAAC,MAAM,qDAAqD,CAAC,CAAC;QACnG,CAAC;QACD,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACtC,2EAA2E;YAC3E,oEAAoE;YACpE,0DAA0D;YAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,UAAU;gBAAE,OAAO;YACxB,IAAI,CAAC;gBACH,sCAAsC;gBACtC,MAAM,QAAQ,GAAG,UAAU,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,oCAAoC;gBACvG,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC5D,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;oBAC1C,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,GAAG,EAAE,CAAC,CAAC,IAAI;oBACX,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,KAAK;oBAC7B,MAAM,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;oBACvB,SAAS,EAAE,GAAG;iBACf,CAAC,CAAC,CAAC;gBACJ,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;gBACvE,CAAC;qBAAM,CAAC;oBACN,MAAM,iBAAiB,CAAC,MAAM,CAAC;wBAC7B,KAAK,EAAE,kBAAkB;wBACzB,GAAG,EAAE,QAAQ;wBACb,aAAa,EAAE,EAAE;wBACjB,QAAQ,EAAE,QAAQ;wBAClB,YAAY,EAAE,UAAU;wBACxB,MAAM,EAAE,IAAI;wBACZ,MAAM,EAAE,WAAW;qBACpB,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,eAAe,MAAM,CAAC,MAAM,uDAAuD,QAAQ,GAAG,CAAC,CAAC;YAChH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,KAAK,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,QAAwB;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,6BAA6B,CAC1C,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CACxF,CAAC;IAEF,2BAA2B;IAC3B,MAAM,eAAe,GAAG,QAAQ,IAAI,sBAAsB,EAAE,CAAC;IAE7D,OAAO;QACL,UAAU,EAAE,yBAAyB,CAAC,QAAQ,CAAC;QAC/C,GAAG,EAAE,aAAa,EAAE;QACpB,QAAQ,EAAE,QAAQ,IAAI,IAAI;QAC1B,gBAAgB,EAAE,MAAM,CAAC,OAAO;QAChC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa;QAC3C,8BAA8B;QAC9B,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC;KACxC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,kBAAkB,CAAC,KAAiB;IACjD,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE7F,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK;gBAAE,SAAS;YAC3C,MAAM,GAAG,CAAC,MAAM,CACd;+EACuE,EACvE,CAAC,KAAK,EAAE,IAAI,CAAC,CACd,CAAC;QACJ,CAAC;QAED,oEAAoE;QACpE,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YACnC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChC,MAAM,GAAG,CAAC,MAAM,CACd;oDAC4C,EAC5C,CAAC,IAAI,CAAC,CACP,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wFAAwF;IAC1F,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,QAAuB,EAAE,KAAc;IAC9D,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG,KAAK,EAAE,CAAC;QAC7D,oCAAoC;QACpC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAoC,EAAE;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;YAEhE,sDAAsD;YACtD,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,8BAA8B;YACpD,MAAM,YAAY,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YACrD,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;gBAClD,oBAAoB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YAED,6DAA6D;YAC7D,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACzC,sBAAsB,CAAC,UAAU,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,IAAI,GAAG,EAAkB,CAAC;YAC5E,MAAM,KAAK,GAAe;gBACxB,GAAG;gBACH,QAAQ;gBACR,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;gBACpB,MAAM;gBACN,MAAM,EAAE,cAAc;aACvB,CAAC;YACF,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACvB,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAChC,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtF,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACjD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,gCAAgC,GAAG,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAClG,CAAC;YACF,MAAM,QAAQ,GAA0B,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAC9F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YACvF,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,wEAAwE;AACxE,SAAS,eAAe,CAAC,UAAkB;IACzC,IAAI,MAAM,CAAC,IAAI,IAAI,UAAU;QAAE,OAAO;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjD,IAAI,MAAM,CAAC,IAAI,IAAI,UAAU;YAAE,MAAM;QACrC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,SAAS,CAAC,qBAAqB;QAC5D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,oBAAoB,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IACxE,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CACV,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACzF,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,QAAgB,EAChB,UAA+B,EAAE;IAEjC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC5E,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CACV,0CAA0C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnG,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,oBAAoB,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,yBAAyB;IACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3C,KAAK,EAAE,KAAK,CAAC,GAAG;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE;YAChD,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;YAC7B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;YAC3B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;YAC/B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;SAC5B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -5,20 +5,46 @@ export interface PluginDependencyInput {
5
5
  versionRange?: string;
6
6
  optional?: boolean;
7
7
  }
8
+ /** Vínculo plugin ↔ tenant (quem tem o plugin ligado). */
9
+ export interface PluginTenantLink {
10
+ id: string;
11
+ plugin_id: string;
12
+ tenant_id: string;
13
+ status: 'ENABLED' | 'DISABLED';
14
+ error?: string | null;
15
+ enabled_at?: string | null;
16
+ disabled_at?: string | null;
17
+ }
8
18
  export declare class PluginService {
9
19
  /**
10
- * O filesystem é a fonte de verdade da instalação. Esta sincronização
11
- * cadastra manifests que chegaram em plugins/ via CLI, Git ou deploy e
12
- * nunca altera um plugin já ativado/desativado.
20
+ * O filesystem é a fonte da INSTALAÇÃO. Esta sincronização cadastra manifests
21
+ * que chegaram em plugins/ via CLI, Git ou deploy:
22
+ *
23
+ * - fonte única de leitura (`readPluginManifest`) — `manifest.json`
24
+ * canônico, `package.json` como fallback npm;
25
+ * - `type !== 'plugin'` (ex.: tema dentro de plugins/) é ignorado;
26
+ * - permissão fora do catálogo → row `QUARANTINED` com erro visível;
27
+ * - artefato que sumiu do disco → `MISSING` (vínculos são preservados);
28
+ * - nunca altera um plugin já ativado/desativado (ativação = vínculo).
29
+ *
30
+ * O artefato é platform: `tenant_id` fica NULL — quem tem o plugin é a linha
31
+ * em `plugin_tenants`.
13
32
  */
14
- syncFromDirectory(tenantId?: string): Promise<Plugin[]>;
33
+ syncFromDirectory(_tenantId?: string): Promise<Plugin[]>;
15
34
  /**
16
- * RULE-tenant-plugin-scope: retorna plugins platform (globais) + os do tenant informado.
17
- * Sem tenantId, retorna apenas os de escopo platform.
35
+ * Lista os artefatos com o estado de vínculo do tenant informado:
36
+ * `enabled` = plugin_tenants.status = 'ENABLED' para aquele tenant.
37
+ * Sem tenantId (visão plataforma), `enabled` vem como false.
18
38
  */
19
- list(tenantId?: string): Promise<Plugin[]>;
39
+ list(tenantId?: string): Promise<Array<Plugin & {
40
+ enabled?: boolean;
41
+ }>>;
20
42
  getById(id: string): Promise<Plugin | null>;
21
43
  getByName(name: string): Promise<Plugin | null>;
44
+ /** Vínculos de um plugin (todos os tenants — leitura exigindo contexto do dono ou platform). */
45
+ listLinks(pluginId: string): Promise<PluginTenantLink[]>;
46
+ /** Plugins habilitados de um tenant (usado pelo bootstrap por tenant). */
47
+ listEnabledForTenant(tenantId: string): Promise<Plugin[]>;
22
48
  install(input: {
23
49
  name: string;
24
50
  version: string;
@@ -29,8 +55,17 @@ export declare class PluginService {
29
55
  migrations?: MigrationFile[];
30
56
  tenantId?: string | null;
31
57
  }): Promise<Plugin>;
32
- activate(id: string): Promise<Plugin | null>;
33
- deactivate(id: string): Promise<Plugin | null>;
58
+ /**
59
+ * Ativa (vincula) o plugin a um tenant: `plugin_tenants.status = ENABLED`.
60
+ * Só SUPER_ADMIN (RBAC) chega aqui; a transação precisa estar no contexto do
61
+ * tenant alvo (RLS de plugin_tenants).
62
+ */
63
+ activate(id: string, tenantId: string): Promise<Plugin | null>;
64
+ /**
65
+ * Desativa (desvincula) o plugin de um tenant: DISABLED + notificação dos
66
+ * dependentes habilitados naquele tenant.
67
+ */
68
+ deactivate(id: string, tenantId: string): Promise<Plugin | null>;
34
69
  uninstall(id: string): Promise<boolean>;
35
70
  updateConfig(id: string, config: Record<string, unknown>): Promise<Plugin | null>;
36
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/plugin/service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAOjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB;;;;OAIG;IACG,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoD7D;;;OAGG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAW1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAM3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAM/C,OAAO,CAAC,KAAK,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAC;QACvC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,OAAO,CAAC,MAAM,CAAC;IAqEb,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmC5C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+C9C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgCvC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAgBxF;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/plugin/service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,qBAAa,aAAa;IACxB;;;;;;;;;;;;;OAaG;IACG,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgG9D;;;;OAIG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAmBvE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAM3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAMrD,gGAAgG;IAC1F,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAS9D,0EAA0E;IACpE,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAYzD,OAAO,CAAC,KAAK,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAC;QACvC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,OAAO,CAAC,MAAM,CAAC;IA+EnB;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiFpE;;;OAGG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwDhE,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiCvC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAgBxF;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}