@open-mercato/shared 0.9.1-develop.7574.1.837288eec1 → 0.10.1-develop.7576.1.21d5b50435

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 (125) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +4 -4
  3. package/dist/lib/auth/server.js +1 -1
  4. package/dist/lib/auth/server.js.map +2 -2
  5. package/dist/lib/bootstrap/dynamicLoader.js +6 -46
  6. package/dist/lib/bootstrap/dynamicLoader.js.map +2 -2
  7. package/dist/lib/bootstrap/factory.js +3 -4
  8. package/dist/lib/bootstrap/factory.js.map +2 -2
  9. package/dist/lib/catalog-visibility/index.js +0 -4
  10. package/dist/lib/catalog-visibility/index.js.map +2 -2
  11. package/dist/lib/commands/command-bus.js +13 -45
  12. package/dist/lib/commands/command-bus.js.map +2 -2
  13. package/dist/lib/commands/types.js.map +2 -2
  14. package/dist/lib/crud/exporters.js +1 -1
  15. package/dist/lib/crud/exporters.js.map +2 -2
  16. package/dist/lib/crud/ids.js +1 -13
  17. package/dist/lib/crud/ids.js.map +2 -2
  18. package/dist/lib/db/pg-errors.js +0 -14
  19. package/dist/lib/db/pg-errors.js.map +2 -2
  20. package/dist/lib/localization/index.js +1 -9
  21. package/dist/lib/localization/index.js.map +2 -2
  22. package/dist/lib/localization/translatable-fields.js +0 -26
  23. package/dist/lib/localization/translatable-fields.js.map +2 -2
  24. package/dist/lib/number.js +0 -6
  25. package/dist/lib/number.js.map +2 -2
  26. package/dist/lib/openapi/generator.js +67 -84
  27. package/dist/lib/openapi/generator.js.map +2 -2
  28. package/dist/lib/query/engine.js +10 -45
  29. package/dist/lib/query/engine.js.map +2 -2
  30. package/dist/lib/query/join-utils.js +1 -1
  31. package/dist/lib/query/join-utils.js.map +2 -2
  32. package/dist/lib/query/types.js.map +2 -2
  33. package/dist/lib/url.js +0 -24
  34. package/dist/lib/url.js.map +2 -2
  35. package/dist/lib/version.js +1 -1
  36. package/dist/lib/version.js.map +1 -1
  37. package/dist/lib/webhooks/body.js +3 -7
  38. package/dist/lib/webhooks/body.js.map +2 -2
  39. package/dist/lib/webhooks/index.js +0 -2
  40. package/dist/lib/webhooks/index.js.map +2 -2
  41. package/dist/modules/integrations/types.js.map +2 -2
  42. package/dist/modules/notifications/types.js +0 -4
  43. package/dist/modules/notifications/types.js.map +3 -3
  44. package/dist/modules/payment_gateways/types.js +1 -14
  45. package/dist/modules/payment_gateways/types.js.map +2 -2
  46. package/dist/modules/registry.js.map +2 -2
  47. package/dist/modules/search.js.map +2 -2
  48. package/dist/modules/widgets/injection-loader.js +3 -14
  49. package/dist/modules/widgets/injection-loader.js.map +2 -2
  50. package/package.json +3 -10
  51. package/src/lib/__tests__/number.test.ts +1 -24
  52. package/src/lib/auth/__tests__/server.test.ts +0 -14
  53. package/src/lib/auth/server.ts +1 -1
  54. package/src/lib/bootstrap/__tests__/dynamicLoader.appDi.test.ts +2 -2
  55. package/src/lib/bootstrap/__tests__/dynamicLoader.appModuleOverrides.test.ts +2 -2
  56. package/src/lib/bootstrap/__tests__/dynamicLoader.cacheRecovery.test.ts +2 -2
  57. package/src/lib/bootstrap/__tests__/dynamicLoader.commandInterceptors.test.ts +2 -2
  58. package/src/lib/bootstrap/__tests__/dynamicLoader.tsconfig.test.ts +2 -2
  59. package/src/lib/bootstrap/__tests__/factory.test.ts +6 -18
  60. package/src/lib/bootstrap/dynamicLoader.ts +5 -63
  61. package/src/lib/bootstrap/factory.ts +3 -8
  62. package/src/lib/bootstrap/types.ts +1 -5
  63. package/src/lib/catalog-visibility/index.ts +0 -2
  64. package/src/lib/commands/__tests__/command-bus.test.ts +1 -100
  65. package/src/lib/commands/command-bus.ts +10 -42
  66. package/src/lib/commands/command-interceptor.ts +0 -4
  67. package/src/lib/commands/types.ts +0 -14
  68. package/src/lib/crud/__tests__/exporters.test.ts +0 -18
  69. package/src/lib/crud/__tests__/ids.test.ts +1 -34
  70. package/src/lib/crud/exporters.ts +1 -1
  71. package/src/lib/crud/ids.ts +0 -24
  72. package/src/lib/db/__tests__/pg-errors.test.ts +1 -68
  73. package/src/lib/db/pg-errors.ts +0 -35
  74. package/src/lib/encryption/__tests__/tenantDataEncryptionService.test.ts +0 -23
  75. package/src/lib/localization/__tests__/translatable-fields.test.ts +0 -17
  76. package/src/lib/localization/index.ts +1 -8
  77. package/src/lib/localization/translatable-fields.ts +0 -46
  78. package/src/lib/number.ts +0 -13
  79. package/src/lib/openapi/generator.ts +77 -106
  80. package/src/lib/query/engine.ts +8 -58
  81. package/src/lib/query/join-utils.ts +1 -1
  82. package/src/lib/query/types.ts +1 -13
  83. package/src/lib/url.ts +0 -30
  84. package/src/lib/webhooks/__tests__/body.test.ts +0 -48
  85. package/src/lib/webhooks/body.ts +4 -11
  86. package/src/lib/webhooks/index.ts +0 -1
  87. package/src/modules/integrations/types.ts +0 -6
  88. package/src/modules/notifications/types.ts +0 -7
  89. package/src/modules/payment_gateways/__tests__/types.test.ts +0 -44
  90. package/src/modules/payment_gateways/types.ts +6 -52
  91. package/src/modules/registry.ts +0 -5
  92. package/src/modules/search.ts +0 -39
  93. package/src/modules/widgets/injection-loader.ts +3 -33
  94. package/dist/lib/bootstrap/next-subpath-resolve-hook-worker.js +0 -6
  95. package/dist/lib/bootstrap/next-subpath-resolve-hook-worker.js.map +0 -7
  96. package/dist/lib/bootstrap/next-subpath-resolve-hook.js +0 -62
  97. package/dist/lib/bootstrap/next-subpath-resolve-hook.js.map +0 -7
  98. package/dist/lib/catalog-visibility/canonicalizeEffectiveScope.js +0 -33
  99. package/dist/lib/catalog-visibility/canonicalizeEffectiveScope.js.map +0 -7
  100. package/dist/lib/catalog-visibility/hashEffectiveScope.js +0 -9
  101. package/dist/lib/catalog-visibility/hashEffectiveScope.js.map +0 -7
  102. package/dist/lib/db/advisoryLock.js +0 -172
  103. package/dist/lib/db/advisoryLock.js.map +0 -7
  104. package/dist/lib/query/overlap.js +0 -58
  105. package/dist/lib/query/overlap.js.map +0 -7
  106. package/dist/modules/notifications/safeHref.js +0 -20
  107. package/dist/modules/notifications/safeHref.js.map +0 -7
  108. package/src/lib/__tests__/url.cross-site.test.ts +0 -140
  109. package/src/lib/bootstrap/__tests__/dynamicLoader.externalSubpath.test.ts +0 -141
  110. package/src/lib/bootstrap/__tests__/next-subpath-resolve-hook.test.ts +0 -174
  111. package/src/lib/bootstrap/next-subpath-resolve-hook-worker.ts +0 -3
  112. package/src/lib/bootstrap/next-subpath-resolve-hook.ts +0 -130
  113. package/src/lib/catalog-visibility/__tests__/hashEffectiveScope.test.ts +0 -121
  114. package/src/lib/catalog-visibility/canonicalizeEffectiveScope.ts +0 -41
  115. package/src/lib/catalog-visibility/hashEffectiveScope.ts +0 -8
  116. package/src/lib/db/__tests__/advisoryLock.integration.test.ts +0 -343
  117. package/src/lib/db/__tests__/advisoryLock.test.ts +0 -564
  118. package/src/lib/db/advisoryLock.ts +0 -271
  119. package/src/lib/openapi/__tests__/optional-path-params.test.ts +0 -102
  120. package/src/lib/query/__tests__/empty-ids-filter.pg.test.ts +0 -89
  121. package/src/lib/query/__tests__/engine.empty-in-filter.test.ts +0 -79
  122. package/src/lib/query/__tests__/overlap.test.ts +0 -219
  123. package/src/lib/query/overlap.ts +0 -106
  124. package/src/modules/notifications/safeHref.ts +0 -19
  125. package/src/modules/widgets/__tests__/injection-loader.partitioned-registration.test.ts +0 -78
@@ -1,3 +1,3 @@
1
1
  [generate-countries] up to date (259 countries)
2
- [build:shared] found 321 entry points
2
+ [build:shared] found 314 entry points
3
3
  [build:shared] built successfully
package/AGENTS.md CHANGED
@@ -38,14 +38,14 @@ yarn workspace @open-mercato/shared build
38
38
  | `auth/organizationScope` | When an organization-scoped API route must resolve the caller's organization — falls back to `actorOrgId` for an "all organizations" selection, but only while the effective tenant is still the actor's tenant. On `null` for an authenticated caller answer with `organizationScopeRequiredResponse()` (400, code `organization_scope_required`) — never 401 | `@open-mercato/shared/lib/auth/organizationScope` — `resolveActiveOrganizationId(auth)`, `organizationScopeRequiredResponse()` |
39
39
  | `boolean/` | When parsing boolean strings from env/query params | `@open-mercato/shared/lib/boolean` |
40
40
  | `browser/` | When persisting client UI state to `localStorage` — use the safe wrappers and the versioned-envelope helper instead of raw `localStorage` reads/writes | `@open-mercato/shared/lib/browser/safeLocalStorage`, `@open-mercato/shared/lib/browser/versionedPreference` |
41
- | `catalog-visibility/` | When combining buyer-facing catalog assortment grants (group-level, channel-level) into one effective visibility check — `AssortmentScope`/`EffectiveAssortmentScope` types plus the pure `matchesOne`/`matchesScope`/`unionScopes`/`intersectScopes` algebra, plus `canonicalizeEffectiveScope`/`hashEffectiveScope` (16-hex digest for cache keys; the hash uses `node:crypto`, server-only). Imports nothing from `catalog`, `customer_groups`, `ecommerce`, or `cart` by construction; `customer_groups`'s `resolveAssortmentScope()` and `ecommerce`'s `BuyerContext.assortmentScope` composition build on top of it | `@open-mercato/shared/lib/catalog-visibility` |
41
+ | `catalog-visibility/` | When combining buyer-facing catalog assortment grants (group-level, channel-level) into one effective visibility check — `AssortmentScope`/`EffectiveAssortmentScope` types plus the pure `matchesOne`/`matchesScope`/`unionScopes`/`intersectScopes` algebra. Imports nothing from `catalog`, `customer_groups`, `ecommerce`, or `cart` by construction; `customer_groups`'s `resolveAssortmentScope()` and `ecommerce`'s `BuyerContext.assortmentScope` composition build on top of it | `@open-mercato/shared/lib/catalog-visibility` |
42
42
  | `commands/` | When implementing undo/redo command pattern | `@open-mercato/shared/lib/commands` |
43
43
  | `commands/flush` | When a command mutates entities across multiple phases (scalar + relation syncs) — wraps phases in a single atomic flush | `@open-mercato/shared/lib/commands/flush` — `withAtomicFlush(em, phases, { transaction? })` |
44
44
  | `commands/runCrudCommandWrite` | When a command writes an entity + custom fields + CRUD/index side effects in one logical operation — composes fork → atomic flush → custom-field write → side-effect queue in the only correct order. **Prefer this over composing the primitives by hand for new commands.** | `@open-mercato/shared/lib/commands/runCrudCommandWrite` — `runCrudCommandWrite({ ctx, entityId, action, scope, phases, customFields?, events?, indexer?, sideEffect })` |
45
45
  | `crud/` | When building CRUD routes | `@open-mercato/shared/lib/crud` |
46
46
  | `custom-fields/` | When handling custom field payloads | `@open-mercato/shared/lib/custom-fields` |
47
47
  | `data/` | When you need `DataEngine` or `QueryEngine` types | `@open-mercato/shared/lib/data/engine` |
48
- | `db/` | When resolving the ORM/connection-pool config (`resolvePoolConfig`, pool/timeout env knobs); when serializing a bounded write across processes under a Postgres transaction advisory lock (`withAdvisoryXactLock` — pass the request EntityManager; `fn` does all DB I/O on `txEm`, flushes its own writes, makes at most one external call, never nests `transactional` or forks; `maxConcurrentHolders` caps holders per process) | `@open-mercato/shared/lib/db/mikro`, `@open-mercato/shared/lib/db/advisoryLock` |
48
+ | `db/` | When resolving the ORM/connection-pool config (`resolvePoolConfig`, pool/timeout env knobs) | `@open-mercato/shared/lib/db/mikro` |
49
49
  | `delivery/` | When scheduling delivery/retry attempts — exponential backoff with jitter for delivery pipelines (currently the push delivery worker) | `@open-mercato/shared/lib/delivery/retry` (`calculateBackoffDelayMs`) |
50
50
  | `di/` | When setting up dependency injection (Awilix). The app-level hook (`src/di.ts` → `register`) is wired explicitly in BOTH bootstrap paths — `src/bootstrap.ts` for the Next.js runtime, `bootstrapFromAppRoot()` for worker/scheduler/CLI processes. Never rely on the legacy `import('@/di')` fallback: the alias does not exist outside the app bundler | `@open-mercato/shared/lib/di` |
51
51
  | `encryption/` | When querying encrypted entities (MUST use instead of raw `em.find`) | `@open-mercato/shared/lib/encryption/find` |
@@ -53,7 +53,7 @@ yarn workspace @open-mercato/shared build
53
53
  | `indexers/` | When building query index helpers | `@open-mercato/shared/lib/indexers` |
54
54
  | `logger/` | When emitting diagnostics — `createLogger(namespace)` instead of raw `console.*` (migrate incrementally, Boy Scout rule). Message-first with structured fields (`logger.warn('Payload too large', { event, maxBytes })`), errors under `err`, `child(bindings)` for context, `getLogLevel()`/`isLevelEnabled()` to gate expensive fields; level via `OM_LOG_LEVEL`. Never log credentials, PII, or payload bodies | `@open-mercato/shared/lib/logger` |
55
55
  | `modules/` | When registering or listing modules; `onModulesRegistered(listener)` subscribes to (re-)registrations so a cache derived from the module list can drop what it built from an incomplete one — bootstrap may register an i18n-only set before the full module list merges in, and listeners fire only when the registered set actually changed, so nothing is added to the request path. Its governing contract — notification timing, fail-soft handling of a throwing or rejecting listener, snapshot-based change detection, listener lifetime under HMR, and the globals a test MUST clear — is [`.ai/specs/2026-08-12-module-registry-registration-listeners.md`](../../.ai/specs/2026-08-12-module-registry-registration-listeners.md); `surfaceFingerprint` gives a deploy-time hash of the enabled modules, their declared ACL features, and the backend route manifest — mix it into any cache key whose payload is derived from those (no DB write exists to tag-invalidate on, so an omitted fingerprint serves the pre-deploy payload forever). It cannot see React-element fields such as a route `icon`, so callers MUST still pass a `ttl` | `@open-mercato/shared/lib/modules/registry`, `@open-mercato/shared/lib/modules/surfaceFingerprint` |
56
- | `number.ts` | When parsing numeric strings from env/query params with a fallback and optional min/integer constraint (`parseNumberWithDefault`), or when parsing a number a USER TYPED, which carries the application locale's decimal/group separators (`parseLocaleNumber`, returns `null` — never a silent `0` — on unparseable input). MUST NOT run API/DB values through `parseLocaleNumber`; those are already numbers. When an input REDISPLAYS a stored number (blur, reload, post-save), render it with `formatLocaleNumberInput(value, locale)`, never `String(value)`, which always emits a dot | `@open-mercato/shared/lib/number` |
56
+ | `number.ts` | When parsing numeric strings from env/query params with a fallback and optional min/integer constraint (`parseNumberWithDefault`), or when parsing a number a USER TYPED, which carries the application locale's decimal/group separators (`parseLocaleNumber`, returns `null` — never a silent `0` — on unparseable input). MUST NOT run API/DB values through `parseLocaleNumber`; those are already numbers | `@open-mercato/shared/lib/number` |
57
57
  | `openapi/` | When generating CRUD OpenAPI specs | `@open-mercato/shared/lib/openapi/crud` |
58
58
  | `profiler/` | When profiling with `OM_PROFILE` env flag | `@open-mercato/shared/lib/profiler` |
59
59
  | `search/` | When resolving record ids from the `search_tokens` index — MUST use instead of hand-rolling the Kysely lookup, and MUST be unioned into (or replace) any `$ilike` filter on a column an encryption map covers | `@open-mercato/shared/lib/search/tokenLookup` |
@@ -192,7 +192,7 @@ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
192
192
  const { t } = await resolveTranslations()
193
193
  ```
194
194
 
195
- **User-facing vs internal errors.** When a `throw new Error(...)`, `createCrudFormError(...)`, `raiseCrudError(...)`, `toast.*(...)`, `CrudHttpError`/helper, or `NextResponse.json({ error })` message will surface to a user, route it through `t('module.errors.<key>')`. When it's a developer-only assertion (programming bug, container/wiring issue, contract violation that should never be triggered at runtime), prefix the literal with `[internal]` so the i18n hardcoded-string checker treats it as opted out:
195
+ **User-facing vs internal errors.** When a `throw new Error(...)`, `createCrudFormError(...)`, `raiseCrudError(...)`, or `toast.*(...)` message will surface to a user, route it through `t('module.errors.<key>')`. When it's a developer-only assertion (programming bug, container/wiring issue, contract violation that should never be triggered at runtime), prefix the literal with `[internal]` so the i18n hardcoded-string checker treats it as opted out:
196
196
 
197
197
  ```typescript
198
198
  throw new Error('[internal] Event bus not available in container')
@@ -275,7 +275,7 @@ async function resolveAuthFromRequestDetailed(req) {
275
275
  if (authHeader.toLowerCase().startsWith("bearer ")) token = authHeader.slice(7).trim();
276
276
  if (!token) {
277
277
  const match = cookieHeader.match(/(?:^|;\s*)auth_token=([^;]+)/);
278
- if (match) token = decodeCookieValue(match[1]) ?? void 0;
278
+ if (match) token = decodeURIComponent(match[1]);
279
279
  }
280
280
  if (token) {
281
281
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/auth/server.ts"],
4
- "sourcesContent": ["import { cookies } from 'next/headers.js'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { isMfaPendingJwtPayload, verifyJwt } from './jwt'\nimport { isMfaPendingAccessAllowed } from './mfaPendingAccess'\nimport { getSharedApiKeyAuthCache } from './apiKeyAuthCache'\nimport { isTransientDbError } from '@open-mercato/shared/lib/db/pg-errors'\n\nfunction readRequestPathname(req: Request): string | null {\n try {\n return new URL(req.url).pathname\n } catch {\n return null\n }\n}\n\nconst TENANT_COOKIE_NAME = 'om_selected_tenant'\nconst ORGANIZATION_COOKIE_NAME = 'om_selected_org'\nconst ALL_ORGANIZATIONS_COOKIE_VALUE = '__all__'\nconst SUPERADMIN_ROLE = 'superadmin'\n\nexport type AuthContext = {\n sub: string\n sid?: string | null\n tenantId: string | null\n orgId: string | null\n email?: string\n roles?: string[]\n isApiKey?: boolean\n userId?: string\n keyId?: string\n keyName?: string\n [k: string]: unknown\n} | null\n\ntype CookieOverride = { applied: boolean; value: string | null }\n// 'error' means auth could not be determined because of a transient/unexpected\n// failure (DB unavailable, connection-pool exhaustion, statement timeout, \u2026) \u2014\n// NOT because the token is genuinely invalid. Callers MUST NOT clear the user's\n// session cookies for 'error'; doing so would log everyone out at once during a\n// shared infrastructure blip (issue #4176).\ntype AuthResolutionStatus = 'authenticated' | 'missing' | 'invalid' | 'error'\ntype AuthResolution = {\n auth: AuthContext\n status: AuthResolutionStatus\n}\n\n// Thrown by `resolveCanonicalInteractiveAuthContext` when the canonical auth\n// lookup itself fails unexpectedly (as opposed to resolving to a genuine\n// \"not authorized\" null). Kept distinct so resolvers can map it to the\n// non-destructive 'error' status instead of the cookie-clearing 'invalid'.\nexport class AuthResolutionUnavailableError extends Error {\n constructor(cause?: unknown) {\n super('Auth resolution unavailable')\n this.name = 'AuthResolutionUnavailableError'\n if (cause !== undefined) (this as { cause?: unknown }).cause = cause\n }\n}\n\n// Symbol-keyed trusted auth context. Set on synthetic Request objects by\n// callers that have already authenticated (e.g. the AI in-process operation\n// runner) so downstream auth resolution short-circuits without re-running\n// cookie/JWT/API-key parsing. The hook is fail-open: if absent the normal\n// resolution path runs unchanged.\nexport const TRUSTED_AUTH_CONTEXT_SYMBOL = Symbol.for('open-mercato.auth.trustedContext')\n\nexport type TrustedAuthContextEnvelope = {\n auth: AuthContext\n status?: AuthResolutionStatus\n}\n\n/**\n * Attach an already-resolved auth context to a synthetic request.\n *\n * INVARIANT callers MUST uphold: `envelope.auth` has to be the product of a gated resolution \u2014\n * `getAuthFromRequest` / `getAuthFromCookies` (or an equivalently validated principal such as an\n * API-key record). The envelope short-circuits `resolveAuthFromRequestDetailed` ahead of both the\n * MFA-pending gate and `resolveCanonicalStaffAuthContext`, so an envelope built straight from an\n * unvalidated JWT would reinstate the MFA bypass this module closes and skip session-revocation\n * checks as well. Never populate it from raw request credentials.\n */\nexport function attachTrustedAuthContext(\n request: Request,\n envelope: TrustedAuthContextEnvelope\n): Request {\n ;(request as unknown as Record<symbol, TrustedAuthContextEnvelope>)[TRUSTED_AUTH_CONTEXT_SYMBOL] = envelope\n return request\n}\n\nfunction readTrustedAuthContext(request: Request): TrustedAuthContextEnvelope | null {\n const carrier = request as unknown as Record<symbol, unknown>\n const envelope = carrier[TRUSTED_AUTH_CONTEXT_SYMBOL]\n if (!envelope || typeof envelope !== 'object') return null\n const candidate = envelope as TrustedAuthContextEnvelope\n if (!('auth' in candidate)) return null\n return candidate\n}\n\nfunction decodeCookieValue(raw: string | undefined): string | null {\n if (raw === undefined) return null\n try {\n const decoded = decodeURIComponent(raw)\n return decoded ?? null\n } catch {\n return raw ?? null\n }\n}\n\nfunction readCookieFromHeader(header: string | null | undefined, name: string): string | undefined {\n if (!header) return undefined\n const parts = header.split(';')\n for (const part of parts) {\n const trimmed = part.trim()\n if (trimmed.startsWith(`${name}=`)) {\n return trimmed.slice(name.length + 1)\n }\n }\n return undefined\n}\n\n/**\n * A blank `om_selected_tenant` is \"no selection\", not a deliberate \"no tenant\".\n *\n * Unlike the organization cookie there is no all-tenants sentinel to express, and the tenant\n * selector renders with `includeEmptyOption={false}`, so no UI produces a blank value. Treating it\n * as an applied override nulled `tenantId` for the whole super-admin session, which is what turned\n * a cosmetic client bug into `tenantId ?? ''` reaching a NOT NULL uuid column. Reporting the\n * override as not applied instead keeps the tenant carried in the token and remediates an\n * already-poisoned browser on its next request, whatever wrote the cookie.\n */\nfunction resolveTenantOverride(raw: string | undefined): CookieOverride {\n if (raw === undefined) return { applied: false, value: null }\n const decoded = decodeCookieValue(raw)\n if (!decoded) return { applied: false, value: null }\n const trimmed = decoded.trim()\n if (!trimmed) return { applied: false, value: null }\n return { applied: true, value: trimmed }\n}\n\nfunction resolveOrganizationOverride(raw: string | undefined): CookieOverride {\n if (raw === undefined) return { applied: false, value: null }\n const decoded = decodeCookieValue(raw)\n if (!decoded || decoded === ALL_ORGANIZATIONS_COOKIE_VALUE) {\n return { applied: true, value: null }\n }\n const trimmed = decoded.trim()\n if (!trimmed || trimmed === ALL_ORGANIZATIONS_COOKIE_VALUE) {\n return { applied: true, value: null }\n }\n return { applied: true, value: trimmed }\n}\n\nfunction isSuperAdminAuth(auth: AuthContext | null | undefined): boolean {\n if (!auth) return false\n return (auth as Record<string, unknown>).isSuperAdmin === true\n}\n\nfunction applySuperAdminScope(\n auth: AuthContext,\n tenantCookie: string | undefined,\n orgCookie: string | undefined\n): AuthContext {\n if (!auth || !isSuperAdminAuth(auth)) return auth\n\n const tenantOverride = resolveTenantOverride(tenantCookie)\n const orgOverride = resolveOrganizationOverride(orgCookie)\n if (!tenantOverride.applied && !orgOverride.applied) return auth\n\n type MutableAuthContext = Exclude<AuthContext, null> & {\n actorTenantId?: string | null\n actorOrgId?: string | null\n }\n const baseAuth = auth as Exclude<AuthContext, null>\n const next: MutableAuthContext = { ...baseAuth }\n if (tenantOverride.applied) {\n if (!('actorTenantId' in next)) next.actorTenantId = auth?.tenantId ?? null\n next.tenantId = tenantOverride.value\n }\n if (orgOverride.applied) {\n if (!('actorOrgId' in next)) next.actorOrgId = auth?.orgId ?? null\n next.orgId = orgOverride.value\n }\n next.isSuperAdmin = true\n const existingRoles = Array.isArray(next.roles) ? next.roles : []\n if (!existingRoles.some((role) => typeof role === 'string' && role.trim().toLowerCase() === SUPERADMIN_ROLE)) {\n next.roles = [...existingRoles, 'superadmin']\n }\n return next\n}\n\nasync function resolveApiKeyAuth(secret: string): Promise<AuthContext> {\n if (!secret) return null\n const cache = getSharedApiKeyAuthCache()\n const cached = cache.get(secret)\n if (cached !== undefined) return cached as AuthContext\n try {\n const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n const { findApiKeyBySecret } = await import('@open-mercato/core/modules/api_keys/services/apiKeyService')\n const { Role, RoleAcl, User } = await import('@open-mercato/core/modules/auth/data/entities')\n const { Organization, Tenant } = await import('@open-mercato/core/modules/directory/data/entities')\n\n const record = await findApiKeyBySecret(em, secret)\n if (!record) {\n cache.setMiss(secret)\n return null\n }\n\n const roleIds = Array.isArray(record.rolesJson)\n ? record.rolesJson.filter((value): value is string => typeof value === 'string' && value.length > 0)\n : []\n const roles = roleIds.length\n ? await em.find(Role, { id: { $in: roleIds }, deletedAt: null })\n : []\n const roleNames = roles.map((role) => role.name).filter((name): name is string => typeof name === 'string' && name.length > 0)\n\n // A role-level super-admin grant is authorization-grade only when it is genuinely\n // unrestricted: the grant itself must not be organization-scoped, it must belong to the\n // key's tenant, and the key must not be bound to a single organization. RbacService applies\n // the same intersection when projecting the scoped ACL, but generic guards\n // (tenantAccess.resolveIsSuperAdmin, the scoped-API helpers) trust this raw bit *before*\n // live RBAC runs \u2014 so an organization-restricted key must never carry it.\n let keyIsSuperAdmin = false\n const keyOrganizationId = typeof record.organizationId === 'string' && record.organizationId.trim().length > 0\n ? record.organizationId.trim()\n : null\n if (roleIds.length && !keyOrganizationId) {\n const superAcls = await em.find(\n RoleAcl,\n {\n role: { $in: roleIds } as any,\n tenantId: record.tenantId ?? null,\n isSuperAdmin: true,\n deletedAt: null,\n } as any,\n )\n keyIsSuperAdmin = superAcls.some((acl) => {\n const organizations = Array.isArray((acl as { organizationsJson?: string[] | null }).organizationsJson)\n ? (acl as { organizationsJson?: string[] | null }).organizationsJson as string[]\n : null\n // An empty list means \"inherit the key's own binding\"; with no binding that is tenant-wide.\n return !organizations || organizations.length === 0 || organizations.includes('__all__')\n })\n }\n\n if (cache.shouldWriteLastUsed(record.id)) {\n try {\n record.lastUsedAt = new Date()\n await em.persist(record).flush()\n } catch {\n // best-effort update; ignore write failures\n }\n }\n\n // Ephemeral session keys are always user-bound. Regular keys retain their\n // legacy creator identity, while tenant-scoped regular keys ignore only the\n // creator's concrete organization when validating the wider key scope.\n // Keep every session marker fail-closed so a malformed session key cannot\n // fall back to the regular key path and escape its user/scope binding.\n const isSessionBoundKey = Boolean(\n record.sessionToken\n || record.sessionUserId\n || record.sessionSecretEncrypted\n || record.opencodeSessionId\n )\n const actualUserId = isSessionBoundKey\n ? record.sessionUserId ?? null\n : record.createdBy ?? null\n\n if (isSessionBoundKey && !actualUserId) {\n cache.setMiss(secret)\n return null\n }\n\n if (actualUserId) {\n const user = await em.findOne(User, { id: actualUserId, deletedAt: null })\n if (!user) {\n cache.setMiss(secret)\n return null\n }\n if ((user.tenantId ?? null) !== (record.tenantId ?? null)) {\n cache.setMiss(secret)\n return null\n }\n const requiresExactOrganization = isSessionBoundKey || Boolean(record.organizationId)\n if (requiresExactOrganization && (user.organizationId ?? null) !== (record.organizationId ?? null)) {\n cache.setMiss(secret)\n return null\n }\n } else {\n if (record.tenantId) {\n const tenant = await em.findOne(Tenant, { id: record.tenantId, deletedAt: null, isActive: true })\n if (!tenant) {\n cache.setMiss(secret)\n return null\n }\n }\n if (record.organizationId) {\n const organization = await em.findOne(Organization, { id: record.organizationId, deletedAt: null, isActive: true })\n if (!organization) {\n cache.setMiss(secret)\n return null\n }\n if (record.tenantId && String(organization.tenant.id) !== record.tenantId) {\n cache.setMiss(secret)\n return null\n }\n }\n }\n\n const auth: Exclude<AuthContext, null> = {\n sub: `api_key:${record.id}`,\n tenantId: record.tenantId ?? null,\n orgId: record.organizationId ?? null,\n roles: roleNames,\n isApiKey: true,\n isSuperAdmin: keyIsSuperAdmin,\n keyId: record.id,\n keyName: record.name,\n ...(actualUserId ? { userId: actualUserId } : {}),\n }\n cache.setSuccess(secret, auth, record.expiresAt ? record.expiresAt.getTime() : null)\n return auth\n } catch (err) {\n // A transient DB failure (pool exhausted, `max_connections` reached, DB\n // restarting) means we could not confirm the key \u2014 NOT that it is invalid.\n // Surface it so callers return a retryable 503 instead of masking it as an\n // auth miss (401). Genuine misses already returned `null` above.\n if (isTransientDbError(err)) {\n throw new AuthResolutionUnavailableError(err)\n }\n return null\n }\n}\n\nfunction extractApiKey(req: Request): string | null {\n const header = (req.headers.get('x-api-key') || '').trim()\n if (header) return header\n const authHeader = (req.headers.get('authorization') || '').trim()\n if (authHeader.toLowerCase().startsWith('apikey ')) {\n return authHeader.slice(7).trim()\n }\n return null\n}\n\nasync function resolveCanonicalInteractiveAuthContext(auth: AuthContext): Promise<AuthContext> {\n if (!auth || auth.isApiKey) return auth\n if (typeof auth.sub !== 'string' || auth.sub.trim().length === 0) return null\n\n try {\n const [{ createRequestContainer }, { resolveCanonicalStaffAuthContext }] = await Promise.all([\n import('@open-mercato/shared/lib/di/container'),\n import('@open-mercato/core/modules/auth/lib/sessionIntegrity'),\n ])\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n return await resolveCanonicalStaffAuthContext(em, auth)\n } catch (err) {\n // A thrown error here means we could not check the token against the\n // database (DB down, pool exhausted, timeout). This is NOT the same as the\n // token being invalid \u2014 surface it so callers keep the session intact and\n // fail the request transiently instead of force-logging the user out.\n throw new AuthResolutionUnavailableError(err)\n }\n}\n\nexport async function resolveAuthFromCookiesDetailed(): Promise<AuthResolution> {\n const cookieStore = await cookies()\n const token = cookieStore.get('auth_token')?.value\n if (!token) return { auth: null, status: 'missing' }\n try {\n const payload = verifyJwt(token) as AuthContext\n if (!payload) return { auth: null, status: 'invalid' }\n if (payload.type === 'customer') return { auth: null, status: 'invalid' }\n // MFA-pending tokens are provisional: pages never complete the second factor, so they\n // must not resolve to an authenticated context anywhere in the RSC/page flow.\n if (isMfaPendingJwtPayload(payload)) return { auth: null, status: 'invalid' }\n const canonicalAuth = await resolveCanonicalInteractiveAuthContext(payload)\n if (!canonicalAuth) return { auth: null, status: 'invalid' }\n const tenantCookie = cookieStore.get(TENANT_COOKIE_NAME)?.value\n const orgCookie = cookieStore.get(ORGANIZATION_COOKIE_NAME)?.value\n return {\n auth: applySuperAdminScope(canonicalAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n } catch (err) {\n if (err instanceof AuthResolutionUnavailableError) return { auth: null, status: 'error' }\n return { auth: null, status: 'invalid' }\n }\n}\n\nexport async function getAuthFromCookies(): Promise<AuthContext> {\n return (await resolveAuthFromCookiesDetailed()).auth\n}\n\nexport async function resolveAuthFromRequestDetailed(req: Request): Promise<AuthResolution> {\n // Deliberately ahead of the MFA-pending gate below: the envelope carries a context that was\n // already gated by its producer (see `attachTrustedAuthContext`), not raw request credentials.\n const trusted = readTrustedAuthContext(req)\n if (trusted) {\n return {\n auth: trusted.auth,\n status: trusted.status ?? (trusted.auth ? 'authenticated' : 'missing'),\n }\n }\n const cookieHeader = req.headers.get('cookie') || ''\n const tenantCookie = readCookieFromHeader(cookieHeader, TENANT_COOKIE_NAME)\n const orgCookie = readCookieFromHeader(cookieHeader, ORGANIZATION_COOKIE_NAME)\n const authHeader = (req.headers.get('authorization') || '').trim()\n let token: string | undefined\n let hadInvalidInteractiveToken = false\n let hadUnavailableResolution = false\n if (authHeader.toLowerCase().startsWith('bearer ')) token = authHeader.slice(7).trim()\n if (!token) {\n const match = cookieHeader.match(/(?:^|;\\s*)auth_token=([^;]+)/)\n if (match) token = decodeCookieValue(match[1]) ?? undefined\n }\n if (token) {\n try {\n const payload = verifyJwt(token) as AuthContext\n if (payload && payload.type === 'customer') return { auth: null, status: 'invalid' }\n if (payload && isMfaPendingJwtPayload(payload)) {\n // MFA-pending tokens authenticate only the registered challenge-completion routes;\n // everywhere else they resolve to `invalid` so the dispatcher answers 401 (clearing\n // staff auth cookies) instead of restoring the account's roles/features.\n if (!isMfaPendingAccessAllowed(req.method, readRequestPathname(req))) {\n return { auth: null, status: 'invalid' }\n }\n }\n if (payload) {\n const canonicalAuth = await resolveCanonicalInteractiveAuthContext(payload)\n if (canonicalAuth) {\n return {\n auth: applySuperAdminScope(canonicalAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n }\n hadInvalidInteractiveToken = true\n }\n } catch (err) {\n // Transient/unexpected canonical-resolution failures must not invalidate\n // the token \u2014 surface them so we return 'error' (retryable) rather than\n // clearing the session cookies.\n if (err instanceof AuthResolutionUnavailableError) hadUnavailableResolution = true\n else hadInvalidInteractiveToken = true\n }\n }\n\n const resolveUnauthenticatedStatus = (): AuthResolutionStatus =>\n hadUnavailableResolution ? 'error' : hadInvalidInteractiveToken ? 'invalid' : 'missing'\n\n const apiKey = extractApiKey(req)\n if (!apiKey) {\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n let apiAuth: AuthContext\n try {\n apiAuth = await resolveApiKeyAuth(apiKey)\n } catch (err) {\n // Only a transient canonical-resolution failure maps to 'error' (retryable\n // 503), mirroring the interactive-token path above. Anything else is an\n // unexpected bug \u2014 rethrow so it surfaces as a 500 rather than being masked\n // as an auth failure.\n if (!(err instanceof AuthResolutionUnavailableError)) {\n throw err\n }\n hadUnavailableResolution = true\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n if (!apiAuth) {\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n return {\n auth: applySuperAdminScope(apiAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n}\n\nexport async function getAuthFromRequest(req: Request): Promise<AuthContext> {\n return (await resolveAuthFromRequestDetailed(req)).auth\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { cookies } from 'next/headers.js'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { isMfaPendingJwtPayload, verifyJwt } from './jwt'\nimport { isMfaPendingAccessAllowed } from './mfaPendingAccess'\nimport { getSharedApiKeyAuthCache } from './apiKeyAuthCache'\nimport { isTransientDbError } from '@open-mercato/shared/lib/db/pg-errors'\n\nfunction readRequestPathname(req: Request): string | null {\n try {\n return new URL(req.url).pathname\n } catch {\n return null\n }\n}\n\nconst TENANT_COOKIE_NAME = 'om_selected_tenant'\nconst ORGANIZATION_COOKIE_NAME = 'om_selected_org'\nconst ALL_ORGANIZATIONS_COOKIE_VALUE = '__all__'\nconst SUPERADMIN_ROLE = 'superadmin'\n\nexport type AuthContext = {\n sub: string\n sid?: string | null\n tenantId: string | null\n orgId: string | null\n email?: string\n roles?: string[]\n isApiKey?: boolean\n userId?: string\n keyId?: string\n keyName?: string\n [k: string]: unknown\n} | null\n\ntype CookieOverride = { applied: boolean; value: string | null }\n// 'error' means auth could not be determined because of a transient/unexpected\n// failure (DB unavailable, connection-pool exhaustion, statement timeout, \u2026) \u2014\n// NOT because the token is genuinely invalid. Callers MUST NOT clear the user's\n// session cookies for 'error'; doing so would log everyone out at once during a\n// shared infrastructure blip (issue #4176).\ntype AuthResolutionStatus = 'authenticated' | 'missing' | 'invalid' | 'error'\ntype AuthResolution = {\n auth: AuthContext\n status: AuthResolutionStatus\n}\n\n// Thrown by `resolveCanonicalInteractiveAuthContext` when the canonical auth\n// lookup itself fails unexpectedly (as opposed to resolving to a genuine\n// \"not authorized\" null). Kept distinct so resolvers can map it to the\n// non-destructive 'error' status instead of the cookie-clearing 'invalid'.\nexport class AuthResolutionUnavailableError extends Error {\n constructor(cause?: unknown) {\n super('Auth resolution unavailable')\n this.name = 'AuthResolutionUnavailableError'\n if (cause !== undefined) (this as { cause?: unknown }).cause = cause\n }\n}\n\n// Symbol-keyed trusted auth context. Set on synthetic Request objects by\n// callers that have already authenticated (e.g. the AI in-process operation\n// runner) so downstream auth resolution short-circuits without re-running\n// cookie/JWT/API-key parsing. The hook is fail-open: if absent the normal\n// resolution path runs unchanged.\nexport const TRUSTED_AUTH_CONTEXT_SYMBOL = Symbol.for('open-mercato.auth.trustedContext')\n\nexport type TrustedAuthContextEnvelope = {\n auth: AuthContext\n status?: AuthResolutionStatus\n}\n\n/**\n * Attach an already-resolved auth context to a synthetic request.\n *\n * INVARIANT callers MUST uphold: `envelope.auth` has to be the product of a gated resolution \u2014\n * `getAuthFromRequest` / `getAuthFromCookies` (or an equivalently validated principal such as an\n * API-key record). The envelope short-circuits `resolveAuthFromRequestDetailed` ahead of both the\n * MFA-pending gate and `resolveCanonicalStaffAuthContext`, so an envelope built straight from an\n * unvalidated JWT would reinstate the MFA bypass this module closes and skip session-revocation\n * checks as well. Never populate it from raw request credentials.\n */\nexport function attachTrustedAuthContext(\n request: Request,\n envelope: TrustedAuthContextEnvelope\n): Request {\n ;(request as unknown as Record<symbol, TrustedAuthContextEnvelope>)[TRUSTED_AUTH_CONTEXT_SYMBOL] = envelope\n return request\n}\n\nfunction readTrustedAuthContext(request: Request): TrustedAuthContextEnvelope | null {\n const carrier = request as unknown as Record<symbol, unknown>\n const envelope = carrier[TRUSTED_AUTH_CONTEXT_SYMBOL]\n if (!envelope || typeof envelope !== 'object') return null\n const candidate = envelope as TrustedAuthContextEnvelope\n if (!('auth' in candidate)) return null\n return candidate\n}\n\nfunction decodeCookieValue(raw: string | undefined): string | null {\n if (raw === undefined) return null\n try {\n const decoded = decodeURIComponent(raw)\n return decoded ?? null\n } catch {\n return raw ?? null\n }\n}\n\nfunction readCookieFromHeader(header: string | null | undefined, name: string): string | undefined {\n if (!header) return undefined\n const parts = header.split(';')\n for (const part of parts) {\n const trimmed = part.trim()\n if (trimmed.startsWith(`${name}=`)) {\n return trimmed.slice(name.length + 1)\n }\n }\n return undefined\n}\n\n/**\n * A blank `om_selected_tenant` is \"no selection\", not a deliberate \"no tenant\".\n *\n * Unlike the organization cookie there is no all-tenants sentinel to express, and the tenant\n * selector renders with `includeEmptyOption={false}`, so no UI produces a blank value. Treating it\n * as an applied override nulled `tenantId` for the whole super-admin session, which is what turned\n * a cosmetic client bug into `tenantId ?? ''` reaching a NOT NULL uuid column. Reporting the\n * override as not applied instead keeps the tenant carried in the token and remediates an\n * already-poisoned browser on its next request, whatever wrote the cookie.\n */\nfunction resolveTenantOverride(raw: string | undefined): CookieOverride {\n if (raw === undefined) return { applied: false, value: null }\n const decoded = decodeCookieValue(raw)\n if (!decoded) return { applied: false, value: null }\n const trimmed = decoded.trim()\n if (!trimmed) return { applied: false, value: null }\n return { applied: true, value: trimmed }\n}\n\nfunction resolveOrganizationOverride(raw: string | undefined): CookieOverride {\n if (raw === undefined) return { applied: false, value: null }\n const decoded = decodeCookieValue(raw)\n if (!decoded || decoded === ALL_ORGANIZATIONS_COOKIE_VALUE) {\n return { applied: true, value: null }\n }\n const trimmed = decoded.trim()\n if (!trimmed || trimmed === ALL_ORGANIZATIONS_COOKIE_VALUE) {\n return { applied: true, value: null }\n }\n return { applied: true, value: trimmed }\n}\n\nfunction isSuperAdminAuth(auth: AuthContext | null | undefined): boolean {\n if (!auth) return false\n return (auth as Record<string, unknown>).isSuperAdmin === true\n}\n\nfunction applySuperAdminScope(\n auth: AuthContext,\n tenantCookie: string | undefined,\n orgCookie: string | undefined\n): AuthContext {\n if (!auth || !isSuperAdminAuth(auth)) return auth\n\n const tenantOverride = resolveTenantOverride(tenantCookie)\n const orgOverride = resolveOrganizationOverride(orgCookie)\n if (!tenantOverride.applied && !orgOverride.applied) return auth\n\n type MutableAuthContext = Exclude<AuthContext, null> & {\n actorTenantId?: string | null\n actorOrgId?: string | null\n }\n const baseAuth = auth as Exclude<AuthContext, null>\n const next: MutableAuthContext = { ...baseAuth }\n if (tenantOverride.applied) {\n if (!('actorTenantId' in next)) next.actorTenantId = auth?.tenantId ?? null\n next.tenantId = tenantOverride.value\n }\n if (orgOverride.applied) {\n if (!('actorOrgId' in next)) next.actorOrgId = auth?.orgId ?? null\n next.orgId = orgOverride.value\n }\n next.isSuperAdmin = true\n const existingRoles = Array.isArray(next.roles) ? next.roles : []\n if (!existingRoles.some((role) => typeof role === 'string' && role.trim().toLowerCase() === SUPERADMIN_ROLE)) {\n next.roles = [...existingRoles, 'superadmin']\n }\n return next\n}\n\nasync function resolveApiKeyAuth(secret: string): Promise<AuthContext> {\n if (!secret) return null\n const cache = getSharedApiKeyAuthCache()\n const cached = cache.get(secret)\n if (cached !== undefined) return cached as AuthContext\n try {\n const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n const { findApiKeyBySecret } = await import('@open-mercato/core/modules/api_keys/services/apiKeyService')\n const { Role, RoleAcl, User } = await import('@open-mercato/core/modules/auth/data/entities')\n const { Organization, Tenant } = await import('@open-mercato/core/modules/directory/data/entities')\n\n const record = await findApiKeyBySecret(em, secret)\n if (!record) {\n cache.setMiss(secret)\n return null\n }\n\n const roleIds = Array.isArray(record.rolesJson)\n ? record.rolesJson.filter((value): value is string => typeof value === 'string' && value.length > 0)\n : []\n const roles = roleIds.length\n ? await em.find(Role, { id: { $in: roleIds }, deletedAt: null })\n : []\n const roleNames = roles.map((role) => role.name).filter((name): name is string => typeof name === 'string' && name.length > 0)\n\n // A role-level super-admin grant is authorization-grade only when it is genuinely\n // unrestricted: the grant itself must not be organization-scoped, it must belong to the\n // key's tenant, and the key must not be bound to a single organization. RbacService applies\n // the same intersection when projecting the scoped ACL, but generic guards\n // (tenantAccess.resolveIsSuperAdmin, the scoped-API helpers) trust this raw bit *before*\n // live RBAC runs \u2014 so an organization-restricted key must never carry it.\n let keyIsSuperAdmin = false\n const keyOrganizationId = typeof record.organizationId === 'string' && record.organizationId.trim().length > 0\n ? record.organizationId.trim()\n : null\n if (roleIds.length && !keyOrganizationId) {\n const superAcls = await em.find(\n RoleAcl,\n {\n role: { $in: roleIds } as any,\n tenantId: record.tenantId ?? null,\n isSuperAdmin: true,\n deletedAt: null,\n } as any,\n )\n keyIsSuperAdmin = superAcls.some((acl) => {\n const organizations = Array.isArray((acl as { organizationsJson?: string[] | null }).organizationsJson)\n ? (acl as { organizationsJson?: string[] | null }).organizationsJson as string[]\n : null\n // An empty list means \"inherit the key's own binding\"; with no binding that is tenant-wide.\n return !organizations || organizations.length === 0 || organizations.includes('__all__')\n })\n }\n\n if (cache.shouldWriteLastUsed(record.id)) {\n try {\n record.lastUsedAt = new Date()\n await em.persist(record).flush()\n } catch {\n // best-effort update; ignore write failures\n }\n }\n\n // Ephemeral session keys are always user-bound. Regular keys retain their\n // legacy creator identity, while tenant-scoped regular keys ignore only the\n // creator's concrete organization when validating the wider key scope.\n // Keep every session marker fail-closed so a malformed session key cannot\n // fall back to the regular key path and escape its user/scope binding.\n const isSessionBoundKey = Boolean(\n record.sessionToken\n || record.sessionUserId\n || record.sessionSecretEncrypted\n || record.opencodeSessionId\n )\n const actualUserId = isSessionBoundKey\n ? record.sessionUserId ?? null\n : record.createdBy ?? null\n\n if (isSessionBoundKey && !actualUserId) {\n cache.setMiss(secret)\n return null\n }\n\n if (actualUserId) {\n const user = await em.findOne(User, { id: actualUserId, deletedAt: null })\n if (!user) {\n cache.setMiss(secret)\n return null\n }\n if ((user.tenantId ?? null) !== (record.tenantId ?? null)) {\n cache.setMiss(secret)\n return null\n }\n const requiresExactOrganization = isSessionBoundKey || Boolean(record.organizationId)\n if (requiresExactOrganization && (user.organizationId ?? null) !== (record.organizationId ?? null)) {\n cache.setMiss(secret)\n return null\n }\n } else {\n if (record.tenantId) {\n const tenant = await em.findOne(Tenant, { id: record.tenantId, deletedAt: null, isActive: true })\n if (!tenant) {\n cache.setMiss(secret)\n return null\n }\n }\n if (record.organizationId) {\n const organization = await em.findOne(Organization, { id: record.organizationId, deletedAt: null, isActive: true })\n if (!organization) {\n cache.setMiss(secret)\n return null\n }\n if (record.tenantId && String(organization.tenant.id) !== record.tenantId) {\n cache.setMiss(secret)\n return null\n }\n }\n }\n\n const auth: Exclude<AuthContext, null> = {\n sub: `api_key:${record.id}`,\n tenantId: record.tenantId ?? null,\n orgId: record.organizationId ?? null,\n roles: roleNames,\n isApiKey: true,\n isSuperAdmin: keyIsSuperAdmin,\n keyId: record.id,\n keyName: record.name,\n ...(actualUserId ? { userId: actualUserId } : {}),\n }\n cache.setSuccess(secret, auth, record.expiresAt ? record.expiresAt.getTime() : null)\n return auth\n } catch (err) {\n // A transient DB failure (pool exhausted, `max_connections` reached, DB\n // restarting) means we could not confirm the key \u2014 NOT that it is invalid.\n // Surface it so callers return a retryable 503 instead of masking it as an\n // auth miss (401). Genuine misses already returned `null` above.\n if (isTransientDbError(err)) {\n throw new AuthResolutionUnavailableError(err)\n }\n return null\n }\n}\n\nfunction extractApiKey(req: Request): string | null {\n const header = (req.headers.get('x-api-key') || '').trim()\n if (header) return header\n const authHeader = (req.headers.get('authorization') || '').trim()\n if (authHeader.toLowerCase().startsWith('apikey ')) {\n return authHeader.slice(7).trim()\n }\n return null\n}\n\nasync function resolveCanonicalInteractiveAuthContext(auth: AuthContext): Promise<AuthContext> {\n if (!auth || auth.isApiKey) return auth\n if (typeof auth.sub !== 'string' || auth.sub.trim().length === 0) return null\n\n try {\n const [{ createRequestContainer }, { resolveCanonicalStaffAuthContext }] = await Promise.all([\n import('@open-mercato/shared/lib/di/container'),\n import('@open-mercato/core/modules/auth/lib/sessionIntegrity'),\n ])\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n return await resolveCanonicalStaffAuthContext(em, auth)\n } catch (err) {\n // A thrown error here means we could not check the token against the\n // database (DB down, pool exhausted, timeout). This is NOT the same as the\n // token being invalid \u2014 surface it so callers keep the session intact and\n // fail the request transiently instead of force-logging the user out.\n throw new AuthResolutionUnavailableError(err)\n }\n}\n\nexport async function resolveAuthFromCookiesDetailed(): Promise<AuthResolution> {\n const cookieStore = await cookies()\n const token = cookieStore.get('auth_token')?.value\n if (!token) return { auth: null, status: 'missing' }\n try {\n const payload = verifyJwt(token) as AuthContext\n if (!payload) return { auth: null, status: 'invalid' }\n if (payload.type === 'customer') return { auth: null, status: 'invalid' }\n // MFA-pending tokens are provisional: pages never complete the second factor, so they\n // must not resolve to an authenticated context anywhere in the RSC/page flow.\n if (isMfaPendingJwtPayload(payload)) return { auth: null, status: 'invalid' }\n const canonicalAuth = await resolveCanonicalInteractiveAuthContext(payload)\n if (!canonicalAuth) return { auth: null, status: 'invalid' }\n const tenantCookie = cookieStore.get(TENANT_COOKIE_NAME)?.value\n const orgCookie = cookieStore.get(ORGANIZATION_COOKIE_NAME)?.value\n return {\n auth: applySuperAdminScope(canonicalAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n } catch (err) {\n if (err instanceof AuthResolutionUnavailableError) return { auth: null, status: 'error' }\n return { auth: null, status: 'invalid' }\n }\n}\n\nexport async function getAuthFromCookies(): Promise<AuthContext> {\n return (await resolveAuthFromCookiesDetailed()).auth\n}\n\nexport async function resolveAuthFromRequestDetailed(req: Request): Promise<AuthResolution> {\n // Deliberately ahead of the MFA-pending gate below: the envelope carries a context that was\n // already gated by its producer (see `attachTrustedAuthContext`), not raw request credentials.\n const trusted = readTrustedAuthContext(req)\n if (trusted) {\n return {\n auth: trusted.auth,\n status: trusted.status ?? (trusted.auth ? 'authenticated' : 'missing'),\n }\n }\n const cookieHeader = req.headers.get('cookie') || ''\n const tenantCookie = readCookieFromHeader(cookieHeader, TENANT_COOKIE_NAME)\n const orgCookie = readCookieFromHeader(cookieHeader, ORGANIZATION_COOKIE_NAME)\n const authHeader = (req.headers.get('authorization') || '').trim()\n let token: string | undefined\n let hadInvalidInteractiveToken = false\n let hadUnavailableResolution = false\n if (authHeader.toLowerCase().startsWith('bearer ')) token = authHeader.slice(7).trim()\n if (!token) {\n const match = cookieHeader.match(/(?:^|;\\s*)auth_token=([^;]+)/)\n if (match) token = decodeURIComponent(match[1])\n }\n if (token) {\n try {\n const payload = verifyJwt(token) as AuthContext\n if (payload && payload.type === 'customer') return { auth: null, status: 'invalid' }\n if (payload && isMfaPendingJwtPayload(payload)) {\n // MFA-pending tokens authenticate only the registered challenge-completion routes;\n // everywhere else they resolve to `invalid` so the dispatcher answers 401 (clearing\n // staff auth cookies) instead of restoring the account's roles/features.\n if (!isMfaPendingAccessAllowed(req.method, readRequestPathname(req))) {\n return { auth: null, status: 'invalid' }\n }\n }\n if (payload) {\n const canonicalAuth = await resolveCanonicalInteractiveAuthContext(payload)\n if (canonicalAuth) {\n return {\n auth: applySuperAdminScope(canonicalAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n }\n hadInvalidInteractiveToken = true\n }\n } catch (err) {\n // Transient/unexpected canonical-resolution failures must not invalidate\n // the token \u2014 surface them so we return 'error' (retryable) rather than\n // clearing the session cookies.\n if (err instanceof AuthResolutionUnavailableError) hadUnavailableResolution = true\n else hadInvalidInteractiveToken = true\n }\n }\n\n const resolveUnauthenticatedStatus = (): AuthResolutionStatus =>\n hadUnavailableResolution ? 'error' : hadInvalidInteractiveToken ? 'invalid' : 'missing'\n\n const apiKey = extractApiKey(req)\n if (!apiKey) {\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n let apiAuth: AuthContext\n try {\n apiAuth = await resolveApiKeyAuth(apiKey)\n } catch (err) {\n // Only a transient canonical-resolution failure maps to 'error' (retryable\n // 503), mirroring the interactive-token path above. Anything else is an\n // unexpected bug \u2014 rethrow so it surfaces as a 500 rather than being masked\n // as an auth failure.\n if (!(err instanceof AuthResolutionUnavailableError)) {\n throw err\n }\n hadUnavailableResolution = true\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n if (!apiAuth) {\n return { auth: null, status: resolveUnauthenticatedStatus() }\n }\n return {\n auth: applySuperAdminScope(apiAuth, tenantCookie, orgCookie),\n status: 'authenticated',\n }\n}\n\nexport async function getAuthFromRequest(req: Request): Promise<AuthContext> {\n return (await resolveAuthFromRequestDetailed(req)).auth\n}\n"],
5
+ "mappings": "AAAA,SAAS,eAAe;AAExB,SAAS,wBAAwB,iBAAiB;AAClD,SAAS,iCAAiC;AAC1C,SAAS,gCAAgC;AACzC,SAAS,0BAA0B;AAEnC,SAAS,oBAAoB,KAA6B;AACxD,MAAI;AACF,WAAO,IAAI,IAAI,IAAI,GAAG,EAAE;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AACjC,MAAM,iCAAiC;AACvC,MAAM,kBAAkB;AAgCjB,MAAM,uCAAuC,MAAM;AAAA,EACxD,YAAY,OAAiB;AAC3B,UAAM,6BAA6B;AACnC,SAAK,OAAO;AACZ,QAAI,UAAU,OAAW,CAAC,KAA6B,QAAQ;AAAA,EACjE;AACF;AAOO,MAAM,8BAA8B,uBAAO,IAAI,kCAAkC;AAiBjF,SAAS,yBACd,SACA,UACS;AACT;AAAC,EAAC,QAAkE,2BAA2B,IAAI;AACnG,SAAO;AACT;AAEA,SAAS,uBAAuB,SAAqD;AACnF,QAAM,UAAU;AAChB,QAAM,WAAW,QAAQ,2BAA2B;AACpD,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU,QAAO;AACtD,QAAM,YAAY;AAClB,MAAI,EAAE,UAAU,WAAY,QAAO;AACnC,SAAO;AACT;AAEA,SAAS,kBAAkB,KAAwC;AACjE,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI;AACF,UAAM,UAAU,mBAAmB,GAAG;AACtC,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO,OAAO;AAAA,EAChB;AACF;AAEA,SAAS,qBAAqB,QAAmC,MAAkC;AACjG,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG;AAClC,aAAO,QAAQ,MAAM,KAAK,SAAS,CAAC;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAYA,SAAS,sBAAsB,KAAyC;AACtE,MAAI,QAAQ,OAAW,QAAO,EAAE,SAAS,OAAO,OAAO,KAAK;AAC5D,QAAM,UAAU,kBAAkB,GAAG;AACrC,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,OAAO,OAAO,KAAK;AACnD,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,OAAO,OAAO,KAAK;AACnD,SAAO,EAAE,SAAS,MAAM,OAAO,QAAQ;AACzC;AAEA,SAAS,4BAA4B,KAAyC;AAC5E,MAAI,QAAQ,OAAW,QAAO,EAAE,SAAS,OAAO,OAAO,KAAK;AAC5D,QAAM,UAAU,kBAAkB,GAAG;AACrC,MAAI,CAAC,WAAW,YAAY,gCAAgC;AAC1D,WAAO,EAAE,SAAS,MAAM,OAAO,KAAK;AAAA,EACtC;AACA,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,CAAC,WAAW,YAAY,gCAAgC;AAC1D,WAAO,EAAE,SAAS,MAAM,OAAO,KAAK;AAAA,EACtC;AACA,SAAO,EAAE,SAAS,MAAM,OAAO,QAAQ;AACzC;AAEA,SAAS,iBAAiB,MAA+C;AACvE,MAAI,CAAC,KAAM,QAAO;AAClB,SAAQ,KAAiC,iBAAiB;AAC5D;AAEA,SAAS,qBACP,MACA,cACA,WACa;AACb,MAAI,CAAC,QAAQ,CAAC,iBAAiB,IAAI,EAAG,QAAO;AAE7C,QAAM,iBAAiB,sBAAsB,YAAY;AACzD,QAAM,cAAc,4BAA4B,SAAS;AACzD,MAAI,CAAC,eAAe,WAAW,CAAC,YAAY,QAAS,QAAO;AAM5D,QAAM,WAAW;AACjB,QAAM,OAA2B,EAAE,GAAG,SAAS;AAC/C,MAAI,eAAe,SAAS;AAC1B,QAAI,EAAE,mBAAmB,MAAO,MAAK,gBAAgB,MAAM,YAAY;AACvE,SAAK,WAAW,eAAe;AAAA,EACjC;AACA,MAAI,YAAY,SAAS;AACvB,QAAI,EAAE,gBAAgB,MAAO,MAAK,aAAa,MAAM,SAAS;AAC9D,SAAK,QAAQ,YAAY;AAAA,EAC3B;AACA,OAAK,eAAe;AACpB,QAAM,gBAAgB,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAChE,MAAI,CAAC,cAAc,KAAK,CAAC,SAAS,OAAO,SAAS,YAAY,KAAK,KAAK,EAAE,YAAY,MAAM,eAAe,GAAG;AAC5G,SAAK,QAAQ,CAAC,GAAG,eAAe,YAAY;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAe,kBAAkB,QAAsC;AACrE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,yBAAyB;AACvC,QAAM,SAAS,MAAM,IAAI,MAAM;AAC/B,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI;AACF,UAAM,EAAE,uBAAuB,IAAI,MAAM,OAAO,uCAAuC;AACvF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,4DAA4D;AACxG,UAAM,EAAE,MAAM,SAAS,KAAK,IAAI,MAAM,OAAO,+CAA+C;AAC5F,UAAM,EAAE,cAAc,OAAO,IAAI,MAAM,OAAO,oDAAoD;AAElG,UAAM,SAAS,MAAM,mBAAmB,IAAI,MAAM;AAClD,QAAI,CAAC,QAAQ;AACX,YAAM,QAAQ,MAAM;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,MAAM,QAAQ,OAAO,SAAS,IAC1C,OAAO,UAAU,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC,IACjG,CAAC;AACL,UAAM,QAAQ,QAAQ,SAClB,MAAM,GAAG,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,QAAQ,GAAG,WAAW,KAAK,CAAC,IAC7D,CAAC;AACL,UAAM,YAAY,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC;AAQ7H,QAAI,kBAAkB;AACtB,UAAM,oBAAoB,OAAO,OAAO,mBAAmB,YAAY,OAAO,eAAe,KAAK,EAAE,SAAS,IACzG,OAAO,eAAe,KAAK,IAC3B;AACJ,QAAI,QAAQ,UAAU,CAAC,mBAAmB;AACxC,YAAM,YAAY,MAAM,GAAG;AAAA,QACzB;AAAA,QACA;AAAA,UACE,MAAM,EAAE,KAAK,QAAQ;AAAA,UACrB,UAAU,OAAO,YAAY;AAAA,UAC7B,cAAc;AAAA,UACd,WAAW;AAAA,QACb;AAAA,MACF;AACA,wBAAkB,UAAU,KAAK,CAAC,QAAQ;AACxC,cAAM,gBAAgB,MAAM,QAAS,IAAgD,iBAAiB,IACjG,IAAgD,oBACjD;AAEJ,eAAO,CAAC,iBAAiB,cAAc,WAAW,KAAK,cAAc,SAAS,SAAS;AAAA,MACzF,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,oBAAoB,OAAO,EAAE,GAAG;AACxC,UAAI;AACF,eAAO,aAAa,oBAAI,KAAK;AAC7B,cAAM,GAAG,QAAQ,MAAM,EAAE,MAAM;AAAA,MACjC,QAAQ;AAAA,MAER;AAAA,IACF;AAOA,UAAM,oBAAoB;AAAA,MACxB,OAAO,gBACJ,OAAO,iBACP,OAAO,0BACP,OAAO;AAAA,IACZ;AACA,UAAM,eAAe,oBACjB,OAAO,iBAAiB,OACxB,OAAO,aAAa;AAExB,QAAI,qBAAqB,CAAC,cAAc;AACtC,YAAM,QAAQ,MAAM;AACpB,aAAO;AAAA,IACT;AAEA,QAAI,cAAc;AAChB,YAAM,OAAO,MAAM,GAAG,QAAQ,MAAM,EAAE,IAAI,cAAc,WAAW,KAAK,CAAC;AACzE,UAAI,CAAC,MAAM;AACT,cAAM,QAAQ,MAAM;AACpB,eAAO;AAAA,MACT;AACA,WAAK,KAAK,YAAY,WAAW,OAAO,YAAY,OAAO;AACzD,cAAM,QAAQ,MAAM;AACpB,eAAO;AAAA,MACT;AACA,YAAM,4BAA4B,qBAAqB,QAAQ,OAAO,cAAc;AACpF,UAAI,8BAA8B,KAAK,kBAAkB,WAAW,OAAO,kBAAkB,OAAO;AAClG,cAAM,QAAQ,MAAM;AACpB,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AACL,UAAI,OAAO,UAAU;AACnB,cAAM,SAAS,MAAM,GAAG,QAAQ,QAAQ,EAAE,IAAI,OAAO,UAAU,WAAW,MAAM,UAAU,KAAK,CAAC;AAChG,YAAI,CAAC,QAAQ;AACX,gBAAM,QAAQ,MAAM;AACpB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,UAAI,OAAO,gBAAgB;AACzB,cAAM,eAAe,MAAM,GAAG,QAAQ,cAAc,EAAE,IAAI,OAAO,gBAAgB,WAAW,MAAM,UAAU,KAAK,CAAC;AAClH,YAAI,CAAC,cAAc;AACjB,gBAAM,QAAQ,MAAM;AACpB,iBAAO;AAAA,QACT;AACA,YAAI,OAAO,YAAY,OAAO,aAAa,OAAO,EAAE,MAAM,OAAO,UAAU;AACzE,gBAAM,QAAQ,MAAM;AACpB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAmC;AAAA,MACvC,KAAK,WAAW,OAAO,EAAE;AAAA,MACzB,UAAU,OAAO,YAAY;AAAA,MAC7B,OAAO,OAAO,kBAAkB;AAAA,MAChC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,GAAI,eAAe,EAAE,QAAQ,aAAa,IAAI,CAAC;AAAA,IACjD;AACA,UAAM,WAAW,QAAQ,MAAM,OAAO,YAAY,OAAO,UAAU,QAAQ,IAAI,IAAI;AACnF,WAAO;AAAA,EACT,SAAS,KAAK;AAKZ,QAAI,mBAAmB,GAAG,GAAG;AAC3B,YAAM,IAAI,+BAA+B,GAAG;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAA6B;AAClD,QAAM,UAAU,IAAI,QAAQ,IAAI,WAAW,KAAK,IAAI,KAAK;AACzD,MAAI,OAAQ,QAAO;AACnB,QAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,KAAK,IAAI,KAAK;AACjE,MAAI,WAAW,YAAY,EAAE,WAAW,SAAS,GAAG;AAClD,WAAO,WAAW,MAAM,CAAC,EAAE,KAAK;AAAA,EAClC;AACA,SAAO;AACT;AAEA,eAAe,uCAAuC,MAAyC;AAC7F,MAAI,CAAC,QAAQ,KAAK,SAAU,QAAO;AACnC,MAAI,OAAO,KAAK,QAAQ,YAAY,KAAK,IAAI,KAAK,EAAE,WAAW,EAAG,QAAO;AAEzE,MAAI;AACF,UAAM,CAAC,EAAE,uBAAuB,GAAG,EAAE,iCAAiC,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3F,OAAO,uCAAuC;AAAA,MAC9C,OAAO,sDAAsD;AAAA,IAC/D,CAAC;AACD,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAK,UAAU,QAAQ,IAAI;AACjC,WAAO,MAAM,iCAAiC,IAAI,IAAI;AAAA,EACxD,SAAS,KAAK;AAKZ,UAAM,IAAI,+BAA+B,GAAG;AAAA,EAC9C;AACF;AAEA,eAAsB,iCAA0D;AAC9E,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,QAAQ,YAAY,IAAI,YAAY,GAAG;AAC7C,MAAI,CAAC,MAAO,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AACnD,MAAI;AACF,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,QAAS,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AACrD,QAAI,QAAQ,SAAS,WAAY,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AAGxE,QAAI,uBAAuB,OAAO,EAAG,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AAC5E,UAAM,gBAAgB,MAAM,uCAAuC,OAAO;AAC1E,QAAI,CAAC,cAAe,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AAC3D,UAAM,eAAe,YAAY,IAAI,kBAAkB,GAAG;AAC1D,UAAM,YAAY,YAAY,IAAI,wBAAwB,GAAG;AAC7D,WAAO;AAAA,MACL,MAAM,qBAAqB,eAAe,cAAc,SAAS;AAAA,MACjE,QAAQ;AAAA,IACV;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,+BAAgC,QAAO,EAAE,MAAM,MAAM,QAAQ,QAAQ;AACxF,WAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AAAA,EACzC;AACF;AAEA,eAAsB,qBAA2C;AAC/D,UAAQ,MAAM,+BAA+B,GAAG;AAClD;AAEA,eAAsB,+BAA+B,KAAuC;AAG1F,QAAM,UAAU,uBAAuB,GAAG;AAC1C,MAAI,SAAS;AACX,WAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ,WAAW,QAAQ,OAAO,kBAAkB;AAAA,IAC9D;AAAA,EACF;AACA,QAAM,eAAe,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAClD,QAAM,eAAe,qBAAqB,cAAc,kBAAkB;AAC1E,QAAM,YAAY,qBAAqB,cAAc,wBAAwB;AAC7E,QAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,KAAK,IAAI,KAAK;AACjE,MAAI;AACJ,MAAI,6BAA6B;AACjC,MAAI,2BAA2B;AAC/B,MAAI,WAAW,YAAY,EAAE,WAAW,SAAS,EAAG,SAAQ,WAAW,MAAM,CAAC,EAAE,KAAK;AACrF,MAAI,CAAC,OAAO;AACV,UAAM,QAAQ,aAAa,MAAM,8BAA8B;AAC/D,QAAI,MAAO,SAAQ,mBAAmB,MAAM,CAAC,CAAC;AAAA,EAChD;AACA,MAAI,OAAO;AACT,QAAI;AACF,YAAM,UAAU,UAAU,KAAK;AAC/B,UAAI,WAAW,QAAQ,SAAS,WAAY,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AACnF,UAAI,WAAW,uBAAuB,OAAO,GAAG;AAI9C,YAAI,CAAC,0BAA0B,IAAI,QAAQ,oBAAoB,GAAG,CAAC,GAAG;AACpE,iBAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AAAA,QACzC;AAAA,MACF;AACA,UAAI,SAAS;AACX,cAAM,gBAAgB,MAAM,uCAAuC,OAAO;AAC1E,YAAI,eAAe;AACjB,iBAAO;AAAA,YACL,MAAM,qBAAqB,eAAe,cAAc,SAAS;AAAA,YACjE,QAAQ;AAAA,UACV;AAAA,QACF;AACA,qCAA6B;AAAA,MAC/B;AAAA,IACF,SAAS,KAAK;AAIZ,UAAI,eAAe,+BAAgC,4BAA2B;AAAA,UACzE,8BAA6B;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,+BAA+B,MACnC,2BAA2B,UAAU,6BAA6B,YAAY;AAEhF,QAAM,SAAS,cAAc,GAAG;AAChC,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,MAAM,MAAM,QAAQ,6BAA6B,EAAE;AAAA,EAC9D;AACA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,kBAAkB,MAAM;AAAA,EAC1C,SAAS,KAAK;AAKZ,QAAI,EAAE,eAAe,iCAAiC;AACpD,YAAM;AAAA,IACR;AACA,+BAA2B;AAC3B,WAAO,EAAE,MAAM,MAAM,QAAQ,6BAA6B,EAAE;AAAA,EAC9D;AACA,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,MAAM,MAAM,QAAQ,6BAA6B,EAAE;AAAA,EAC9D;AACA,SAAO;AAAA,IACL,MAAM,qBAAqB,SAAS,cAAc,SAAS;AAAA,IAC3D,QAAQ;AAAA,EACV;AACF;AAEA,eAAsB,mBAAmB,KAAoC;AAC3E,UAAQ,MAAM,+BAA+B,GAAG,GAAG;AACrD;",
6
6
  "names": []
7
7
  }
@@ -13,7 +13,7 @@ import { CLIENT_ONLY_STUB_NAMESPACE, createClientOnlyStubPlugin } from "./client
13
13
  import path from "node:path";
14
14
  import fs from "node:fs";
15
15
  import crypto from "node:crypto";
16
- import { createRequire, isBuiltin } from "node:module";
16
+ import { createRequire } from "node:module";
17
17
  import { pathToFileURL } from "node:url";
18
18
  let activeBootstrapLoads = 0;
19
19
  let esbuildRuntime = null;
@@ -54,33 +54,7 @@ class GeneratedFileNotFoundError extends Error {
54
54
  this.filePath = filePath;
55
55
  }
56
56
  }
57
- function splitBareSpecifier(specifier) {
58
- const segments = specifier.split("/");
59
- const nameLength = specifier.startsWith("@") ? 2 : 1;
60
- if (segments.length <= nameLength || segments.slice(0, nameLength).some((segment) => !segment)) return null;
61
- return {
62
- packageName: segments.slice(0, nameLength).join("/"),
63
- subpath: segments.slice(nameLength).join("/")
64
- };
65
- }
66
- function rewriteLegacySubpathSpecifier(specifier, appRequire, onRewrite) {
67
- if (isBuiltin(specifier)) return specifier;
68
- const parts = splitBareSpecifier(specifier);
69
- if (!parts || path.posix.extname(parts.subpath)) return specifier;
70
- try {
71
- const manifestPath = appRequire.resolve(`${parts.packageName}/package.json`);
72
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
73
- if (manifest.exports != null) return specifier;
74
- const resolvedFile = appRequire.resolve(specifier);
75
- const relativeFile = path.relative(path.dirname(manifestPath), resolvedFile);
76
- if (!relativeFile || relativeFile.startsWith("..") || path.isAbsolute(relativeFile)) return specifier;
77
- onRewrite(manifestPath);
78
- return `${parts.packageName}/${relativeFile.split(path.sep).join("/")}`;
79
- } catch {
80
- return specifier;
81
- }
82
- }
83
- function createCliBundlePlugins(appRoot, options = {}) {
57
+ function createCliBundlePlugins(appRoot) {
84
58
  const aliasPlugin = {
85
59
  name: "alias-resolver",
86
60
  setup(build) {
@@ -101,16 +75,6 @@ function createCliBundlePlugins(appRoot, options = {}) {
101
75
  });
102
76
  }
103
77
  };
104
- const appRequire = createRequire(path.join(appRoot, "package.json"));
105
- const externalSpecifierCache = /* @__PURE__ */ new Map();
106
- const onLegacySubpathRewrite = options.onLegacySubpathRewrite ?? (() => void 0);
107
- const resolveExternalSpecifier = (specifier) => {
108
- const cached = externalSpecifierCache.get(specifier);
109
- if (cached !== void 0) return cached;
110
- const resolved = rewriteLegacySubpathSpecifier(specifier, appRequire, onLegacySubpathRewrite);
111
- externalSpecifierCache.set(specifier, resolved);
112
- return resolved;
113
- };
114
78
  const externalNonJsonPlugin = {
115
79
  name: "external-non-json",
116
80
  setup(build) {
@@ -121,13 +85,13 @@ function createCliBundlePlugins(appRoot, options = {}) {
121
85
  if (args.path.endsWith(".json")) {
122
86
  return null;
123
87
  }
124
- return { path: resolveExternalSpecifier(args.path), external: true };
88
+ return { path: args.path, external: true };
125
89
  });
126
90
  }
127
91
  };
128
92
  return [createClientOnlyStubPlugin(), aliasPlugin, externalNonJsonPlugin];
129
93
  }
130
- const DYNAMIC_LOADER_CACHE_VERSION = 5;
94
+ const DYNAMIC_LOADER_CACHE_VERSION = 4;
131
95
  function cacheMetadataPath(jsPath) {
132
96
  return `${jsPath}.cache.json`;
133
97
  }
@@ -296,7 +260,6 @@ async function compileAppSourceFileWithActiveEsbuild(tsPath, options) {
296
260
  }
297
261
  fs.mkdirSync(path.dirname(outFile), { recursive: true });
298
262
  const esbuild = await getEsbuildRuntime();
299
- const rewrittenPackageManifests = /* @__PURE__ */ new Set();
300
263
  const result = await esbuild.build({
301
264
  entryPoints: [tsPath],
302
265
  outfile: outFile,
@@ -307,9 +270,7 @@ async function compileAppSourceFileWithActiveEsbuild(tsPath, options) {
307
270
  platform: "node",
308
271
  target: "node18",
309
272
  tsconfig: appTsconfig,
310
- plugins: createCliBundlePlugins(appRoot, {
311
- onLegacySubpathRewrite: (manifestPath) => rewrittenPackageManifests.add(manifestPath)
312
- }),
273
+ plugins: createCliBundlePlugins(appRoot),
313
274
  // Allow JSON imports
314
275
  loader: { ".json": "json" }
315
276
  });
@@ -319,8 +280,7 @@ async function compileAppSourceFileWithActiveEsbuild(tsPath, options) {
319
280
  outputHash: contentHash(fs.readFileSync(outFile)),
320
281
  dependencies: {
321
282
  ...collectDependencyHashes(appRoot, result.metafile.inputs),
322
- ...hashFilesRelativeTo(appRoot, tsconfigPaths),
323
- ...hashFilesRelativeTo(appRoot, [...rewrittenPackageManifests])
283
+ ...hashFilesRelativeTo(appRoot, tsconfigPaths)
324
284
  }
325
285
  };
326
286
  fs.writeFileSync(metadataPath, JSON.stringify(metadata));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/bootstrap/dynamicLoader.ts"],
4
- "sourcesContent": ["import { asValue } from 'awilix'\nimport type { BootstrapData } from './types'\nimport type { AppDiRegistrar } from '../di/container'\nimport { findAppRoot, type AppRoot } from './appResolver'\nimport { registerEntityIds } from '../encryption/entityIds'\nimport { createLogger } from '../logger'\nimport {\n applyModuleOverridesFromEnabledModules,\n type ModuleEntryWithOverrides,\n} from '../../modules/overrides'\nimport {\n ensureMikroOrmV7GeneratedCacheCompatibility,\n recoverMikroOrmV7GeneratedCacheFromImportError,\n} from './generatedCacheRecovery'\nimport { CLIENT_ONLY_STUB_NAMESPACE, createClientOnlyStubPlugin } from './clientOnlyModules'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport crypto from 'node:crypto'\nimport { createRequire, isBuiltin } from 'node:module'\nimport { pathToFileURL } from 'node:url'\n\nlet activeBootstrapLoads = 0\nlet esbuildRuntime: typeof import('esbuild') | null = null\nlet esbuildStopPromise: Promise<void> | null = null\n\nconst logger = createLogger('shared').child({ component: 'bootstrap' })\n\nasync function getEsbuildRuntime(): Promise<typeof import('esbuild')> {\n if (esbuildStopPromise) await esbuildStopPromise\n if (esbuildRuntime) return esbuildRuntime\n\n const loadedRuntime = await import('esbuild')\n esbuildRuntime ??= loadedRuntime\n return esbuildRuntime\n}\n\nasync function withEsbuildLifecycle<T>(load: () => Promise<T>): Promise<T> {\n activeBootstrapLoads += 1\n\n try {\n return await load()\n } finally {\n activeBootstrapLoads -= 1\n if (activeBootstrapLoads === 0 && esbuildRuntime) {\n // esbuild keeps a helper process alive after build(). Bootstrap compilation\n // is a bounded phase, so release it once every concurrent loader is done.\n // A later build() call transparently starts a fresh helper process.\n const runtimeToStop = esbuildRuntime\n esbuildRuntime = null\n const stopPromise = runtimeToStop.stop().catch((err) => {\n logger.warn('Failed to stop the bootstrap compiler service', { err })\n })\n esbuildStopPromise = stopPromise\n try {\n await stopPromise\n } finally {\n if (esbuildStopPromise === stopPromise) esbuildStopPromise = null\n }\n }\n }\n}\n\n/**\n * Thrown when an expected generated source file is absent.\n *\n * Optional registries treat this as the supported compatibility case (an app\n * that never generated the file), which is what makes it distinguishable from\n * a file that exists but fails to compile or import.\n */\nclass GeneratedFileNotFoundError extends Error {\n readonly filePath: string\n\n constructor(filePath: string) {\n super(`Generated file not found: ${filePath}`)\n this.name = 'GeneratedFileNotFoundError'\n this.filePath = filePath\n }\n}\n\nfunction splitBareSpecifier(specifier: string): { packageName: string; subpath: string } | null {\n const segments = specifier.split('/')\n const nameLength = specifier.startsWith('@') ? 2 : 1\n if (segments.length <= nameLength || segments.slice(0, nameLength).some((segment) => !segment)) return null\n return {\n packageName: segments.slice(0, nameLength).join('/'),\n subpath: segments.slice(nameLength).join('/'),\n }\n}\n\n/**\n * Rewrites an externalized `pkg/subpath` specifier to the file Node's ESM resolver can load\n * when `pkg` publishes no `exports` map (#6993). Builtins, packages with `exports`, subpaths\n * that already carry an extension and anything that fails to resolve keep the original\n * specifier, so the bundle never gets worse than before.\n */\nfunction rewriteLegacySubpathSpecifier(\n specifier: string,\n appRequire: NodeRequire,\n onRewrite: (manifestPath: string) => void,\n): string {\n if (isBuiltin(specifier)) return specifier\n const parts = splitBareSpecifier(specifier)\n if (!parts || path.posix.extname(parts.subpath)) return specifier\n try {\n const manifestPath = appRequire.resolve(`${parts.packageName}/package.json`)\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown }\n if (manifest.exports != null) return specifier\n const resolvedFile = appRequire.resolve(specifier)\n const relativeFile = path.relative(path.dirname(manifestPath), resolvedFile)\n if (!relativeFile || relativeFile.startsWith('..') || path.isAbsolute(relativeFile)) return specifier\n onRewrite(manifestPath)\n return `${parts.packageName}/${relativeFile.split(path.sep).join('/')}`\n } catch {\n return specifier\n }\n}\n\n/**\n * esbuild plugins for the CLI bundle, in resolution order. The client-only stub must come\n * first so it wins over the alias and external plugins for `*.client` dynamic imports.\n *\n * Exported so the wiring itself is testable: a test that only exercises\n * `createClientOnlyStubPlugin` in isolation stays green if the plugin is dropped from this\n * list, which would silently reintroduce #4623.\n */\nexport function createCliBundlePlugins(\n appRoot: string,\n options: { onLegacySubpathRewrite?: (manifestPath: string) => void } = {},\n): import('esbuild').Plugin[] {\n // Plugin to resolve the @/ alias the way the app tsconfig maps it:\n // `@/.mercato/*` to the app root, every other `@/*` to the app's src/ directory.\n const aliasPlugin: import('esbuild').Plugin = {\n name: 'alias-resolver',\n setup(build) {\n build.onResolve({ filter: /^@\\// }, (args) => {\n const rest = args.path.slice('@/'.length)\n const bases = rest.startsWith('.mercato/')\n ? [path.join(appRoot, rest)]\n : [path.join(appRoot, 'src', rest), path.join(appRoot, rest)]\n for (const base of bases) {\n if (fs.existsSync(base) && fs.statSync(base).isFile()) {\n return { path: base }\n }\n for (const suffix of ['.ts', '.tsx', '/index.ts', '/index.tsx']) {\n if (fs.existsSync(base + suffix)) {\n return { path: base + suffix }\n }\n }\n }\n // Nothing matched \u2014 hand esbuild the literal mapping so it reports the\n // missing file against the path the app author actually wrote.\n return { path: path.join(appRoot, rest) }\n })\n },\n }\n\n // Node's ESM resolver only maps an extensionless package subpath (`next/link`) when the\n // package publishes an `exports` map; legacy packages need the real file path instead.\n const appRequire = createRequire(path.join(appRoot, 'package.json'))\n const externalSpecifierCache = new Map<string, string>()\n const onLegacySubpathRewrite = options.onLegacySubpathRewrite ?? (() => undefined)\n const resolveExternalSpecifier = (specifier: string): string => {\n const cached = externalSpecifierCache.get(specifier)\n if (cached !== undefined) return cached\n const resolved = rewriteLegacySubpathSpecifier(specifier, appRequire, onLegacySubpathRewrite)\n externalSpecifierCache.set(specifier, resolved)\n return resolved\n }\n\n // Plugin to mark non-JSON package imports as external\n const externalNonJsonPlugin: import('esbuild').Plugin = {\n name: 'external-non-json',\n setup(build) {\n // Mark all package imports as external EXCEPT JSON files\n // Filter matches paths that don't start with . or / (package imports like @open-mercato/shared)\n build.onResolve({ filter: /^[^./]/ }, (args) => {\n // Skip Windows absolute paths (e.g., C:\\...) - they're local files, not packages\n if (/^[a-zA-Z]:/.test(args.path)) {\n return null // Let esbuild handle it\n }\n // If it's a JSON file, let esbuild bundle it\n if (args.path.endsWith('.json')) {\n return null // Let esbuild handle it\n }\n // Otherwise mark as external\n return { path: resolveExternalSpecifier(args.path), external: true }\n })\n },\n }\n\n return [createClientOnlyStubPlugin(), aliasPlugin, externalNonJsonPlugin]\n}\n\nconst DYNAMIC_LOADER_CACHE_VERSION = 5\n\ntype DynamicLoaderCacheMetadata = {\n version: number\n inputHash: string\n outputHash: string\n dependencies: Record<string, string>\n}\n\nfunction cacheMetadataPath(jsPath: string): string {\n return `${jsPath}.cache.json`\n}\n\nfunction contentHash(content: Buffer | string): string {\n return crypto.createHash('sha256').update(content).digest('hex')\n}\n\nfunction parseJsonConfig(content: string): unknown {\n let normalized = ''\n let inString = false\n let escaped = false\n\n for (let index = 0; index < content.length; index += 1) {\n const character = content[index]\n const nextCharacter = content[index + 1]\n\n if (inString) {\n normalized += character\n if (escaped) {\n escaped = false\n } else if (character === '\\\\') {\n escaped = true\n } else if (character === '\"') {\n inString = false\n }\n continue\n }\n\n if (character === '\"') {\n inString = true\n normalized += character\n continue\n }\n\n if (character === '/' && nextCharacter === '/') {\n while (index < content.length && content[index] !== '\\n') index += 1\n normalized += '\\n'\n continue\n }\n\n if (character === '/' && nextCharacter === '*') {\n index += 2\n while (index < content.length && !(content[index] === '*' && content[index + 1] === '/')) {\n index += 1\n }\n index += 1\n continue\n }\n\n if (character === ',') {\n let lookahead = index + 1\n while (lookahead < content.length && /\\s/.test(content[lookahead])) lookahead += 1\n if (content[lookahead] === '}' || content[lookahead] === ']') continue\n }\n\n normalized += character\n }\n\n return JSON.parse(normalized)\n}\n\nfunction resolveExistingConfigPath(candidate: string): string | null {\n for (const configPath of [candidate, `${candidate}.json`, path.join(candidate, 'tsconfig.json')]) {\n if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) return configPath\n }\n return null\n}\n\nfunction resolvePackageConfig(configPath: string, reference: string): string | null {\n try {\n const resolved = createRequire(pathToFileURL(configPath)).resolve(reference)\n return path.extname(resolved) === '.json' ? resolved : null\n } catch {\n return null\n }\n}\n\nfunction resolveExtendedConfig(configPath: string, reference: string): string {\n if (path.isAbsolute(reference) || reference.startsWith('.')) {\n const resolved = resolveExistingConfigPath(path.resolve(path.dirname(configPath), reference))\n if (resolved) return resolved\n } else {\n for (const packageReference of [reference, `${reference}/tsconfig.json`]) {\n const resolved = resolvePackageConfig(configPath, packageReference)\n if (resolved) return resolved\n }\n }\n\n throw new Error(`[internal] TypeScript config extends target not found: ${reference}`)\n}\n\nfunction collectTsconfigPaths(entryPath: string, visited: Set<string> = new Set()): string[] {\n const configPath = path.resolve(entryPath)\n if (visited.has(configPath)) return []\n visited.add(configPath)\n\n const parsed = parseJsonConfig(fs.readFileSync(configPath, 'utf8'))\n if (typeof parsed !== 'object' || parsed === null || !('extends' in parsed)) return [configPath]\n\n const extendsValue = parsed.extends\n const references = typeof extendsValue === 'string'\n ? [extendsValue]\n : Array.isArray(extendsValue) && extendsValue.every((value) => typeof value === 'string')\n ? extendsValue\n : []\n\n return [\n ...references.flatMap((reference) => collectTsconfigPaths(\n resolveExtendedConfig(configPath, reference),\n visited,\n )),\n configPath,\n ]\n}\n\nfunction hashFilesRelativeTo(appRoot: string, filePaths: string[]): Record<string, string> {\n return Object.fromEntries(filePaths.map((filePath) => [\n path.relative(appRoot, filePath).split(path.sep).join('/'),\n contentHash(fs.readFileSync(filePath)),\n ]))\n}\n\nfunction cacheInputHash(tsPath: string, appRoot: string, tsconfigPaths: string[]): string {\n const hash = crypto.createHash('sha256')\n hash.update(JSON.stringify({\n version: DYNAMIC_LOADER_CACHE_VERSION,\n sourceHash: contentHash(fs.readFileSync(tsPath)),\n tsconfigHashes: hashFilesRelativeTo(appRoot, tsconfigPaths),\n }))\n return hash.digest('hex')\n}\n\nfunction dependenciesAreValid(appRoot: string, dependencies: Record<string, string>): boolean {\n return Object.entries(dependencies).every(([relativePath, expectedHash]) => {\n const dependencyPath = path.resolve(appRoot, relativePath)\n return fs.existsSync(dependencyPath)\n && contentHash(fs.readFileSync(dependencyPath)) === expectedHash\n })\n}\n\nfunction collectDependencyHashes(\n appRoot: string,\n inputs: Record<string, unknown>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.keys(inputs)\n .filter((inputPath) => !inputPath.startsWith(`${CLIENT_ONLY_STUB_NAMESPACE}:`))\n .map((inputPath) => {\n const absolutePath = path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(appRoot, inputPath)\n const relativePath = path.relative(appRoot, absolutePath).split(path.sep).join('/')\n return [relativePath, contentHash(fs.readFileSync(absolutePath))]\n })\n .sort(([left], [right]) => left.localeCompare(right)),\n )\n}\n\nfunction readCacheMetadata(metadataPath: string): DynamicLoaderCacheMetadata | null {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(metadataPath, 'utf8'))\n if (\n typeof parsed === 'object'\n && parsed !== null\n && 'version' in parsed\n && parsed.version === DYNAMIC_LOADER_CACHE_VERSION\n && 'inputHash' in parsed\n && typeof parsed.inputHash === 'string'\n && 'outputHash' in parsed\n && typeof parsed.outputHash === 'string'\n && 'dependencies' in parsed\n && typeof parsed.dependencies === 'object'\n && parsed.dependencies !== null\n && Object.values(parsed.dependencies).every((hash) => typeof hash === 'string')\n ) {\n return {\n version: parsed.version,\n inputHash: parsed.inputHash,\n outputHash: parsed.outputHash,\n dependencies: parsed.dependencies as Record<string, string>,\n }\n }\n } catch {\n return null\n }\n return null\n}\n\nfunction cacheIsValid(\n appRoot: string,\n jsPath: string,\n metadataPath: string,\n expectedInputHash: string,\n): boolean {\n if (!fs.existsSync(jsPath)) return false\n const metadata = readCacheMetadata(metadataPath)\n if (!metadata || metadata.inputHash !== expectedInputHash) return false\n return contentHash(fs.readFileSync(jsPath)) === metadata.outputHash\n && dependenciesAreValid(appRoot, metadata.dependencies)\n}\n\n/**\n * Options for `compileAndImport`.\n *\n * Both paths default to the generated-registry layout (`<appRoot>/.mercato/generated/<file>.ts`\n * compiled to a `.mjs` sibling). Sources that live elsewhere in the app \u2014 `src/di.ts` \u2014 MUST pass\n * both explicitly: the default app root is derived by walking three directories up from the source,\n * which only holds inside `.mercato/generated`.\n */\ntype CompileAndImportOptions = {\n appRoot?: string\n outFile?: string\n allowRecovery?: boolean\n}\n\n/**\n * Options for `compileAppSourceFile`.\n *\n * `appRoot` anchors the tsconfig, the `@/` alias resolution and the dependency\n * cache; `outFile` is the absolute path of the artifact to write. `format`\n * selects the module system of that artifact \u2014 `'cjs'` exists for the Jest\n * runtime, which cannot `import()` an ESM sibling.\n */\nexport type CompileAppSourceOptions = {\n appRoot: string\n outFile: string\n format?: 'esm' | 'cjs'\n}\n\n/**\n * Compile one app-owned TypeScript source and its relative import graph into a\n * single JavaScript artifact, leaving every package import external.\n *\n * This is the only supported way to load app source (`apps/<app>/src/**`,\n * `.mercato/generated/**`) from a plain Node process. Those files are never\n * compiled to `dist`, and Node's own type stripping cannot load them: it\n * requires explicit file extensions on relative specifiers and rejects the\n * decorator and enum syntax the entities and DI files use.\n *\n * The artifact is cached against the content of the entry, its whole bundled\n * dependency graph, and the tsconfig chain, so an edit anywhere in the graph\n * invalidates it.\n *\n * The build runs inside the shared esbuild lifecycle. Callers outside a\n * bootstrap load \u2014 the generated-registry loader compiling an `@app` module \u2014\n * would otherwise hold a build on a service another scope is entitled to\n * `stop()`, and would leave the helper process running afterwards. Nesting is\n * safe: the scope only releases the service when the last participant exits.\n */\nexport async function compileAppSourceFile(\n tsPath: string,\n options: CompileAppSourceOptions,\n): Promise<string> {\n return withEsbuildLifecycle(() => compileAppSourceFileWithActiveEsbuild(tsPath, options))\n}\n\nasync function compileAppSourceFileWithActiveEsbuild(\n tsPath: string,\n options: CompileAppSourceOptions,\n): Promise<string> {\n const { appRoot, outFile } = options\n const format = options.format ?? 'esm'\n const appTsconfig = path.join(appRoot, 'tsconfig.json')\n const metadataPath = cacheMetadataPath(outFile)\n\n const tsExists = fs.existsSync(tsPath)\n const tsconfigExists = fs.existsSync(appTsconfig)\n\n if (!tsExists) {\n throw new GeneratedFileNotFoundError(tsPath)\n }\n if (!tsconfigExists) {\n throw new Error(`App TypeScript config not found: ${appTsconfig}`)\n }\n\n const tsconfigPaths = collectTsconfigPaths(appTsconfig)\n const expectedInputHash = cacheInputHash(tsPath, appRoot, tsconfigPaths)\n\n if (cacheIsValid(appRoot, outFile, metadataPath, expectedInputHash)) {\n return outFile\n }\n\n fs.mkdirSync(path.dirname(outFile), { recursive: true })\n // Dynamically import esbuild only when needed\n const esbuild = await getEsbuildRuntime()\n\n const rewrittenPackageManifests = new Set<string>()\n // Use esbuild.build with bundling to handle JSON imports\n const result = await esbuild.build({\n entryPoints: [tsPath],\n outfile: outFile,\n absWorkingDir: appRoot,\n bundle: true,\n metafile: true,\n format,\n platform: 'node',\n target: 'node18',\n tsconfig: appTsconfig,\n plugins: createCliBundlePlugins(appRoot, {\n onLegacySubpathRewrite: (manifestPath) => rewrittenPackageManifests.add(manifestPath),\n }),\n // Allow JSON imports\n loader: { '.json': 'json' },\n })\n const metadata: DynamicLoaderCacheMetadata = {\n version: DYNAMIC_LOADER_CACHE_VERSION,\n inputHash: expectedInputHash,\n outputHash: contentHash(fs.readFileSync(outFile)),\n dependencies: {\n ...collectDependencyHashes(appRoot, result.metafile.inputs),\n ...hashFilesRelativeTo(appRoot, tsconfigPaths),\n ...hashFilesRelativeTo(appRoot, [...rewrittenPackageManifests]),\n },\n }\n fs.writeFileSync(metadataPath, JSON.stringify(metadata))\n\n return outFile\n}\n\n/**\n * Compile a TypeScript file to JavaScript using esbuild bundler.\n * This bundles the file and all its dependencies, handling JSON imports properly.\n * The compiled file is written next to the source file with a .mjs extension unless\n * `outFile` says otherwise.\n */\nasync function compileAndImport(\n tsPath: string,\n options: CompileAndImportOptions = {},\n): Promise<Record<string, unknown>> {\n const allowRecovery = options.allowRecovery ?? true\n const jsPath = options.outFile ?? tsPath.replace(/\\.ts$/, '.mjs')\n const appRoot = options.appRoot ?? path.dirname(path.dirname(path.dirname(tsPath)))\n\n await compileAppSourceFile(tsPath, { appRoot, outFile: jsPath })\n\n // Import the compiled JavaScript\n try {\n const outputHash = contentHash(fs.readFileSync(jsPath))\n const fileUrl = `${pathToFileURL(jsPath).href}?cache=${outputHash}`\n return await import(fileUrl)\n } catch (error) {\n if (!allowRecovery) {\n throw error\n }\n\n const recovered = recoverMikroOrmV7GeneratedCacheFromImportError(appRoot, error)\n if (!recovered.applied) {\n throw error\n }\n\n return compileAndImport(tsPath, { ...options, allowRecovery: false })\n }\n}\n\n\n/**\n * Registers an app-owned generated value on the request container.\n *\n * The app registers these statically from `src/di.ts`, which `createRequestContainer`\n * reaches through the `@/` alias \u2014 and that alias only exists under the bundler.\n * A CLI or MCP process runs plain Node, so the import fails, the failure is\n * swallowed, and the value is simply absent with no diagnostic. Routing it through\n * a registrar built from the same generated file keeps both processes in step.\n */\nfunction appValueRegistrar(key: string, value: unknown): BootstrapData['diRegistrars'][number] {\n return (container) => {\n container.register({ [key]: asValue(value) })\n }\n}\n\n/**\n * Load a generated registry that older apps may not have generated yet.\n *\n * An absent source file is the supported compatibility case and resolves to\n * `fallback` quietly. Any other failure \u2014 a compile error, a broken import, a\n * runtime throw at module scope \u2014 still resolves to `fallback` so bootstrap\n * keeps working, but is reported at error level: a registry that silently\n * degrades to nothing is exactly how command interceptors stopped applying in\n * worker/CLI processes (#4327, #4491).\n */\nasync function loadOptionalGeneratedModule(\n tsPath: string,\n fallback: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n try {\n return await compileAndImport(tsPath)\n } catch (error) {\n if (error instanceof GeneratedFileNotFoundError) {\n logger.debug('Optional generated registry not present, using empty fallback', {\n file: path.basename(tsPath),\n })\n return fallback\n }\n\n logger.error('Failed to load generated registry, continuing without its entries', {\n file: path.basename(tsPath),\n filePath: tsPath,\n err: error,\n })\n return fallback\n }\n}\n\nfunction resolveAppRootOrThrow(appRoot?: string): AppRoot {\n const resolved: AppRoot | null = appRoot\n ? {\n generatedDir: path.join(appRoot, '.mercato', 'generated'),\n appDir: appRoot,\n mercatoDir: path.join(appRoot, '.mercato'),\n }\n : findAppRoot()\n\n if (!resolved) {\n throw new Error(\n 'Could not find app root with .mercato/generated directory. ' +\n 'Make sure you run this command from within a Next.js app directory, ' +\n 'or run \"yarn mercato generate\" first to create the generated files.',\n )\n }\n\n return resolved\n}\n\n/**\n * Load the app-level DI registrar (`src/di.ts`) for the dynamic bootstrap path.\n *\n * The Next.js runtime imports `@/di` statically from its own `src/bootstrap.ts` and hands the\n * registrar to `createBootstrap`. Worker, scheduler and CLI processes bootstrap through\n * `bootstrapFromAppRoot` instead, where the `@/` alias does not exist \u2014 so without this the app's\n * DI registrations silently never ran there, and every request container paid a failed\n * `import('@/di')` resolution (the compatibility fallback in `lib/di/container.ts`).\n *\n * An absent `src/di.ts` is the supported case and resolves to `null` quietly. A file that exists\n * but cannot be compiled, imported, or does not export `register` is reported at error level and\n * still resolves to `null`, so a broken app DI module degrades the same way a broken generated\n * registry does (#4327, #4491) instead of taking the whole process down.\n */\nasync function loadAppDiRegistrar(appDir: string): Promise<AppDiRegistrar | null> {\n const tsPath = path.join(appDir, 'src', 'di.ts')\n if (!fs.existsSync(tsPath)) {\n logger.debug('App-level DI module not present, skipping its registrations', { filePath: tsPath })\n return null\n }\n\n try {\n const appDiModule = await compileAndImport(tsPath, {\n appRoot: appDir,\n outFile: path.join(appDir, '.mercato', 'generated', 'app-di.compiled.mjs'),\n })\n const register = appDiModule.register\n if (typeof register !== 'function') {\n logger.error('App-level DI module exports no register(); its registrations are skipped', {\n filePath: tsPath,\n })\n return null\n }\n return register as AppDiRegistrar\n } catch (error) {\n logger.error('Failed to load the app-level DI module; its registrations are skipped', {\n filePath: tsPath,\n err: error,\n })\n return null\n }\n}\n\n/**\n * Override domains whose applier is not registered by `registerBuiltInModuleOverrideAppliers()`\n * but by importing a domain package for its side effect. `bootstrap-common.ts` does this with a\n * static import right before it dispatches; the dynamic bootstrap path has no bundler to lean on,\n * so it resolves the same modules here \u2014 lazily, and only when an app actually declares the\n * domain, so `@open-mercato/shared` keeps its rule of never taking a runtime dependency on a\n * domain package (soft-optional coupling, `packages/core/AGENTS.md` \u2192 Cross-Module Coupling).\n */\nconst OPTIONAL_OVERRIDE_APPLIER_MODULES: Record<string, string> = {\n ai: '@open-mercato/ai-assistant/modules/ai_assistant/lib/ai-overrides',\n}\n\n/**\n * Import the side-effect module that registers the applier for every declared override domain\n * that has no built-in one. A domain package the app does not install is not an error \u2014 there\n * is nothing for that domain to apply to \u2014 so a failed resolution is logged and skipped, and the\n * dispatcher's own \"domain not yet wired\" warning still fires behind it.\n */\nasync function ensureOptionalOverrideAppliers(enabledModules: ModuleEntryWithOverrides[]): Promise<void> {\n for (const [domain, specifier] of Object.entries(OPTIONAL_OVERRIDE_APPLIER_MODULES)) {\n const declared = enabledModules.some((entry) => {\n const overrides = entry?.overrides as Record<string, unknown> | undefined\n return Boolean(overrides && overrides[domain])\n })\n if (!declared) continue\n try {\n await import(/* webpackIgnore: true */ /* turbopackIgnore: true */ specifier)\n } catch (error) {\n logger.debug('Optional override applier module is not installed; the domain has nothing to apply to', {\n domain,\n specifier,\n err: error,\n })\n }\n }\n}\n\n/**\n * Dispatch `entry.overrides` declared in the app's `src/modules.ts` for the dynamic\n * bootstrap path.\n *\n * The Next.js runtime imports `enabledModules` statically from its own `src/modules.ts` and\n * calls `applyModuleOverridesFromEnabledModules` from `bootstrap-common.ts` before any registry\n * first-loads. Worker, scheduler and CLI processes bootstrap through `bootstrapFromAppRoot`\n * instead, which only ever compiled the generated `modules.cli.generated.ts` \u2014 so an app's\n * `entry.overrides` (encryption maps, ACL features, CLI commands, workers, event subscribers,\n * setup, \u2026) silently never applied there. `seed-encryption` seeding the base encryption maps\n * instead of the app's `overrides.encryption.maps` was the concrete symptom (#5582).\n *\n * An app layout with no `src/modules.ts` at all is logged and skipped \u2014 that is a real\n * compatibility case, handled the same way an absent `src/di.ts` is. A file that is *present*\n * but fails to compile or import is not: it throws, matching how this same function treats\n * every other mandatory input and how the Next.js runtime treats this same file (a static\n * import in `bootstrap-common.ts`). Degrading there would put `seed-encryption` back on the\n * base encryption maps while still printing success \u2014 #5582's outcome, only quieter.\n */\nasync function loadAppModuleOverrides(appDir: string): Promise<void> {\n const tsPath = path.join(appDir, 'src', 'modules.ts')\n if (!fs.existsSync(tsPath)) {\n logger.debug('App-level modules file not present, skipping entry.overrides dispatch', { filePath: tsPath })\n return\n }\n\n let enabledModules: unknown\n try {\n const appModulesModule = await compileAndImport(tsPath, {\n appRoot: appDir,\n outFile: path.join(appDir, '.mercato', 'generated', 'app-modules-overrides.compiled.mjs'),\n })\n enabledModules = appModulesModule.enabledModules\n } catch (error) {\n throw new Error(\n `[internal] Failed to load the app-level modules file (${tsPath}); entry.overrides cannot be applied. ` +\n 'Refusing to bootstrap with a partial override set.',\n { cause: error },\n )\n }\n\n if (!Array.isArray(enabledModules)) {\n throw new Error(\n `[internal] The app-level modules file (${tsPath}) exports no enabledModules array; ` +\n 'entry.overrides cannot be applied. Refusing to bootstrap with a partial override set.',\n )\n }\n\n await ensureOptionalOverrideAppliers(enabledModules as ModuleEntryWithOverrides[])\n applyModuleOverridesFromEnabledModules(enabledModules as ModuleEntryWithOverrides[])\n}\n\n/**\n * Dynamically load bootstrap data from a resolved app directory.\n *\n * IMPORTANT: This only works in unbundled contexts (CLI, tsx).\n * Do NOT use this in Next.js bundled code - use static imports instead.\n *\n * For CLI context, we skip loading modules.generated.ts which has Next.js dependencies.\n * CLI commands are discovered separately via the CLI module system.\n *\n * @param appRoot - Optional explicit app root path. If not provided, will search from cwd.\n * @returns The loaded bootstrap data\n * @throws Error if app root cannot be found or generated files are missing\n */\nasync function loadBootstrapDataWithActiveEsbuild(appRoot?: string): Promise<BootstrapData> {\n const resolved = resolveAppRootOrThrow(appRoot)\n\n const { generatedDir } = resolved\n\n ensureMikroOrmV7GeneratedCacheCompatibility(resolved.appDir)\n\n // IMPORTANT: Load entity IDs FIRST and register them before loading modules.\n // This is because modules (e.g., ce.ts files) use E.xxx.xxx at module scope,\n // and they need entity IDs to be available when they're imported.\n const entityIdsModule = await compileAndImport(path.join(generatedDir, 'entities.ids.generated.ts'))\n registerEntityIds(entityIdsModule.E as BootstrapData['entityIds'])\n\n // Now load the rest of the generated files.\n // modules.cli.generated.ts excludes Next.js-dependent code (routes, APIs, widgets)\n const [\n modulesModule,\n entitiesModule,\n diModule,\n searchModule,\n commandLoadersModule,\n webResearchModule,\n commandInterceptorsModule,\n workflowsModule,\n ] = await Promise.all([\n compileAndImport(path.join(generatedDir, 'modules.cli.generated.ts')),\n compileAndImport(path.join(generatedDir, 'entities.generated.ts')),\n compileAndImport(path.join(generatedDir, 'di.generated.ts')),\n loadOptionalGeneratedModule(path.join(generatedDir, 'search.generated.ts'), { searchModuleConfigs: [] }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'command-loaders.generated.ts'), { commandLoaderEntries: [] }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'web-research-adapters.generated.ts'), {\n webResearchAdapterEntries: [],\n }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'command-interceptors.generated.ts'), {\n commandInterceptorEntries: [],\n }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'workflows.generated.ts'), { allCodeWorkflows: [] }),\n ])\n\n return {\n modules: modulesModule.modules as BootstrapData['modules'],\n entities: entitiesModule.entities as BootstrapData['entities'],\n diRegistrars: [\n ...(diModule.diRegistrars as BootstrapData['diRegistrars']),\n appValueRegistrar('webResearchAdapterEntries', webResearchModule.webResearchAdapterEntries ?? []),\n ],\n entityIds: entityIdsModule.E as BootstrapData['entityIds'],\n // Search configs are needed by workers for indexing\n searchModuleConfigs: (searchModule.searchModuleConfigs ?? []) as BootstrapData['searchModuleConfigs'],\n commandLoaderEntries: (commandLoadersModule.commandLoaderEntries ?? []) as BootstrapData['commandLoaderEntries'],\n // Command interceptors must apply in worker/CLI processes too \u2014 the\n // interceptor registry is per-process, so relying on the Next.js runtime's\n // registration silently no-ops every interceptor for queued/CLI commands\n // (#4327).\n commandInterceptorEntries: (commandInterceptorsModule.commandInterceptorEntries ??\n []) as BootstrapData['commandInterceptorEntries'],\n // Code workflow definitions are needed by workers to resume code-defined instances\n codeWorkflows: (workflowsModule.allCodeWorkflows ?? []) as BootstrapData['codeWorkflows'],\n // Empty UI-related data - not needed for CLI\n dashboardWidgetEntries: [],\n injectionWidgetEntries: [],\n injectionTables: [],\n interceptorEntries: [],\n componentOverrideEntries: [],\n }\n}\n\nexport async function loadBootstrapData(appRoot?: string): Promise<BootstrapData> {\n return withEsbuildLifecycle(() => loadBootstrapDataWithActiveEsbuild(appRoot))\n}\n\n/**\n * Create and execute bootstrap in CLI context.\n *\n * This is a convenience function that finds the app root, loads the generated\n * data dynamically, and runs bootstrap. Use this in CLI entry points.\n *\n * Returns the loaded bootstrap data so the CLI can register modules directly\n * (avoids module resolution issues when importing @open-mercato/cli/mercato).\n *\n * @param appRoot - Optional explicit app root path\n * @returns The loaded bootstrap data (modules, entities, etc.)\n */\nexport async function bootstrapFromAppRoot(appRoot?: string): Promise<BootstrapData> {\n const { createBootstrap, waitForAsyncRegistration } = await import('./factory.js')\n const resolved = resolveAppRootOrThrow(appRoot)\n // All three loads compile through esbuild, so they share one lifecycle scope: without it\n // `loadBootstrapData` releases the esbuild helper process and `loadAppDiRegistrar`\n // silently starts a second one that nothing ever stops.\n const { data, appDiRegistrar } = await withEsbuildLifecycle(async () => {\n // Dispatch the app's `entry.overrides` (src/modules.ts) BEFORE any registry\n // first-loads \u2014 the `bootstrap()` call below runs `registerModules(data.modules)`,\n // and `registerCliModules` in the mercato bin right after this function returns;\n // both read the override side-registry this populates.\n await loadAppModuleOverrides(resolved.appDir)\n return {\n data: await loadBootstrapData(resolved.appDir),\n appDiRegistrar: await loadAppDiRegistrar(resolved.appDir),\n }\n })\n const bootstrap = createBootstrap(data, appDiRegistrar ? { appDiRegistrar } : {})\n bootstrap()\n // In CLI context, wait for async registrations (UI widgets, search configs, etc.)\n await waitForAsyncRegistration()\n\n return data\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { asValue } from 'awilix'\nimport type { BootstrapData } from './types'\nimport type { AppDiRegistrar } from '../di/container'\nimport { findAppRoot, type AppRoot } from './appResolver'\nimport { registerEntityIds } from '../encryption/entityIds'\nimport { createLogger } from '../logger'\nimport {\n applyModuleOverridesFromEnabledModules,\n type ModuleEntryWithOverrides,\n} from '../../modules/overrides'\nimport {\n ensureMikroOrmV7GeneratedCacheCompatibility,\n recoverMikroOrmV7GeneratedCacheFromImportError,\n} from './generatedCacheRecovery'\nimport { CLIENT_ONLY_STUB_NAMESPACE, createClientOnlyStubPlugin } from './clientOnlyModules'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport crypto from 'node:crypto'\nimport { createRequire } from 'node:module'\nimport { pathToFileURL } from 'node:url'\n\nlet activeBootstrapLoads = 0\nlet esbuildRuntime: typeof import('esbuild') | null = null\nlet esbuildStopPromise: Promise<void> | null = null\n\nconst logger = createLogger('shared').child({ component: 'bootstrap' })\n\nasync function getEsbuildRuntime(): Promise<typeof import('esbuild')> {\n if (esbuildStopPromise) await esbuildStopPromise\n if (esbuildRuntime) return esbuildRuntime\n\n const loadedRuntime = await import('esbuild')\n esbuildRuntime ??= loadedRuntime\n return esbuildRuntime\n}\n\nasync function withEsbuildLifecycle<T>(load: () => Promise<T>): Promise<T> {\n activeBootstrapLoads += 1\n\n try {\n return await load()\n } finally {\n activeBootstrapLoads -= 1\n if (activeBootstrapLoads === 0 && esbuildRuntime) {\n // esbuild keeps a helper process alive after build(). Bootstrap compilation\n // is a bounded phase, so release it once every concurrent loader is done.\n // A later build() call transparently starts a fresh helper process.\n const runtimeToStop = esbuildRuntime\n esbuildRuntime = null\n const stopPromise = runtimeToStop.stop().catch((err) => {\n logger.warn('Failed to stop the bootstrap compiler service', { err })\n })\n esbuildStopPromise = stopPromise\n try {\n await stopPromise\n } finally {\n if (esbuildStopPromise === stopPromise) esbuildStopPromise = null\n }\n }\n }\n}\n\n/**\n * Thrown when an expected generated source file is absent.\n *\n * Optional registries treat this as the supported compatibility case (an app\n * that never generated the file), which is what makes it distinguishable from\n * a file that exists but fails to compile or import.\n */\nclass GeneratedFileNotFoundError extends Error {\n readonly filePath: string\n\n constructor(filePath: string) {\n super(`Generated file not found: ${filePath}`)\n this.name = 'GeneratedFileNotFoundError'\n this.filePath = filePath\n }\n}\n\n/**\n * esbuild plugins for the CLI bundle, in resolution order. The client-only stub must come\n * first so it wins over the alias and external plugins for `*.client` dynamic imports.\n *\n * Exported so the wiring itself is testable: a test that only exercises\n * `createClientOnlyStubPlugin` in isolation stays green if the plugin is dropped from this\n * list, which would silently reintroduce #4623.\n */\nexport function createCliBundlePlugins(appRoot: string): import('esbuild').Plugin[] {\n // Plugin to resolve the @/ alias the way the app tsconfig maps it:\n // `@/.mercato/*` to the app root, every other `@/*` to the app's src/ directory.\n const aliasPlugin: import('esbuild').Plugin = {\n name: 'alias-resolver',\n setup(build) {\n build.onResolve({ filter: /^@\\// }, (args) => {\n const rest = args.path.slice('@/'.length)\n const bases = rest.startsWith('.mercato/')\n ? [path.join(appRoot, rest)]\n : [path.join(appRoot, 'src', rest), path.join(appRoot, rest)]\n for (const base of bases) {\n if (fs.existsSync(base) && fs.statSync(base).isFile()) {\n return { path: base }\n }\n for (const suffix of ['.ts', '.tsx', '/index.ts', '/index.tsx']) {\n if (fs.existsSync(base + suffix)) {\n return { path: base + suffix }\n }\n }\n }\n // Nothing matched \u2014 hand esbuild the literal mapping so it reports the\n // missing file against the path the app author actually wrote.\n return { path: path.join(appRoot, rest) }\n })\n },\n }\n\n // Plugin to mark non-JSON package imports as external\n const externalNonJsonPlugin: import('esbuild').Plugin = {\n name: 'external-non-json',\n setup(build) {\n // Mark all package imports as external EXCEPT JSON files\n // Filter matches paths that don't start with . or / (package imports like @open-mercato/shared)\n build.onResolve({ filter: /^[^./]/ }, (args) => {\n // Skip Windows absolute paths (e.g., C:\\...) - they're local files, not packages\n if (/^[a-zA-Z]:/.test(args.path)) {\n return null // Let esbuild handle it\n }\n // If it's a JSON file, let esbuild bundle it\n if (args.path.endsWith('.json')) {\n return null // Let esbuild handle it\n }\n // Otherwise mark as external\n return { path: args.path, external: true }\n })\n },\n }\n\n return [createClientOnlyStubPlugin(), aliasPlugin, externalNonJsonPlugin]\n}\n\nconst DYNAMIC_LOADER_CACHE_VERSION = 4\n\ntype DynamicLoaderCacheMetadata = {\n version: number\n inputHash: string\n outputHash: string\n dependencies: Record<string, string>\n}\n\nfunction cacheMetadataPath(jsPath: string): string {\n return `${jsPath}.cache.json`\n}\n\nfunction contentHash(content: Buffer | string): string {\n return crypto.createHash('sha256').update(content).digest('hex')\n}\n\nfunction parseJsonConfig(content: string): unknown {\n let normalized = ''\n let inString = false\n let escaped = false\n\n for (let index = 0; index < content.length; index += 1) {\n const character = content[index]\n const nextCharacter = content[index + 1]\n\n if (inString) {\n normalized += character\n if (escaped) {\n escaped = false\n } else if (character === '\\\\') {\n escaped = true\n } else if (character === '\"') {\n inString = false\n }\n continue\n }\n\n if (character === '\"') {\n inString = true\n normalized += character\n continue\n }\n\n if (character === '/' && nextCharacter === '/') {\n while (index < content.length && content[index] !== '\\n') index += 1\n normalized += '\\n'\n continue\n }\n\n if (character === '/' && nextCharacter === '*') {\n index += 2\n while (index < content.length && !(content[index] === '*' && content[index + 1] === '/')) {\n index += 1\n }\n index += 1\n continue\n }\n\n if (character === ',') {\n let lookahead = index + 1\n while (lookahead < content.length && /\\s/.test(content[lookahead])) lookahead += 1\n if (content[lookahead] === '}' || content[lookahead] === ']') continue\n }\n\n normalized += character\n }\n\n return JSON.parse(normalized)\n}\n\nfunction resolveExistingConfigPath(candidate: string): string | null {\n for (const configPath of [candidate, `${candidate}.json`, path.join(candidate, 'tsconfig.json')]) {\n if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) return configPath\n }\n return null\n}\n\nfunction resolvePackageConfig(configPath: string, reference: string): string | null {\n try {\n const resolved = createRequire(pathToFileURL(configPath)).resolve(reference)\n return path.extname(resolved) === '.json' ? resolved : null\n } catch {\n return null\n }\n}\n\nfunction resolveExtendedConfig(configPath: string, reference: string): string {\n if (path.isAbsolute(reference) || reference.startsWith('.')) {\n const resolved = resolveExistingConfigPath(path.resolve(path.dirname(configPath), reference))\n if (resolved) return resolved\n } else {\n for (const packageReference of [reference, `${reference}/tsconfig.json`]) {\n const resolved = resolvePackageConfig(configPath, packageReference)\n if (resolved) return resolved\n }\n }\n\n throw new Error(`[internal] TypeScript config extends target not found: ${reference}`)\n}\n\nfunction collectTsconfigPaths(entryPath: string, visited: Set<string> = new Set()): string[] {\n const configPath = path.resolve(entryPath)\n if (visited.has(configPath)) return []\n visited.add(configPath)\n\n const parsed = parseJsonConfig(fs.readFileSync(configPath, 'utf8'))\n if (typeof parsed !== 'object' || parsed === null || !('extends' in parsed)) return [configPath]\n\n const extendsValue = parsed.extends\n const references = typeof extendsValue === 'string'\n ? [extendsValue]\n : Array.isArray(extendsValue) && extendsValue.every((value) => typeof value === 'string')\n ? extendsValue\n : []\n\n return [\n ...references.flatMap((reference) => collectTsconfigPaths(\n resolveExtendedConfig(configPath, reference),\n visited,\n )),\n configPath,\n ]\n}\n\nfunction hashFilesRelativeTo(appRoot: string, filePaths: string[]): Record<string, string> {\n return Object.fromEntries(filePaths.map((filePath) => [\n path.relative(appRoot, filePath).split(path.sep).join('/'),\n contentHash(fs.readFileSync(filePath)),\n ]))\n}\n\nfunction cacheInputHash(tsPath: string, appRoot: string, tsconfigPaths: string[]): string {\n const hash = crypto.createHash('sha256')\n hash.update(JSON.stringify({\n version: DYNAMIC_LOADER_CACHE_VERSION,\n sourceHash: contentHash(fs.readFileSync(tsPath)),\n tsconfigHashes: hashFilesRelativeTo(appRoot, tsconfigPaths),\n }))\n return hash.digest('hex')\n}\n\nfunction dependenciesAreValid(appRoot: string, dependencies: Record<string, string>): boolean {\n return Object.entries(dependencies).every(([relativePath, expectedHash]) => {\n const dependencyPath = path.resolve(appRoot, relativePath)\n return fs.existsSync(dependencyPath)\n && contentHash(fs.readFileSync(dependencyPath)) === expectedHash\n })\n}\n\nfunction collectDependencyHashes(\n appRoot: string,\n inputs: Record<string, unknown>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.keys(inputs)\n .filter((inputPath) => !inputPath.startsWith(`${CLIENT_ONLY_STUB_NAMESPACE}:`))\n .map((inputPath) => {\n const absolutePath = path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(appRoot, inputPath)\n const relativePath = path.relative(appRoot, absolutePath).split(path.sep).join('/')\n return [relativePath, contentHash(fs.readFileSync(absolutePath))]\n })\n .sort(([left], [right]) => left.localeCompare(right)),\n )\n}\n\nfunction readCacheMetadata(metadataPath: string): DynamicLoaderCacheMetadata | null {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(metadataPath, 'utf8'))\n if (\n typeof parsed === 'object'\n && parsed !== null\n && 'version' in parsed\n && parsed.version === DYNAMIC_LOADER_CACHE_VERSION\n && 'inputHash' in parsed\n && typeof parsed.inputHash === 'string'\n && 'outputHash' in parsed\n && typeof parsed.outputHash === 'string'\n && 'dependencies' in parsed\n && typeof parsed.dependencies === 'object'\n && parsed.dependencies !== null\n && Object.values(parsed.dependencies).every((hash) => typeof hash === 'string')\n ) {\n return {\n version: parsed.version,\n inputHash: parsed.inputHash,\n outputHash: parsed.outputHash,\n dependencies: parsed.dependencies as Record<string, string>,\n }\n }\n } catch {\n return null\n }\n return null\n}\n\nfunction cacheIsValid(\n appRoot: string,\n jsPath: string,\n metadataPath: string,\n expectedInputHash: string,\n): boolean {\n if (!fs.existsSync(jsPath)) return false\n const metadata = readCacheMetadata(metadataPath)\n if (!metadata || metadata.inputHash !== expectedInputHash) return false\n return contentHash(fs.readFileSync(jsPath)) === metadata.outputHash\n && dependenciesAreValid(appRoot, metadata.dependencies)\n}\n\n/**\n * Options for `compileAndImport`.\n *\n * Both paths default to the generated-registry layout (`<appRoot>/.mercato/generated/<file>.ts`\n * compiled to a `.mjs` sibling). Sources that live elsewhere in the app \u2014 `src/di.ts` \u2014 MUST pass\n * both explicitly: the default app root is derived by walking three directories up from the source,\n * which only holds inside `.mercato/generated`.\n */\ntype CompileAndImportOptions = {\n appRoot?: string\n outFile?: string\n allowRecovery?: boolean\n}\n\n/**\n * Options for `compileAppSourceFile`.\n *\n * `appRoot` anchors the tsconfig, the `@/` alias resolution and the dependency\n * cache; `outFile` is the absolute path of the artifact to write. `format`\n * selects the module system of that artifact \u2014 `'cjs'` exists for the Jest\n * runtime, which cannot `import()` an ESM sibling.\n */\nexport type CompileAppSourceOptions = {\n appRoot: string\n outFile: string\n format?: 'esm' | 'cjs'\n}\n\n/**\n * Compile one app-owned TypeScript source and its relative import graph into a\n * single JavaScript artifact, leaving every package import external.\n *\n * This is the only supported way to load app source (`apps/<app>/src/**`,\n * `.mercato/generated/**`) from a plain Node process. Those files are never\n * compiled to `dist`, and Node's own type stripping cannot load them: it\n * requires explicit file extensions on relative specifiers and rejects the\n * decorator and enum syntax the entities and DI files use.\n *\n * The artifact is cached against the content of the entry, its whole bundled\n * dependency graph, and the tsconfig chain, so an edit anywhere in the graph\n * invalidates it.\n *\n * The build runs inside the shared esbuild lifecycle. Callers outside a\n * bootstrap load \u2014 the generated-registry loader compiling an `@app` module \u2014\n * would otherwise hold a build on a service another scope is entitled to\n * `stop()`, and would leave the helper process running afterwards. Nesting is\n * safe: the scope only releases the service when the last participant exits.\n */\nexport async function compileAppSourceFile(\n tsPath: string,\n options: CompileAppSourceOptions,\n): Promise<string> {\n return withEsbuildLifecycle(() => compileAppSourceFileWithActiveEsbuild(tsPath, options))\n}\n\nasync function compileAppSourceFileWithActiveEsbuild(\n tsPath: string,\n options: CompileAppSourceOptions,\n): Promise<string> {\n const { appRoot, outFile } = options\n const format = options.format ?? 'esm'\n const appTsconfig = path.join(appRoot, 'tsconfig.json')\n const metadataPath = cacheMetadataPath(outFile)\n\n const tsExists = fs.existsSync(tsPath)\n const tsconfigExists = fs.existsSync(appTsconfig)\n\n if (!tsExists) {\n throw new GeneratedFileNotFoundError(tsPath)\n }\n if (!tsconfigExists) {\n throw new Error(`App TypeScript config not found: ${appTsconfig}`)\n }\n\n const tsconfigPaths = collectTsconfigPaths(appTsconfig)\n const expectedInputHash = cacheInputHash(tsPath, appRoot, tsconfigPaths)\n\n if (cacheIsValid(appRoot, outFile, metadataPath, expectedInputHash)) {\n return outFile\n }\n\n fs.mkdirSync(path.dirname(outFile), { recursive: true })\n // Dynamically import esbuild only when needed\n const esbuild = await getEsbuildRuntime()\n\n // Use esbuild.build with bundling to handle JSON imports\n const result = await esbuild.build({\n entryPoints: [tsPath],\n outfile: outFile,\n absWorkingDir: appRoot,\n bundle: true,\n metafile: true,\n format,\n platform: 'node',\n target: 'node18',\n tsconfig: appTsconfig,\n plugins: createCliBundlePlugins(appRoot),\n // Allow JSON imports\n loader: { '.json': 'json' },\n })\n const metadata: DynamicLoaderCacheMetadata = {\n version: DYNAMIC_LOADER_CACHE_VERSION,\n inputHash: expectedInputHash,\n outputHash: contentHash(fs.readFileSync(outFile)),\n dependencies: {\n ...collectDependencyHashes(appRoot, result.metafile.inputs),\n ...hashFilesRelativeTo(appRoot, tsconfigPaths),\n },\n }\n fs.writeFileSync(metadataPath, JSON.stringify(metadata))\n\n return outFile\n}\n\n/**\n * Compile a TypeScript file to JavaScript using esbuild bundler.\n * This bundles the file and all its dependencies, handling JSON imports properly.\n * The compiled file is written next to the source file with a .mjs extension unless\n * `outFile` says otherwise.\n */\nasync function compileAndImport(\n tsPath: string,\n options: CompileAndImportOptions = {},\n): Promise<Record<string, unknown>> {\n const allowRecovery = options.allowRecovery ?? true\n const jsPath = options.outFile ?? tsPath.replace(/\\.ts$/, '.mjs')\n const appRoot = options.appRoot ?? path.dirname(path.dirname(path.dirname(tsPath)))\n\n await compileAppSourceFile(tsPath, { appRoot, outFile: jsPath })\n\n // Import the compiled JavaScript\n try {\n const outputHash = contentHash(fs.readFileSync(jsPath))\n const fileUrl = `${pathToFileURL(jsPath).href}?cache=${outputHash}`\n return await import(fileUrl)\n } catch (error) {\n if (!allowRecovery) {\n throw error\n }\n\n const recovered = recoverMikroOrmV7GeneratedCacheFromImportError(appRoot, error)\n if (!recovered.applied) {\n throw error\n }\n\n return compileAndImport(tsPath, { ...options, allowRecovery: false })\n }\n}\n\n\n/**\n * Registers an app-owned generated value on the request container.\n *\n * The app registers these statically from `src/di.ts`, which `createRequestContainer`\n * reaches through the `@/` alias \u2014 and that alias only exists under the bundler.\n * A CLI or MCP process runs plain Node, so the import fails, the failure is\n * swallowed, and the value is simply absent with no diagnostic. Routing it through\n * a registrar built from the same generated file keeps both processes in step.\n */\nfunction appValueRegistrar(key: string, value: unknown): BootstrapData['diRegistrars'][number] {\n return (container) => {\n container.register({ [key]: asValue(value) })\n }\n}\n\n/**\n * Load a generated registry that older apps may not have generated yet.\n *\n * An absent source file is the supported compatibility case and resolves to\n * `fallback` quietly. Any other failure \u2014 a compile error, a broken import, a\n * runtime throw at module scope \u2014 still resolves to `fallback` so bootstrap\n * keeps working, but is reported at error level: a registry that silently\n * degrades to nothing is exactly how command interceptors stopped applying in\n * worker/CLI processes (#4327, #4491).\n */\nasync function loadOptionalGeneratedModule(\n tsPath: string,\n fallback: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n try {\n return await compileAndImport(tsPath)\n } catch (error) {\n if (error instanceof GeneratedFileNotFoundError) {\n logger.debug('Optional generated registry not present, using empty fallback', {\n file: path.basename(tsPath),\n })\n return fallback\n }\n\n logger.error('Failed to load generated registry, continuing without its entries', {\n file: path.basename(tsPath),\n filePath: tsPath,\n err: error,\n })\n return fallback\n }\n}\n\nfunction resolveAppRootOrThrow(appRoot?: string): AppRoot {\n const resolved: AppRoot | null = appRoot\n ? {\n generatedDir: path.join(appRoot, '.mercato', 'generated'),\n appDir: appRoot,\n mercatoDir: path.join(appRoot, '.mercato'),\n }\n : findAppRoot()\n\n if (!resolved) {\n throw new Error(\n 'Could not find app root with .mercato/generated directory. ' +\n 'Make sure you run this command from within a Next.js app directory, ' +\n 'or run \"yarn mercato generate\" first to create the generated files.',\n )\n }\n\n return resolved\n}\n\n/**\n * Load the app-level DI registrar (`src/di.ts`) for the dynamic bootstrap path.\n *\n * The Next.js runtime imports `@/di` statically from its own `src/bootstrap.ts` and hands the\n * registrar to `createBootstrap`. Worker, scheduler and CLI processes bootstrap through\n * `bootstrapFromAppRoot` instead, where the `@/` alias does not exist \u2014 so without this the app's\n * DI registrations silently never ran there, and every request container paid a failed\n * `import('@/di')` resolution (the compatibility fallback in `lib/di/container.ts`).\n *\n * An absent `src/di.ts` is the supported case and resolves to `null` quietly. A file that exists\n * but cannot be compiled, imported, or does not export `register` is reported at error level and\n * still resolves to `null`, so a broken app DI module degrades the same way a broken generated\n * registry does (#4327, #4491) instead of taking the whole process down.\n */\nasync function loadAppDiRegistrar(appDir: string): Promise<AppDiRegistrar | null> {\n const tsPath = path.join(appDir, 'src', 'di.ts')\n if (!fs.existsSync(tsPath)) {\n logger.debug('App-level DI module not present, skipping its registrations', { filePath: tsPath })\n return null\n }\n\n try {\n const appDiModule = await compileAndImport(tsPath, {\n appRoot: appDir,\n outFile: path.join(appDir, '.mercato', 'generated', 'app-di.compiled.mjs'),\n })\n const register = appDiModule.register\n if (typeof register !== 'function') {\n logger.error('App-level DI module exports no register(); its registrations are skipped', {\n filePath: tsPath,\n })\n return null\n }\n return register as AppDiRegistrar\n } catch (error) {\n logger.error('Failed to load the app-level DI module; its registrations are skipped', {\n filePath: tsPath,\n err: error,\n })\n return null\n }\n}\n\n/**\n * Override domains whose applier is not registered by `registerBuiltInModuleOverrideAppliers()`\n * but by importing a domain package for its side effect. `bootstrap-common.ts` does this with a\n * static import right before it dispatches; the dynamic bootstrap path has no bundler to lean on,\n * so it resolves the same modules here \u2014 lazily, and only when an app actually declares the\n * domain, so `@open-mercato/shared` keeps its rule of never taking a runtime dependency on a\n * domain package (soft-optional coupling, `packages/core/AGENTS.md` \u2192 Cross-Module Coupling).\n */\nconst OPTIONAL_OVERRIDE_APPLIER_MODULES: Record<string, string> = {\n ai: '@open-mercato/ai-assistant/modules/ai_assistant/lib/ai-overrides',\n}\n\n/**\n * Import the side-effect module that registers the applier for every declared override domain\n * that has no built-in one. A domain package the app does not install is not an error \u2014 there\n * is nothing for that domain to apply to \u2014 so a failed resolution is logged and skipped, and the\n * dispatcher's own \"domain not yet wired\" warning still fires behind it.\n */\nasync function ensureOptionalOverrideAppliers(enabledModules: ModuleEntryWithOverrides[]): Promise<void> {\n for (const [domain, specifier] of Object.entries(OPTIONAL_OVERRIDE_APPLIER_MODULES)) {\n const declared = enabledModules.some((entry) => {\n const overrides = entry?.overrides as Record<string, unknown> | undefined\n return Boolean(overrides && overrides[domain])\n })\n if (!declared) continue\n try {\n await import(/* webpackIgnore: true */ /* turbopackIgnore: true */ specifier)\n } catch (error) {\n logger.debug('Optional override applier module is not installed; the domain has nothing to apply to', {\n domain,\n specifier,\n err: error,\n })\n }\n }\n}\n\n/**\n * Dispatch `entry.overrides` declared in the app's `src/modules.ts` for the dynamic\n * bootstrap path.\n *\n * The Next.js runtime imports `enabledModules` statically from its own `src/modules.ts` and\n * calls `applyModuleOverridesFromEnabledModules` from `bootstrap-common.ts` before any registry\n * first-loads. Worker, scheduler and CLI processes bootstrap through `bootstrapFromAppRoot`\n * instead, which only ever compiled the generated `modules.cli.generated.ts` \u2014 so an app's\n * `entry.overrides` (encryption maps, ACL features, CLI commands, workers, event subscribers,\n * setup, \u2026) silently never applied there. `seed-encryption` seeding the base encryption maps\n * instead of the app's `overrides.encryption.maps` was the concrete symptom (#5582).\n *\n * An app layout with no `src/modules.ts` at all is logged and skipped \u2014 that is a real\n * compatibility case, handled the same way an absent `src/di.ts` is. A file that is *present*\n * but fails to compile or import is not: it throws, matching how this same function treats\n * every other mandatory input and how the Next.js runtime treats this same file (a static\n * import in `bootstrap-common.ts`). Degrading there would put `seed-encryption` back on the\n * base encryption maps while still printing success \u2014 #5582's outcome, only quieter.\n */\nasync function loadAppModuleOverrides(appDir: string): Promise<void> {\n const tsPath = path.join(appDir, 'src', 'modules.ts')\n if (!fs.existsSync(tsPath)) {\n logger.debug('App-level modules file not present, skipping entry.overrides dispatch', { filePath: tsPath })\n return\n }\n\n let enabledModules: unknown\n try {\n const appModulesModule = await compileAndImport(tsPath, {\n appRoot: appDir,\n outFile: path.join(appDir, '.mercato', 'generated', 'app-modules-overrides.compiled.mjs'),\n })\n enabledModules = appModulesModule.enabledModules\n } catch (error) {\n throw new Error(\n `[internal] Failed to load the app-level modules file (${tsPath}); entry.overrides cannot be applied. ` +\n 'Refusing to bootstrap with a partial override set.',\n { cause: error },\n )\n }\n\n if (!Array.isArray(enabledModules)) {\n throw new Error(\n `[internal] The app-level modules file (${tsPath}) exports no enabledModules array; ` +\n 'entry.overrides cannot be applied. Refusing to bootstrap with a partial override set.',\n )\n }\n\n await ensureOptionalOverrideAppliers(enabledModules as ModuleEntryWithOverrides[])\n applyModuleOverridesFromEnabledModules(enabledModules as ModuleEntryWithOverrides[])\n}\n\n/**\n * Dynamically load bootstrap data from a resolved app directory.\n *\n * IMPORTANT: This only works in unbundled contexts (CLI, tsx).\n * Do NOT use this in Next.js bundled code - use static imports instead.\n *\n * For CLI context, we skip loading modules.generated.ts which has Next.js dependencies.\n * CLI commands are discovered separately via the CLI module system.\n *\n * @param appRoot - Optional explicit app root path. If not provided, will search from cwd.\n * @returns The loaded bootstrap data\n * @throws Error if app root cannot be found or generated files are missing\n */\nasync function loadBootstrapDataWithActiveEsbuild(appRoot?: string): Promise<BootstrapData> {\n const resolved = resolveAppRootOrThrow(appRoot)\n\n const { generatedDir } = resolved\n\n ensureMikroOrmV7GeneratedCacheCompatibility(resolved.appDir)\n\n // IMPORTANT: Load entity IDs FIRST and register them before loading modules.\n // This is because modules (e.g., ce.ts files) use E.xxx.xxx at module scope,\n // and they need entity IDs to be available when they're imported.\n const entityIdsModule = await compileAndImport(path.join(generatedDir, 'entities.ids.generated.ts'))\n registerEntityIds(entityIdsModule.E as BootstrapData['entityIds'])\n\n // Now load the rest of the generated files.\n // modules.cli.generated.ts excludes Next.js-dependent code (routes, APIs, widgets)\n const [\n modulesModule,\n entitiesModule,\n diModule,\n searchModule,\n commandLoadersModule,\n webResearchModule,\n commandInterceptorsModule,\n workflowsModule,\n ] = await Promise.all([\n compileAndImport(path.join(generatedDir, 'modules.cli.generated.ts')),\n compileAndImport(path.join(generatedDir, 'entities.generated.ts')),\n compileAndImport(path.join(generatedDir, 'di.generated.ts')),\n loadOptionalGeneratedModule(path.join(generatedDir, 'search.generated.ts'), { searchModuleConfigs: [] }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'command-loaders.generated.ts'), { commandLoaderEntries: [] }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'web-research-adapters.generated.ts'), {\n webResearchAdapterEntries: [],\n }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'command-interceptors.generated.ts'), {\n commandInterceptorEntries: [],\n }),\n loadOptionalGeneratedModule(path.join(generatedDir, 'workflows.generated.ts'), { allCodeWorkflows: [] }),\n ])\n\n return {\n modules: modulesModule.modules as BootstrapData['modules'],\n entities: entitiesModule.entities as BootstrapData['entities'],\n diRegistrars: [\n ...(diModule.diRegistrars as BootstrapData['diRegistrars']),\n appValueRegistrar('webResearchAdapterEntries', webResearchModule.webResearchAdapterEntries ?? []),\n ],\n entityIds: entityIdsModule.E as BootstrapData['entityIds'],\n // Search configs are needed by workers for indexing\n searchModuleConfigs: (searchModule.searchModuleConfigs ?? []) as BootstrapData['searchModuleConfigs'],\n commandLoaderEntries: (commandLoadersModule.commandLoaderEntries ?? []) as BootstrapData['commandLoaderEntries'],\n // Command interceptors must apply in worker/CLI processes too \u2014 the\n // interceptor registry is per-process, so relying on the Next.js runtime's\n // registration silently no-ops every interceptor for queued/CLI commands\n // (#4327).\n commandInterceptorEntries: (commandInterceptorsModule.commandInterceptorEntries ??\n []) as BootstrapData['commandInterceptorEntries'],\n // Code workflow definitions are needed by workers to resume code-defined instances\n codeWorkflows: (workflowsModule.allCodeWorkflows ?? []) as BootstrapData['codeWorkflows'],\n // Empty UI-related data - not needed for CLI\n dashboardWidgetEntries: [],\n injectionWidgetEntries: [],\n injectionTables: [],\n interceptorEntries: [],\n componentOverrideEntries: [],\n }\n}\n\nexport async function loadBootstrapData(appRoot?: string): Promise<BootstrapData> {\n return withEsbuildLifecycle(() => loadBootstrapDataWithActiveEsbuild(appRoot))\n}\n\n/**\n * Create and execute bootstrap in CLI context.\n *\n * This is a convenience function that finds the app root, loads the generated\n * data dynamically, and runs bootstrap. Use this in CLI entry points.\n *\n * Returns the loaded bootstrap data so the CLI can register modules directly\n * (avoids module resolution issues when importing @open-mercato/cli/mercato).\n *\n * @param appRoot - Optional explicit app root path\n * @returns The loaded bootstrap data (modules, entities, etc.)\n */\nexport async function bootstrapFromAppRoot(appRoot?: string): Promise<BootstrapData> {\n const { createBootstrap, waitForAsyncRegistration } = await import('./factory.js')\n const resolved = resolveAppRootOrThrow(appRoot)\n // All three loads compile through esbuild, so they share one lifecycle scope: without it\n // `loadBootstrapData` releases the esbuild helper process and `loadAppDiRegistrar`\n // silently starts a second one that nothing ever stops.\n const { data, appDiRegistrar } = await withEsbuildLifecycle(async () => {\n // Dispatch the app's `entry.overrides` (src/modules.ts) BEFORE any registry\n // first-loads \u2014 the `bootstrap()` call below runs `registerModules(data.modules)`,\n // and `registerCliModules` in the mercato bin right after this function returns;\n // both read the override side-registry this populates.\n await loadAppModuleOverrides(resolved.appDir)\n return {\n data: await loadBootstrapData(resolved.appDir),\n appDiRegistrar: await loadAppDiRegistrar(resolved.appDir),\n }\n })\n const bootstrap = createBootstrap(data, appDiRegistrar ? { appDiRegistrar } : {})\n bootstrap()\n // In CLI context, wait for async registrations (UI widgets, search configs, etc.)\n await waitForAsyncRegistration()\n\n return data\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -86,10 +86,9 @@ async function waitForAsyncRegistration() {
86
86
  async function registerWidgetsAndOptionalPackages(data, options) {
87
87
  try {
88
88
  const coreInjection = await import("@open-mercato/core/modules/widgets/lib/injection");
89
- coreInjection.registerCoreInjectionWidgets(
90
- data.injectionWidgetEntries,
91
- options.skipCoreInjectionWidgets ? { mode: "merge" } : void 0
92
- );
89
+ if (!options.skipCoreInjectionWidgets) {
90
+ coreInjection.registerCoreInjectionWidgets(data.injectionWidgetEntries);
91
+ }
93
92
  coreInjection.registerCoreInjectionTables(data.injectionTables, data.injectionWidgetEntries);
94
93
  coreInjection.registerEnabledModuleIds(
95
94
  data.modules.map((module) => module.id).filter((id) => typeof id === "string" && id.length > 0)