@open-mercato/shared 0.6.2-develop.3461.1.605f31c2c9 → 0.6.2

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 (67) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +24 -0
  3. package/dist/lib/bootstrap/factory.js +3 -1
  4. package/dist/lib/bootstrap/factory.js.map +2 -2
  5. package/dist/lib/commands/command-interceptor-store.js +3 -1
  6. package/dist/lib/commands/command-interceptor-store.js.map +2 -2
  7. package/dist/lib/crud/enricher-registry.js +3 -1
  8. package/dist/lib/crud/enricher-registry.js.map +2 -2
  9. package/dist/lib/crud/factory.js.map +1 -1
  10. package/dist/lib/crud/interceptor-registry.js +3 -1
  11. package/dist/lib/crud/interceptor-registry.js.map +2 -2
  12. package/dist/lib/crud/sync-event-runner.js +2 -8
  13. package/dist/lib/crud/sync-event-runner.js.map +2 -2
  14. package/dist/lib/db/mikro.js +27 -3
  15. package/dist/lib/db/mikro.js.map +2 -2
  16. package/dist/lib/di/container.js +16 -0
  17. package/dist/lib/di/container.js.map +2 -2
  18. package/dist/lib/events/patterns.js +2 -10
  19. package/dist/lib/events/patterns.js.map +2 -2
  20. package/dist/lib/middleware/page-executor.js +2 -1
  21. package/dist/lib/middleware/page-executor.js.map +2 -2
  22. package/dist/lib/modules/registry.js +2 -1
  23. package/dist/lib/modules/registry.js.map +2 -2
  24. package/dist/lib/notifications/handler-registry.js +3 -1
  25. package/dist/lib/notifications/handler-registry.js.map +2 -2
  26. package/dist/lib/patterns/wildcard.js +42 -0
  27. package/dist/lib/patterns/wildcard.js.map +7 -0
  28. package/dist/lib/regex/linear.js +31 -0
  29. package/dist/lib/regex/linear.js.map +7 -0
  30. package/dist/lib/version.js +1 -1
  31. package/dist/lib/version.js.map +1 -1
  32. package/dist/modules/entities/validation.js +15 -7
  33. package/dist/modules/entities/validation.js.map +2 -2
  34. package/dist/modules/overrides.js +857 -0
  35. package/dist/modules/overrides.js.map +2 -2
  36. package/dist/modules/registry.js +17 -4
  37. package/dist/modules/registry.js.map +2 -2
  38. package/dist/modules/widgets/injection-loader.js +12 -6
  39. package/dist/modules/widgets/injection-loader.js.map +2 -2
  40. package/jest.config.cjs +3 -1
  41. package/package.json +8 -8
  42. package/src/lib/bootstrap/factory.ts +3 -1
  43. package/src/lib/commands/command-interceptor-store.ts +3 -1
  44. package/src/lib/crud/__tests__/sync-event-runner.test.ts +5 -0
  45. package/src/lib/crud/enricher-registry.ts +3 -1
  46. package/src/lib/crud/factory.ts +2 -2
  47. package/src/lib/crud/interceptor-registry.ts +3 -1
  48. package/src/lib/crud/sync-event-runner.ts +2 -11
  49. package/src/lib/db/mikro.ts +27 -2
  50. package/src/lib/di/container.ts +24 -4
  51. package/src/lib/events/__tests__/patterns.test.ts +5 -0
  52. package/src/lib/events/patterns.ts +3 -16
  53. package/src/lib/middleware/page-executor.ts +2 -1
  54. package/src/lib/modules/registry.ts +2 -1
  55. package/src/lib/notifications/handler-registry.ts +3 -1
  56. package/src/lib/patterns/__tests__/wildcard.test.ts +27 -0
  57. package/src/lib/patterns/wildcard.ts +59 -0
  58. package/src/lib/regex/linear.ts +48 -0
  59. package/src/modules/__tests__/contract-overrides.test.ts +332 -0
  60. package/src/modules/__tests__/overrides.test.ts +23 -22
  61. package/src/modules/__tests__/route-overrides.test.ts +441 -0
  62. package/src/modules/entities/__tests__/validation.test.ts +97 -2
  63. package/src/modules/entities/validation.ts +14 -9
  64. package/src/modules/overrides.ts +1297 -27
  65. package/src/modules/registry.ts +27 -4
  66. package/src/modules/widgets/__tests__/injection-loader.required-modules.test.ts +21 -0
  67. package/src/modules/widgets/injection-loader.ts +12 -6
@@ -4,6 +4,13 @@ import type { SyncCrudEventResult } from '../lib/crud/sync-event-types'
4
4
  import type { DashboardWidgetModule } from './dashboard/widgets'
5
5
  import type { InjectionAnyWidgetModule, ModuleInjectionTable } from './widgets/injection'
6
6
  import type { IntegrationBundle, IntegrationDefinition } from './integrations/types'
7
+ import {
8
+ applyApiOverridesToManifests,
9
+ applyModuleOverridesToModules,
10
+ applyPageOverridesToManifests,
11
+ composeApiRouteOverrides,
12
+ composePageRouteOverrides,
13
+ } from './overrides'
7
14
 
8
15
  // Context passed to dynamic metadata guards
9
16
  export type RouteVisibilityContext = { path?: string; auth?: any }
@@ -396,7 +403,11 @@ export function findApiRouteManifestMatch<T extends { path: string; methods: Htt
396
403
  let _backendRouteManifests: BackendRouteManifestEntry[] | null = null
397
404
 
398
405
  export function registerBackendRouteManifests(routes: BackendRouteManifestEntry[]) {
399
- _backendRouteManifests = sortRoutesBySpecificity(routes)
406
+ const pageOverrides = composePageRouteOverrides()
407
+ const finalRoutes = Object.keys(pageOverrides).length === 0
408
+ ? routes
409
+ : applyPageOverridesToManifests(routes, pageOverrides, 'backend')
410
+ _backendRouteManifests = sortRoutesBySpecificity(finalRoutes)
400
411
  }
401
412
 
402
413
  export function getBackendRouteManifests(): BackendRouteManifestEntry[] {
@@ -406,7 +417,11 @@ export function getBackendRouteManifests(): BackendRouteManifestEntry[] {
406
417
  let _frontendRouteManifests: FrontendRouteManifestEntry[] | null = null
407
418
 
408
419
  export function registerFrontendRouteManifests(routes: FrontendRouteManifestEntry[]) {
409
- _frontendRouteManifests = sortRoutesBySpecificity(routes)
420
+ const pageOverrides = composePageRouteOverrides()
421
+ const finalRoutes = Object.keys(pageOverrides).length === 0
422
+ ? routes
423
+ : applyPageOverridesToManifests(routes, pageOverrides, 'frontend')
424
+ _frontendRouteManifests = sortRoutesBySpecificity(finalRoutes)
410
425
  }
411
426
 
412
427
  export function getFrontendRouteManifests(): FrontendRouteManifestEntry[] {
@@ -416,7 +431,15 @@ export function getFrontendRouteManifests(): FrontendRouteManifestEntry[] {
416
431
  let _apiRouteManifests: ApiRouteManifestEntry[] | null = null
417
432
 
418
433
  export function registerApiRouteManifests(routes: ApiRouteManifestEntry[]) {
419
- _apiRouteManifests = sortRoutesBySpecificity(routes)
434
+ // Apply any `entry.overrides.routes.api` overrides registered through the
435
+ // unified `modules.ts` dispatcher or programmatic API before storing the
436
+ // manifest. The composer is cheap and returns an empty object when no
437
+ // overrides exist, so this is a no-op for apps that do not opt in.
438
+ const routeOverrides = composeApiRouteOverrides()
439
+ const finalRoutes = Object.keys(routeOverrides).length === 0
440
+ ? routes
441
+ : applyApiOverridesToManifests(routes, routeOverrides)
442
+ _apiRouteManifests = sortRoutesBySpecificity(finalRoutes)
420
443
  }
421
444
 
422
445
  export function getApiRouteManifests(): ApiRouteManifestEntry[] {
@@ -430,7 +453,7 @@ export function registerCliModules(modules: Module[]) {
430
453
  if (_cliModules !== null && process.env.NODE_ENV === 'development') {
431
454
  console.debug('[Bootstrap] CLI modules re-registered (this may occur during HMR)')
432
455
  }
433
- _cliModules = modules
456
+ _cliModules = applyModuleOverridesToModules(modules)
434
457
  }
435
458
 
436
459
  export function getCliModules(): Module[] {
@@ -173,4 +173,25 @@ describe('Injection loader — requiredModules gating (#1849)', () => {
173
173
  expect(ids).toContain(ALWAYS_AVAILABLE_WIDGET_ID)
174
174
  expect(ids).not.toContain(REQUIRES_AI_WIDGET_ID)
175
175
  })
176
+
177
+ it('loads wildcard spot entries without regex pattern execution', async () => {
178
+ invalidateInjectionWidgetCache()
179
+ registerCoreInjectionWidgets([
180
+ makeWidgetEntry('host', 'host/widgets/injection/always-available/widget.ts', async () => alwaysAvailableWidget),
181
+ ])
182
+ registerCoreInjectionTables([
183
+ {
184
+ moduleId: 'host',
185
+ table: {
186
+ 'data-table:host.*:search-trailing': [
187
+ { widgetId: ALWAYS_AVAILABLE_WIDGET_ID, priority: 50 },
188
+ ],
189
+ },
190
+ },
191
+ ])
192
+ registerEnabledModuleIds(['host'])
193
+
194
+ const loaded = await loadInjectionWidgetsForSpot(HOST_SPOT_ID)
195
+ expect(loaded.map((widget) => widget.metadata.id)).toEqual([ALWAYS_AVAILABLE_WIDGET_ID])
196
+ })
176
197
  })
@@ -1,4 +1,5 @@
1
1
  import type { ModuleInjectionWidgetEntry } from '../registry'
2
+ import { matchWildcardPattern } from '@open-mercato/shared/lib/patterns/wildcard'
2
3
  import type {
3
4
  InjectionAnyWidgetModule,
4
5
  InjectionDataWidgetModule,
@@ -9,6 +10,10 @@ import type {
9
10
  ModuleInjectionTable,
10
11
  InjectionWidgetPlacement,
11
12
  } from './injection'
13
+ import {
14
+ applyInjectionWidgetOverridesToEntries,
15
+ applyInjectionWidgetOverridesToTables,
16
+ } from '../overrides'
12
17
 
13
18
  type LoadedWidgetModule = InjectionWidgetModule<any, any> & { metadata: InjectionWidgetMetadata }
14
19
  type LoadedDataWidgetModule = InjectionDataWidgetModule & { metadata: InjectionWidgetMetadata }
@@ -137,8 +142,9 @@ export function registerCoreInjectionWidgets(entries: ModuleInjectionWidgetEntry
137
142
  if (_coreInjectionWidgetEntries !== null && process.env.NODE_ENV === 'development') {
138
143
  console.debug('[Bootstrap] Core injection widgets re-registered (this may occur during HMR)')
139
144
  }
140
- _coreInjectionWidgetEntries = entries
141
- writeGlobalInjectionWidgets(entries)
145
+ const finalEntries = applyInjectionWidgetOverridesToEntries(entries)
146
+ _coreInjectionWidgetEntries = finalEntries
147
+ writeGlobalInjectionWidgets(finalEntries)
142
148
  notifyInjectionRegistryChanged()
143
149
  }
144
150
 
@@ -159,8 +165,9 @@ export function registerCoreInjectionTables(tables: Array<{ moduleId: string; ta
159
165
  if (_coreInjectionTables !== null && process.env.NODE_ENV === 'development') {
160
166
  console.debug('[Bootstrap] Core injection tables re-registered (this may occur during HMR)')
161
167
  }
162
- _coreInjectionTables = tables
163
- writeGlobalInjectionTables(tables)
168
+ const finalTables = applyInjectionWidgetOverridesToTables(tables)
169
+ _coreInjectionTables = finalTables
170
+ writeGlobalInjectionTables(finalTables)
164
171
  notifyInjectionRegistryChanged()
165
172
  }
166
173
 
@@ -446,8 +453,7 @@ async function getResolvedEntriesForSpot(spotId: InjectionSpotId): Promise<Table
446
453
  for (const [candidateSpotId, candidateEntries] of table.entries()) {
447
454
  if (candidateSpotId === spotId) continue
448
455
  if (!candidateSpotId.includes('*')) continue
449
- const pattern = new RegExp(`^${candidateSpotId.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*')}$`)
450
- if (!pattern.test(spotId)) continue
456
+ if (!matchWildcardPattern(spotId, candidateSpotId)) continue
451
457
  wildcardEntries.push(...candidateEntries)
452
458
  }
453
459