@open-mercato/shared 0.7.1-develop.7137.1.26575786c0 → 0.7.1-develop.7148.1.3076e5ccf7
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.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +4 -2
- package/dist/lib/bootstrap/factory.js +1 -1
- package/dist/lib/bootstrap/factory.js.map +2 -2
- package/dist/lib/query/migration-reindex.js +45 -0
- package/dist/lib/query/migration-reindex.js.map +7 -0
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/dist/modules/overrides.js +69 -9
- package/dist/modules/overrides.js.map +2 -2
- package/dist/modules/widgets/injection-loader.js +2 -2
- package/dist/modules/widgets/injection-loader.js.map +2 -2
- package/package.json +2 -2
- package/src/lib/bootstrap/__tests__/factory.test.ts +4 -1
- package/src/lib/bootstrap/factory.ts +1 -1
- package/src/lib/query/__tests__/migration-reindex.test.ts +80 -0
- package/src/lib/query/migration-reindex.ts +61 -0
- package/src/modules/__tests__/injection-widget-override-ids.test.ts +249 -0
- package/src/modules/overrides.ts +137 -12
- package/src/modules/widgets/injection-loader.ts +11 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
[build:shared] found
|
|
1
|
+
[build:shared] found 271 entry points
|
|
2
2
|
[build:shared] built successfully
|
package/AGENTS.md
CHANGED
|
@@ -296,10 +296,12 @@ MUST rules:
|
|
|
296
296
|
- API-route override keys are `'METHOD /api/path'` (method case-insensitive, path leading slash optional). Trailing slashes are stripped.
|
|
297
297
|
- Page-route override keys are `'/backend/path'` or `'/frontend/path'`.
|
|
298
298
|
- `null` disables the matching method; `{ handler, metadata? }` replaces it. Disabling every method on an entry drops the entry.
|
|
299
|
-
- The dispatcher SHOULD run from `bootstrap.ts` BEFORE any registry first-loads (`registerApiRouteManifests`, widget registries, notification registries, etc.) so the overrides take effect when the registry stores entries.
|
|
299
|
+
- The dispatcher SHOULD run from `bootstrap.ts` BEFORE any registry first-loads (`registerApiRouteManifests`, widget registries, notification registries, etc.) so the overrides take effect when the registry stores entries. It MUST also run in the browser before `ClientBootstrap` re-registers the injection/dashboard/notification registries — pass `{ domains: ['widgets', 'notifications'] }` there so server-only appliers are not reported as unwired — otherwise the raw generated registries overwrite the filtered ones and a disabled widget returns on hydration (#5152).
|
|
300
|
+
- `widgets.injection` keys accept EITHER identifier: the generated `entry.key` (`module:widget:file`) or the widget's own `entry.widgetId` (`module.injection.widget`). Both the entries registry and the injection tables resolve either spelling, so listing one is enough; listing both is accepted silently, and only genuinely conflicting values warn.
|
|
301
|
+
- An `enabledModules` entry gated on a **server-only** env var (anything not `NEXT_PUBLIC_*`) MUST NOT carry `widgets` or `notifications` overrides. The browser re-evaluates `modules.ts` with those reads `undefined`, so the entry is absent there: the server dispatches the override and the client does not, and the widget returns on hydration with nothing logged. Declare such an override on an ungated entry, or gate it on a `NEXT_PUBLIC_` var. Outside production `ClientBootstrap` warns for every module id in `enabled-module-ids.generated` that the browser-evaluated list is missing.
|
|
300
302
|
- Adding a new override domain MUST follow the umbrella spec: typed sub-shape + composer + runtime hook + tests + AGENTS.md/docs update + status-table tick.
|
|
301
303
|
- `nav.groupOrder` **prepends** group ids ahead of the built-in ordering; ids it does not name keep their current position. It is a default, resolved beneath role and per-user sidebar preferences, and an absent override MUST leave ordering byte-identical.
|
|
302
|
-
- Nav ordering state lives on `globalThis` because its reader is `@open-mercato/core` while its writer is app bootstrap; a module-local variable would be invisible across duplicated module instances in standalone builds.
|
|
304
|
+
- Nav ordering state lives on `globalThis` because its reader is `@open-mercato/core` while its writer is app bootstrap; a module-local variable would be invisible across duplicated module instances in standalone builds. The injection-widget `key`⇄`widgetId` alias index is on `globalThis` for the same reason — `@open-mercato/ui` writes it while filtering entries, `@open-mercato/core` reads it while filtering tables.
|
|
303
305
|
|
|
304
306
|
### Query Engine Extensibility (UMES)
|
|
305
307
|
|
|
@@ -89,7 +89,7 @@ async function registerWidgetsAndOptionalPackages(data, options) {
|
|
|
89
89
|
if (!options.skipCoreInjectionWidgets) {
|
|
90
90
|
coreInjection.registerCoreInjectionWidgets(data.injectionWidgetEntries);
|
|
91
91
|
}
|
|
92
|
-
coreInjection.registerCoreInjectionTables(data.injectionTables);
|
|
92
|
+
coreInjection.registerCoreInjectionTables(data.injectionTables, data.injectionWidgetEntries);
|
|
93
93
|
coreInjection.registerEnabledModuleIds(
|
|
94
94
|
data.modules.map((module) => module.id).filter((id) => typeof id === "string" && id.length > 0)
|
|
95
95
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/bootstrap/factory.ts"],
|
|
4
|
-
"sourcesContent": ["import type { BootstrapData, BootstrapOptions } from './types'\nimport { registerOrmEntities } from '../db/mikro'\nimport { registerAppDiRegistrar, registerDiRegistrars } from '../di/container'\nimport { registerModules } from '../modules/registry'\nimport { registerEntityIds } from '../encryption/entityIds'\nimport { registerEntityFields } from '../encryption/entityFields'\nimport { registerSearchModuleConfigs } from '../../modules/search'\nimport { registerAnalyticsModuleConfigs } from '../../modules/analytics'\nimport { registerCodeWorkflowEntries } from '../../modules/workflows/code-registry'\nimport { registerResponseEnrichers } from '../crud/enricher-registry'\nimport { registerApiInterceptors } from '../crud/interceptor-registry'\nimport { registerComponentOverrides } from '../../modules/widgets/component-registry'\nimport { registerMutationGuards } from '../crud/mutation-guard-store'\nimport { registerCommandInterceptors } from '../commands/command-interceptor-store'\nimport { registerCommandLoaders } from '../commands/registry'\nimport { registerNotificationHandlers } from '../notifications/handler-registry'\nimport { clearRegisteredIntegrations, registerBundles, registerIntegrations } from '../../modules/integrations/types'\nimport { applyComponentOverridesToEntries } from '../../modules/overrides'\n\nconst _bootstrappedKeys = new Set<string>()\n\n// Store the async registration promise so callers can await it if needed\nlet _asyncRegistrationPromise: Promise<void> | null = null\n\n/**\n * Creates a bootstrap function that registers all application dependencies.\n *\n * The returned function should be called once at application startup.\n * In development mode, it can be called multiple times (for HMR).\n *\n * @param data - All generated registry data from .mercato/generated/\n * @param options - Optional configuration\n * @returns A bootstrap function to call at app startup\n */\nexport function createBootstrap(data: BootstrapData, options: BootstrapOptions = {}) {\n return function bootstrap(): void {\n const registrationKey = options.registrationKey ?? 'default'\n if (options.appDiRegistrar) {\n registerAppDiRegistrar(options.appDiRegistrar)\n }\n // In development, always re-run registrations to handle HMR\n // (Module state may be reset when Turbopack reloads packages)\n if (_bootstrappedKeys.has(registrationKey) && process.env.NODE_ENV !== 'development') return\n _bootstrappedKeys.add(registrationKey)\n\n // === 1. Foundation: ORM entities and DI registrars ===\n registerOrmEntities(data.entities)\n registerDiRegistrars(data.diRegistrars.filter((r): r is NonNullable<typeof r> => r != null))\n\n // === 2. Modules registry (required by i18n, query engine, dashboards, CLI) ===\n registerModules(data.modules)\n clearRegisteredIntegrations()\n for (const module of data.modules) {\n if (module.integrations?.length) {\n registerIntegrations(module.integrations)\n }\n if (module.bundles?.length) {\n registerBundles(module.bundles)\n }\n }\n\n // === 3. Entity IDs (required by encryption, indexing, entity links) ===\n registerEntityIds(data.entityIds)\n\n // === 4. Entity fields registry (for encryption manager, Turbopack compatibility) ===\n if (data.entityFieldsRegistry) {\n registerEntityFields(data.entityFieldsRegistry)\n }\n\n // === 5. Search module configs (for search service registration in DI) ===\n if (data.searchModuleConfigs) {\n registerSearchModuleConfigs(data.searchModuleConfigs)\n }\n\n // === 6. Analytics module configs (for dashboard widgets and analytics API) ===\n if (data.analyticsModuleConfigs) {\n registerAnalyticsModuleConfigs(data.analyticsModuleConfigs)\n }\n\n // === 6a. Code workflow definitions (so CLI/worker processes resolve them like the app runtime) ===\n if (data.codeWorkflows?.length) {\n registerCodeWorkflowEntries(data.codeWorkflows)\n }\n\n // === 6b. Response enrichers (for CRUD response enrichment) ===\n if (data.enricherEntries) {\n registerResponseEnrichers(data.enricherEntries)\n }\n\n // === 6c. API interceptors (for CRUD route interception) ===\n if (data.interceptorEntries) {\n registerApiInterceptors(data.interceptorEntries)\n }\n\n // === 6d. Component overrides (for page/component replacement) ===\n if (data.componentOverrideEntries) {\n const finalEntries = applyComponentOverridesToEntries(data.componentOverrideEntries)\n const allOverrides = finalEntries.flatMap((entry) => entry.componentOverrides ?? [])\n registerComponentOverrides(allOverrides)\n }\n\n // === 6e. Mutation guards (for CRUD mutation lifecycle) ===\n if (data.guardEntries) {\n registerMutationGuards(data.guardEntries)\n }\n\n // === 6f. Command interceptors (for command bus lifecycle) ===\n if (data.commandInterceptorEntries) {\n registerCommandInterceptors(data.commandInterceptorEntries)\n }\n\n // === 6f.1. Command loaders (for lazy command handler registration) ===\n if (data.commandLoaderEntries) {\n registerCommandLoaders(data.commandLoaderEntries)\n }\n\n // === 6g. Notification handlers (reactive notification side-effects) ===\n if (data.notificationHandlerEntries) {\n registerNotificationHandlers(data.notificationHandlerEntries)\n }\n\n // === 7-8. UI Widgets and Optional packages (async to avoid circular deps) ===\n // Store the promise so CLI context can await it\n _asyncRegistrationPromise = registerWidgetsAndOptionalPackages(data, options)\n void _asyncRegistrationPromise\n\n options.onRegistrationComplete?.()\n }\n}\n\n/**\n * Wait for async registrations (CLI modules, widgets, etc.) to complete.\n * Call this after bootstrap() in CLI context where you need modules immediately.\n */\nexport async function waitForAsyncRegistration(): Promise<void> {\n if (_asyncRegistrationPromise) {\n await _asyncRegistrationPromise\n }\n}\n\nasync function registerWidgetsAndOptionalPackages(data: BootstrapData, options: BootstrapOptions): Promise<void> {\n // Register widget data required by server-side injection independently from\n // browser-facing UI registries. API-only bootstraps avoid loading @open-mercato/ui.\n try {\n const coreInjection = await import('@open-mercato/core/modules/widgets/lib/injection')\n if (!options.skipCoreInjectionWidgets) {\n coreInjection.registerCoreInjectionWidgets(data.injectionWidgetEntries)\n }\n coreInjection.registerCoreInjectionTables(data.injectionTables)\n coreInjection.registerEnabledModuleIds(\n data.modules.map((module) => module.id).filter((id): id is string => typeof id === 'string' && id.length > 0),\n )\n\n if (!options.skipUiRegistries) {\n const [dashboardRegistry, injectionRegistry] = await Promise.all([\n import('@open-mercato/ui/backend/dashboard/widgetRegistry'),\n import('@open-mercato/ui/backend/injection/widgetRegistry'),\n ])\n dashboardRegistry.registerDashboardWidgets(data.dashboardWidgetEntries)\n injectionRegistry.registerInjectionWidgets(data.injectionWidgetEntries)\n }\n } catch {\n // UI packages may not be available in all contexts\n }\n\n // Note: Search module configs are registered synchronously in the main bootstrap.\n // The actual registerSearchModule() call happens in core/bootstrap.ts when the\n // DI container is created, using getSearchModuleConfigs() from the global registry.\n\n // Note: CLI module registration is handled separately in CLI context\n // via bootstrapFromAppRoot in dynamicLoader. We don't import CLI here\n // to avoid Turbopack tracing through the CLI package in Next.js context.\n}\n\n/**\n * Check if bootstrap has been called.\n */\nexport function isBootstrapped(): boolean {\n return _bootstrappedKeys.size > 0\n}\n\n/**\n * Reset bootstrap state. Useful for testing.\n */\nexport function resetBootstrapState(): void {\n _bootstrappedKeys.clear()\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,2BAA2B;AACpC,SAAS,wBAAwB,4BAA4B;AAC7D,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,mCAAmC;AAC5C,SAAS,sCAAsC;AAC/C,SAAS,mCAAmC;AAC5C,SAAS,iCAAiC;AAC1C,SAAS,+BAA+B;AACxC,SAAS,kCAAkC;AAC3C,SAAS,8BAA8B;AACvC,SAAS,mCAAmC;AAC5C,SAAS,8BAA8B;AACvC,SAAS,oCAAoC;AAC7C,SAAS,6BAA6B,iBAAiB,4BAA4B;AACnF,SAAS,wCAAwC;AAEjD,MAAM,oBAAoB,oBAAI,IAAY;AAG1C,IAAI,4BAAkD;AAY/C,SAAS,gBAAgB,MAAqB,UAA4B,CAAC,GAAG;AACnF,SAAO,SAAS,YAAkB;AAChC,UAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAI,QAAQ,gBAAgB;AAC1B,6BAAuB,QAAQ,cAAc;AAAA,IAC/C;AAGA,QAAI,kBAAkB,IAAI,eAAe,KAAK,QAAQ,IAAI,aAAa,cAAe;AACtF,sBAAkB,IAAI,eAAe;AAGrC,wBAAoB,KAAK,QAAQ;AACjC,yBAAqB,KAAK,aAAa,OAAO,CAAC,MAAkC,KAAK,IAAI,CAAC;AAG3F,oBAAgB,KAAK,OAAO;AAC5B,gCAA4B;AAC5B,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,OAAO,cAAc,QAAQ;AAC/B,6BAAqB,OAAO,YAAY;AAAA,MAC1C;AACA,UAAI,OAAO,SAAS,QAAQ;AAC1B,wBAAgB,OAAO,OAAO;AAAA,MAChC;AAAA,IACF;AAGA,sBAAkB,KAAK,SAAS;AAGhC,QAAI,KAAK,sBAAsB;AAC7B,2BAAqB,KAAK,oBAAoB;AAAA,IAChD;AAGA,QAAI,KAAK,qBAAqB;AAC5B,kCAA4B,KAAK,mBAAmB;AAAA,IACtD;AAGA,QAAI,KAAK,wBAAwB;AAC/B,qCAA+B,KAAK,sBAAsB;AAAA,IAC5D;AAGA,QAAI,KAAK,eAAe,QAAQ;AAC9B,kCAA4B,KAAK,aAAa;AAAA,IAChD;AAGA,QAAI,KAAK,iBAAiB;AACxB,gCAA0B,KAAK,eAAe;AAAA,IAChD;AAGA,QAAI,KAAK,oBAAoB;AAC3B,8BAAwB,KAAK,kBAAkB;AAAA,IACjD;AAGA,QAAI,KAAK,0BAA0B;AACjC,YAAM,eAAe,iCAAiC,KAAK,wBAAwB;AACnF,YAAM,eAAe,aAAa,QAAQ,CAAC,UAAU,MAAM,sBAAsB,CAAC,CAAC;AACnF,iCAA2B,YAAY;AAAA,IACzC;AAGA,QAAI,KAAK,cAAc;AACrB,6BAAuB,KAAK,YAAY;AAAA,IAC1C;AAGA,QAAI,KAAK,2BAA2B;AAClC,kCAA4B,KAAK,yBAAyB;AAAA,IAC5D;AAGA,QAAI,KAAK,sBAAsB;AAC7B,6BAAuB,KAAK,oBAAoB;AAAA,IAClD;AAGA,QAAI,KAAK,4BAA4B;AACnC,mCAA6B,KAAK,0BAA0B;AAAA,IAC9D;AAIA,gCAA4B,mCAAmC,MAAM,OAAO;AAC5E,SAAK;AAEL,YAAQ,yBAAyB;AAAA,EACnC;AACF;AAMA,eAAsB,2BAA0C;AAC9D,MAAI,2BAA2B;AAC7B,UAAM;AAAA,EACR;AACF;AAEA,eAAe,mCAAmC,MAAqB,SAA0C;AAG/G,MAAI;AACF,UAAM,gBAAgB,MAAM,OAAO,kDAAkD;AACrF,QAAI,CAAC,QAAQ,0BAA0B;AACrC,oBAAc,6BAA6B,KAAK,sBAAsB;AAAA,IACxE;AACA,kBAAc,4BAA4B,KAAK,
|
|
4
|
+
"sourcesContent": ["import type { BootstrapData, BootstrapOptions } from './types'\nimport { registerOrmEntities } from '../db/mikro'\nimport { registerAppDiRegistrar, registerDiRegistrars } from '../di/container'\nimport { registerModules } from '../modules/registry'\nimport { registerEntityIds } from '../encryption/entityIds'\nimport { registerEntityFields } from '../encryption/entityFields'\nimport { registerSearchModuleConfigs } from '../../modules/search'\nimport { registerAnalyticsModuleConfigs } from '../../modules/analytics'\nimport { registerCodeWorkflowEntries } from '../../modules/workflows/code-registry'\nimport { registerResponseEnrichers } from '../crud/enricher-registry'\nimport { registerApiInterceptors } from '../crud/interceptor-registry'\nimport { registerComponentOverrides } from '../../modules/widgets/component-registry'\nimport { registerMutationGuards } from '../crud/mutation-guard-store'\nimport { registerCommandInterceptors } from '../commands/command-interceptor-store'\nimport { registerCommandLoaders } from '../commands/registry'\nimport { registerNotificationHandlers } from '../notifications/handler-registry'\nimport { clearRegisteredIntegrations, registerBundles, registerIntegrations } from '../../modules/integrations/types'\nimport { applyComponentOverridesToEntries } from '../../modules/overrides'\n\nconst _bootstrappedKeys = new Set<string>()\n\n// Store the async registration promise so callers can await it if needed\nlet _asyncRegistrationPromise: Promise<void> | null = null\n\n/**\n * Creates a bootstrap function that registers all application dependencies.\n *\n * The returned function should be called once at application startup.\n * In development mode, it can be called multiple times (for HMR).\n *\n * @param data - All generated registry data from .mercato/generated/\n * @param options - Optional configuration\n * @returns A bootstrap function to call at app startup\n */\nexport function createBootstrap(data: BootstrapData, options: BootstrapOptions = {}) {\n return function bootstrap(): void {\n const registrationKey = options.registrationKey ?? 'default'\n if (options.appDiRegistrar) {\n registerAppDiRegistrar(options.appDiRegistrar)\n }\n // In development, always re-run registrations to handle HMR\n // (Module state may be reset when Turbopack reloads packages)\n if (_bootstrappedKeys.has(registrationKey) && process.env.NODE_ENV !== 'development') return\n _bootstrappedKeys.add(registrationKey)\n\n // === 1. Foundation: ORM entities and DI registrars ===\n registerOrmEntities(data.entities)\n registerDiRegistrars(data.diRegistrars.filter((r): r is NonNullable<typeof r> => r != null))\n\n // === 2. Modules registry (required by i18n, query engine, dashboards, CLI) ===\n registerModules(data.modules)\n clearRegisteredIntegrations()\n for (const module of data.modules) {\n if (module.integrations?.length) {\n registerIntegrations(module.integrations)\n }\n if (module.bundles?.length) {\n registerBundles(module.bundles)\n }\n }\n\n // === 3. Entity IDs (required by encryption, indexing, entity links) ===\n registerEntityIds(data.entityIds)\n\n // === 4. Entity fields registry (for encryption manager, Turbopack compatibility) ===\n if (data.entityFieldsRegistry) {\n registerEntityFields(data.entityFieldsRegistry)\n }\n\n // === 5. Search module configs (for search service registration in DI) ===\n if (data.searchModuleConfigs) {\n registerSearchModuleConfigs(data.searchModuleConfigs)\n }\n\n // === 6. Analytics module configs (for dashboard widgets and analytics API) ===\n if (data.analyticsModuleConfigs) {\n registerAnalyticsModuleConfigs(data.analyticsModuleConfigs)\n }\n\n // === 6a. Code workflow definitions (so CLI/worker processes resolve them like the app runtime) ===\n if (data.codeWorkflows?.length) {\n registerCodeWorkflowEntries(data.codeWorkflows)\n }\n\n // === 6b. Response enrichers (for CRUD response enrichment) ===\n if (data.enricherEntries) {\n registerResponseEnrichers(data.enricherEntries)\n }\n\n // === 6c. API interceptors (for CRUD route interception) ===\n if (data.interceptorEntries) {\n registerApiInterceptors(data.interceptorEntries)\n }\n\n // === 6d. Component overrides (for page/component replacement) ===\n if (data.componentOverrideEntries) {\n const finalEntries = applyComponentOverridesToEntries(data.componentOverrideEntries)\n const allOverrides = finalEntries.flatMap((entry) => entry.componentOverrides ?? [])\n registerComponentOverrides(allOverrides)\n }\n\n // === 6e. Mutation guards (for CRUD mutation lifecycle) ===\n if (data.guardEntries) {\n registerMutationGuards(data.guardEntries)\n }\n\n // === 6f. Command interceptors (for command bus lifecycle) ===\n if (data.commandInterceptorEntries) {\n registerCommandInterceptors(data.commandInterceptorEntries)\n }\n\n // === 6f.1. Command loaders (for lazy command handler registration) ===\n if (data.commandLoaderEntries) {\n registerCommandLoaders(data.commandLoaderEntries)\n }\n\n // === 6g. Notification handlers (reactive notification side-effects) ===\n if (data.notificationHandlerEntries) {\n registerNotificationHandlers(data.notificationHandlerEntries)\n }\n\n // === 7-8. UI Widgets and Optional packages (async to avoid circular deps) ===\n // Store the promise so CLI context can await it\n _asyncRegistrationPromise = registerWidgetsAndOptionalPackages(data, options)\n void _asyncRegistrationPromise\n\n options.onRegistrationComplete?.()\n }\n}\n\n/**\n * Wait for async registrations (CLI modules, widgets, etc.) to complete.\n * Call this after bootstrap() in CLI context where you need modules immediately.\n */\nexport async function waitForAsyncRegistration(): Promise<void> {\n if (_asyncRegistrationPromise) {\n await _asyncRegistrationPromise\n }\n}\n\nasync function registerWidgetsAndOptionalPackages(data: BootstrapData, options: BootstrapOptions): Promise<void> {\n // Register widget data required by server-side injection independently from\n // browser-facing UI registries. API-only bootstraps avoid loading @open-mercato/ui.\n try {\n const coreInjection = await import('@open-mercato/core/modules/widgets/lib/injection')\n if (!options.skipCoreInjectionWidgets) {\n coreInjection.registerCoreInjectionWidgets(data.injectionWidgetEntries)\n }\n coreInjection.registerCoreInjectionTables(data.injectionTables, data.injectionWidgetEntries)\n coreInjection.registerEnabledModuleIds(\n data.modules.map((module) => module.id).filter((id): id is string => typeof id === 'string' && id.length > 0),\n )\n\n if (!options.skipUiRegistries) {\n const [dashboardRegistry, injectionRegistry] = await Promise.all([\n import('@open-mercato/ui/backend/dashboard/widgetRegistry'),\n import('@open-mercato/ui/backend/injection/widgetRegistry'),\n ])\n dashboardRegistry.registerDashboardWidgets(data.dashboardWidgetEntries)\n injectionRegistry.registerInjectionWidgets(data.injectionWidgetEntries)\n }\n } catch {\n // UI packages may not be available in all contexts\n }\n\n // Note: Search module configs are registered synchronously in the main bootstrap.\n // The actual registerSearchModule() call happens in core/bootstrap.ts when the\n // DI container is created, using getSearchModuleConfigs() from the global registry.\n\n // Note: CLI module registration is handled separately in CLI context\n // via bootstrapFromAppRoot in dynamicLoader. We don't import CLI here\n // to avoid Turbopack tracing through the CLI package in Next.js context.\n}\n\n/**\n * Check if bootstrap has been called.\n */\nexport function isBootstrapped(): boolean {\n return _bootstrappedKeys.size > 0\n}\n\n/**\n * Reset bootstrap state. Useful for testing.\n */\nexport function resetBootstrapState(): void {\n _bootstrappedKeys.clear()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const QUERY_INDEX_REINDEX_EXPORT = "queryIndexReindexEntityTypes";
|
|
2
|
+
const ENTITY_TYPE_PATTERN = /^[a-z0-9_]+:[a-z0-9_]+$/;
|
|
3
|
+
function isQueryIndexEntityType(value) {
|
|
4
|
+
return typeof value === "string" && ENTITY_TYPE_PATTERN.test(value);
|
|
5
|
+
}
|
|
6
|
+
function declareQueryIndexReindex(entityTypes) {
|
|
7
|
+
if (!Array.isArray(entityTypes) || entityTypes.length === 0) {
|
|
8
|
+
throw new Error("[internal] declareQueryIndexReindex requires at least one entity type");
|
|
9
|
+
}
|
|
10
|
+
const normalized = [];
|
|
11
|
+
for (const entityType of entityTypes) {
|
|
12
|
+
if (!isQueryIndexEntityType(entityType)) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`[internal] declareQueryIndexReindex expects "module:entity" identifiers, received: ${String(entityType)}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (!normalized.includes(entityType)) normalized.push(entityType);
|
|
18
|
+
}
|
|
19
|
+
return Object.freeze(normalized);
|
|
20
|
+
}
|
|
21
|
+
function readQueryIndexReindexDeclaration(moduleExports, onReject) {
|
|
22
|
+
if (!moduleExports || typeof moduleExports !== "object") return [];
|
|
23
|
+
const declared = moduleExports[QUERY_INDEX_REINDEX_EXPORT];
|
|
24
|
+
if (!Array.isArray(declared)) return [];
|
|
25
|
+
const collected = [];
|
|
26
|
+
for (const entityType of declared) {
|
|
27
|
+
if (!isQueryIndexEntityType(entityType)) {
|
|
28
|
+
onReject?.(entityType);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!collected.includes(entityType)) collected.push(entityType);
|
|
32
|
+
}
|
|
33
|
+
return collected;
|
|
34
|
+
}
|
|
35
|
+
function formatQueryIndexRebuildCommands(entityTypes) {
|
|
36
|
+
return entityTypes.map((entityType) => `mercato query_index rebuild --entity ${entityType} --global`);
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
QUERY_INDEX_REINDEX_EXPORT,
|
|
40
|
+
declareQueryIndexReindex,
|
|
41
|
+
formatQueryIndexRebuildCommands,
|
|
42
|
+
isQueryIndexEntityType,
|
|
43
|
+
readQueryIndexReindexDeclaration
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=migration-reindex.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/query/migration-reindex.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Data migrations rewrite columns in raw SQL, so they bypass every CRUD/indexer helper that\n * would normally emit `query_index.upsert_one`. A migration also cannot emit from where it\n * stands: it runs inside its own transaction with no DI container, and the projection must\n * only be refreshed once the rewrite has committed.\n *\n * A migration therefore *declares* the entity types whose projections it invalidated, and\n * `mercato db migrate` discharges the obligation after the whole run commits.\n */\n\nexport const QUERY_INDEX_REINDEX_EXPORT = 'queryIndexReindexEntityTypes'\n\nconst ENTITY_TYPE_PATTERN = /^[a-z0-9_]+:[a-z0-9_]+$/\n\nexport function isQueryIndexEntityType(value: unknown): value is string {\n return typeof value === 'string' && ENTITY_TYPE_PATTERN.test(value)\n}\n\nexport function declareQueryIndexReindex(entityTypes: readonly string[]): readonly string[] {\n if (!Array.isArray(entityTypes) || entityTypes.length === 0) {\n throw new Error('[internal] declareQueryIndexReindex requires at least one entity type')\n }\n const normalized: string[] = []\n for (const entityType of entityTypes) {\n if (!isQueryIndexEntityType(entityType)) {\n throw new Error(\n `[internal] declareQueryIndexReindex expects \"module:entity\" identifiers, received: ${String(entityType)}`,\n )\n }\n if (!normalized.includes(entityType)) normalized.push(entityType)\n }\n return Object.freeze(normalized)\n}\n\n/**\n * The reader \u2014 not `declareQueryIndexReindex` \u2014 is the contract's real boundary: it accepts any\n * `queryIndexReindexEntityTypes` array, including one written as a plain literal. A rejected entry\n * is therefore reported through `onReject` rather than dropped silently, so a typo such as\n * `customers:customerDictionaryEntry` cannot leave a projection stale behind a green migrate run.\n */\nexport function readQueryIndexReindexDeclaration(\n moduleExports: unknown,\n onReject?: (value: unknown) => void,\n): string[] {\n if (!moduleExports || typeof moduleExports !== 'object') return []\n const declared = (moduleExports as Record<string, unknown>)[QUERY_INDEX_REINDEX_EXPORT]\n if (!Array.isArray(declared)) return []\n const collected: string[] = []\n for (const entityType of declared) {\n if (!isQueryIndexEntityType(entityType)) {\n onReject?.(entityType)\n continue\n }\n if (!collected.includes(entityType)) collected.push(entityType)\n }\n return collected\n}\n\nexport function formatQueryIndexRebuildCommands(entityTypes: readonly string[]): string[] {\n return entityTypes.map((entityType) => `mercato query_index rebuild --entity ${entityType} --global`)\n}\n"],
|
|
5
|
+
"mappings": "AAUO,MAAM,6BAA6B;AAE1C,MAAM,sBAAsB;AAErB,SAAS,uBAAuB,OAAiC;AACtE,SAAO,OAAO,UAAU,YAAY,oBAAoB,KAAK,KAAK;AACpE;AAEO,SAAS,yBAAyB,aAAmD;AAC1F,MAAI,CAAC,MAAM,QAAQ,WAAW,KAAK,YAAY,WAAW,GAAG;AAC3D,UAAM,IAAI,MAAM,uEAAuE;AAAA,EACzF;AACA,QAAM,aAAuB,CAAC;AAC9B,aAAW,cAAc,aAAa;AACpC,QAAI,CAAC,uBAAuB,UAAU,GAAG;AACvC,YAAM,IAAI;AAAA,QACR,sFAAsF,OAAO,UAAU,CAAC;AAAA,MAC1G;AAAA,IACF;AACA,QAAI,CAAC,WAAW,SAAS,UAAU,EAAG,YAAW,KAAK,UAAU;AAAA,EAClE;AACA,SAAO,OAAO,OAAO,UAAU;AACjC;AAQO,SAAS,iCACd,eACA,UACU;AACV,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAAU,QAAO,CAAC;AACjE,QAAM,WAAY,cAA0C,0BAA0B;AACtF,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO,CAAC;AACtC,QAAM,YAAsB,CAAC;AAC7B,aAAW,cAAc,UAAU;AACjC,QAAI,CAAC,uBAAuB,UAAU,GAAG;AACvC,iBAAW,UAAU;AACrB;AAAA,IACF;AACA,QAAI,CAAC,UAAU,SAAS,UAAU,EAAG,WAAU,KAAK,UAAU;AAAA,EAChE;AACA,SAAO;AACT;AAEO,SAAS,gCAAgC,aAA0C;AACxF,SAAO,YAAY,IAAI,CAAC,eAAe,wCAAwC,UAAU,WAAW;AACtG;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/lib/version.js
CHANGED
package/dist/lib/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.7.1-develop.
|
|
4
|
+
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.7.1-develop.7148.1.3076e5ccf7';\nexport const appVersion = APP_VERSION;\n"],
|
|
5
5
|
"mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,14 +27,15 @@ const DOMAIN_KEYS = [
|
|
|
27
27
|
"nav"
|
|
28
28
|
];
|
|
29
29
|
const TRACKING_ISSUE_HINT = "See `.ai/specs/implemented/2026-05-04-modules-ts-unified-overrides.md` and tracking issue https://github.com/open-mercato/open-mercato/issues/1787.";
|
|
30
|
-
function applyModuleOverridesFromEnabledModules(modules) {
|
|
30
|
+
function applyModuleOverridesFromEnabledModules(modules, options) {
|
|
31
31
|
if (!Array.isArray(modules) || modules.length === 0) return;
|
|
32
|
+
const selectedDomains = options?.domains ? DOMAIN_KEYS.filter((domain) => options.domains.includes(domain)) : DOMAIN_KEYS;
|
|
32
33
|
const buckets = /* @__PURE__ */ new Map();
|
|
33
34
|
for (const entry of modules) {
|
|
34
35
|
if (!entry || typeof entry.id !== "string" || !entry.id) continue;
|
|
35
36
|
const overrides = entry.overrides;
|
|
36
37
|
if (!overrides || typeof overrides !== "object") continue;
|
|
37
|
-
for (const domain of
|
|
38
|
+
for (const domain of selectedDomains) {
|
|
38
39
|
const value = overrides[domain];
|
|
39
40
|
if (value === void 0 || value === null) continue;
|
|
40
41
|
if (typeof value !== "object") continue;
|
|
@@ -132,6 +133,15 @@ function composeStore(store) {
|
|
|
132
133
|
}
|
|
133
134
|
return { ...store.modules, ...store.programmatic };
|
|
134
135
|
}
|
|
136
|
+
function resolveOverrideIds(value, options) {
|
|
137
|
+
const ids = [];
|
|
138
|
+
const primary = options.getId(value);
|
|
139
|
+
if (primary) ids.push(primary);
|
|
140
|
+
for (const alias of options.getAliasIds?.(value) ?? []) {
|
|
141
|
+
if (alias && !ids.includes(alias)) ids.push(alias);
|
|
142
|
+
}
|
|
143
|
+
return ids;
|
|
144
|
+
}
|
|
135
145
|
function applyArrayOverrides(items, overrides, options) {
|
|
136
146
|
if (!items || Object.keys(overrides).length === 0) {
|
|
137
147
|
return { items: items ? Array.from(items) : items, consumed: /* @__PURE__ */ new Set(), changed: false };
|
|
@@ -140,12 +150,20 @@ function applyArrayOverrides(items, overrides, options) {
|
|
|
140
150
|
const result = [];
|
|
141
151
|
let changed = false;
|
|
142
152
|
for (const item of items) {
|
|
143
|
-
const
|
|
144
|
-
if (
|
|
153
|
+
const matched = resolveOverrideIds(item, options).filter((candidate) => Object.prototype.hasOwnProperty.call(overrides, candidate));
|
|
154
|
+
if (matched.length === 0) {
|
|
145
155
|
result.push(item);
|
|
146
156
|
continue;
|
|
147
157
|
}
|
|
148
|
-
|
|
158
|
+
const id = matched[0];
|
|
159
|
+
for (const candidate of matched) consumed.add(candidate);
|
|
160
|
+
if (matched.some((candidate) => overrides[candidate] !== overrides[id])) {
|
|
161
|
+
const disablesAndReplaces = matched.some((candidate) => overrides[candidate] === null !== (overrides[id] === null));
|
|
162
|
+
logger.warn(
|
|
163
|
+
disablesAndReplaces ? "Conflicting overrides for the same entry \u2014 one key disables it while another replaces it; the first matching key wins" : "Duplicate replacement overrides for the same entry \u2014 only the first matching key takes effect",
|
|
164
|
+
{ label: options.label, id, keys: matched }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
149
167
|
changed = true;
|
|
150
168
|
const replacement = overrides[id];
|
|
151
169
|
if (replacement === null) continue;
|
|
@@ -154,12 +172,22 @@ function applyArrayOverrides(items, overrides, options) {
|
|
|
154
172
|
result.push(item);
|
|
155
173
|
continue;
|
|
156
174
|
}
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
175
|
+
const replacementIds = resolveOverrideIds(replacement, options);
|
|
176
|
+
if (!replacementIds.includes(id)) {
|
|
159
177
|
logger.warn("Skipping malformed override \u2014 replacement id must match the override key", { label: options.label, id });
|
|
160
178
|
result.push(item);
|
|
161
179
|
continue;
|
|
162
180
|
}
|
|
181
|
+
const itemIds = resolveOverrideIds(item, options);
|
|
182
|
+
const divergent = itemIds.filter((candidate) => !replacementIds.includes(candidate));
|
|
183
|
+
if (divergent.length > 0) {
|
|
184
|
+
logger.warn("Replacement override changes an identifier it was not matched on \u2014 references to the old value are not rewritten", {
|
|
185
|
+
label: options.label,
|
|
186
|
+
id,
|
|
187
|
+
replaced: divergent,
|
|
188
|
+
replacementIds
|
|
189
|
+
});
|
|
190
|
+
}
|
|
163
191
|
result.push(replacement);
|
|
164
192
|
}
|
|
165
193
|
return { items: result, consumed, changed };
|
|
@@ -289,6 +317,7 @@ function resetModuleContractOverridesForTests() {
|
|
|
289
317
|
clearStore(aclFeatureOverrideStore);
|
|
290
318
|
clearStore(encryptionMapOverrideStore);
|
|
291
319
|
clearStore(diOverrideStore);
|
|
320
|
+
getInjectionWidgetIdAliases().clear();
|
|
292
321
|
for (const key of Object.keys(setupOverridesByModule)) delete setupOverridesByModule[key];
|
|
293
322
|
const navState = getNavOverrideState();
|
|
294
323
|
navState.modules = null;
|
|
@@ -528,10 +557,35 @@ function applyEntryListOverrides(entries, overrides, options) {
|
|
|
528
557
|
warnStaleOverrides(options.label, overrides, consumed);
|
|
529
558
|
return changed ? result : Array.from(entries);
|
|
530
559
|
}
|
|
560
|
+
const GLOBAL_INJECTION_WIDGET_ID_ALIASES_KEY = "__openMercatoInjectionWidgetIdAliases__";
|
|
561
|
+
function getInjectionWidgetIdAliases() {
|
|
562
|
+
const existing = globalThis[GLOBAL_INJECTION_WIDGET_ID_ALIASES_KEY];
|
|
563
|
+
if (existing instanceof Map) return existing;
|
|
564
|
+
const initial = /* @__PURE__ */ new Map();
|
|
565
|
+
globalThis[GLOBAL_INJECTION_WIDGET_ID_ALIASES_KEY] = initial;
|
|
566
|
+
return initial;
|
|
567
|
+
}
|
|
568
|
+
function rememberInjectionWidgetIdAliases(entries) {
|
|
569
|
+
if (!entries) return;
|
|
570
|
+
const aliases = getInjectionWidgetIdAliases();
|
|
571
|
+
for (const entry of entries) {
|
|
572
|
+
const ids = [entry?.key, entry?.widgetId].filter((id) => typeof id === "string" && id.length > 0);
|
|
573
|
+
if (ids.length < 2) continue;
|
|
574
|
+
for (const id of ids) {
|
|
575
|
+
const siblings = aliases.get(id) ?? /* @__PURE__ */ new Set();
|
|
576
|
+
for (const sibling of ids) {
|
|
577
|
+
if (sibling !== id) siblings.add(sibling);
|
|
578
|
+
}
|
|
579
|
+
aliases.set(id, siblings);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
531
583
|
function applyInjectionWidgetOverridesToEntries(entries, overrides = composeInjectionWidgetOverrides()) {
|
|
584
|
+
rememberInjectionWidgetIdAliases(entries);
|
|
532
585
|
const applied = applyArrayOverrides(entries, overrides, {
|
|
533
586
|
label: "widgets.injection",
|
|
534
587
|
getId: (entry) => entry.key,
|
|
588
|
+
getAliasIds: (entry) => [entry.widgetId],
|
|
535
589
|
isReplacement: isInjectionWidgetEntry
|
|
536
590
|
});
|
|
537
591
|
warnStaleOverrides("widgets.injection", overrides, applied.consumed);
|
|
@@ -555,8 +609,14 @@ function applyWorkerOverridesToDescriptors(entries, overrides = composeWorkerOve
|
|
|
555
609
|
warnStaleOverrides("workers", overrides, applied.consumed);
|
|
556
610
|
return applied.items ?? [];
|
|
557
611
|
}
|
|
558
|
-
function applyInjectionWidgetOverridesToTables(tables, overrides = composeInjectionWidgetOverrides()) {
|
|
559
|
-
|
|
612
|
+
function applyInjectionWidgetOverridesToTables(tables, overrides = composeInjectionWidgetOverrides(), entries = []) {
|
|
613
|
+
rememberInjectionWidgetIdAliases(entries);
|
|
614
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
615
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
616
|
+
if (value !== null) continue;
|
|
617
|
+
disabled.add(key);
|
|
618
|
+
for (const alias of getInjectionWidgetIdAliases().get(key) ?? []) disabled.add(alias);
|
|
619
|
+
}
|
|
560
620
|
if (disabled.size === 0) return Array.from(tables);
|
|
561
621
|
const filterSlot = (slot) => {
|
|
562
622
|
if (typeof slot === "string") return disabled.has(slot) ? null : slot;
|