@open-mercato/cli 0.10.1-develop.7809.1.ea24461aeb → 0.10.1-develop.7813.1.83931e7add
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/agentic/guides/module-facts.json +162 -162
- package/dist/agentic/guides/module-facts.v2.json +162 -162
- package/dist/agentic/guides/modules/agent_orchestrator/index.md +1 -1
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/availability/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/carrier_inpost/index.md +1 -1
- package/dist/agentic/guides/modules/cart/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/channel_resend/index.md +1 -1
- package/dist/agentic/guides/modules/channel_ses/index.md +1 -1
- package/dist/agentic/guides/modules/channel_smtp/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customer_groups/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/documents/index.md +1 -1
- package/dist/agentic/guides/modules/ecommerce/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/forms/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_autopay/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_tpay/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/phone_calls/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/promotions/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/seeds/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/telemetry/index.md +1 -1
- package/dist/agentic/guides/modules/tillio/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +40 -38
- package/dist/agentic/guides/upstream/manifest.json +2 -2
- package/dist/lib/generators/ast/imports.js +9 -4
- package/dist/lib/generators/ast/imports.js.map +2 -2
- package/dist/lib/generators/entity-ids.js +10 -12
- package/dist/lib/generators/entity-ids.js.map +2 -2
- package/dist/lib/generators/module-di.js +6 -9
- package/dist/lib/generators/module-di.js.map +2 -2
- package/dist/lib/generators/module-entities.js +6 -9
- package/dist/lib/generators/module-entities.js.map +2 -2
- package/package.json +7 -7
- package/src/lib/generators/ast/imports.ts +14 -4
- package/src/lib/generators/entity-ids.ts +10 -12
- package/src/lib/generators/module-di.ts +6 -9
- package/src/lib/generators/module-entities.ts +6 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# staff — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/staff
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# storage_s3 — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/storage-s3 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/storage-s3 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/storage-s3/src/modules/storage_s3
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# sync_akeneo — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/sync-akeneo 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/sync-akeneo 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/sync-akeneo/src/modules/sync_akeneo
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# sync_excel — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/sync_excel
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# system_status_overlays — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/enterprise 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/enterprise 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/enterprise/src/modules/system_status_overlays
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# telemetry — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/telemetry 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/telemetry 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/telemetry/src/modules/telemetry
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# tillio — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/tillio 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/tillio 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/tillio/src/modules/tillio
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# translations — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/translations
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# warranty_claims — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/warranty_claims
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# webhooks — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/webhooks 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/webhooks 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/webhooks/src/modules/webhooks
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# wms — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/wms
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# workflows — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.10.1-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.10.1-develop.7813.1.83931e7add; core 0.10.1-develop.7813.1.83931e7add — R1 staleness stamp -->
|
|
3
3
|
Source root: node_modules/@open-mercato/core/src/modules/workflows
|
|
4
4
|
|
|
5
5
|
## Sections
|
|
@@ -1185,7 +1185,7 @@
|
|
|
1185
1185
|
"facts": {
|
|
1186
1186
|
"title": "Example Module",
|
|
1187
1187
|
"description": "Demonstrates pages, APIs, entities and DI.",
|
|
1188
|
-
"coreVersion": "0.10.1-develop.
|
|
1188
|
+
"coreVersion": "0.10.1-develop.7813.1.83931e7add",
|
|
1189
1189
|
"sourcePackage": null,
|
|
1190
1190
|
"sourceVersion": null,
|
|
1191
1191
|
"sourceRoot": "src/modules/example",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Backward Compatibility Contract
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Every listed surface is a **public contract**. Changes MUST follow the deprecation protocol or block merge as **breaking changes**.
|
|
4
4
|
|
|
5
5
|
## Deprecation Protocol
|
|
6
6
|
|
|
@@ -68,7 +68,7 @@ The following file names, their expected export names, and their role in module
|
|
|
68
68
|
|
|
69
69
|
### 2. Type Definitions & Interfaces (STABLE)
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Required fields MUST NOT be removed or narrowed. Optional fields may be added freely.
|
|
72
72
|
|
|
73
73
|
**Immutable required fields** (removing or renaming any is a breaking change):
|
|
74
74
|
|
|
@@ -112,7 +112,7 @@ These exported types are consumed by module developers. Required fields MUST NOT
|
|
|
112
112
|
|
|
113
113
|
### 3. Function Signatures (STABLE)
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
Signatures MUST NOT change incompatibly. New optional parameters may be added.
|
|
116
116
|
|
|
117
117
|
|Function|Package|Contract|
|
|
118
118
|
|---|---|---|
|
|
@@ -180,8 +180,6 @@ Spot IDs are the addresses where external modules inject UI. Renaming or removin
|
|
|
180
180
|
|
|
181
181
|
### 7. API Route URLs (STABLE)
|
|
182
182
|
|
|
183
|
-
External tools, frontends, and integrations depend on API URL patterns.
|
|
184
|
-
|
|
185
183
|
- MUST NOT rename or remove an existing API route URL
|
|
186
184
|
- MUST NOT change the HTTP method for an existing operation
|
|
187
185
|
- MUST NOT remove fields from existing response schemas
|
|
@@ -312,7 +310,7 @@ Files in `apps/mercato/.mercato/generated/` are produced by the CLI generators.
|
|
|
312
310
|
|
|
313
311
|
|Surface|Change|Classification|
|
|
314
312
|
|---|---|---|
|
|
315
|
-
|Type interface (`IntegrationScope`)|New **optional** field `userId?: string \|
|
|
313
|
+
|Type interface (`IntegrationScope`)|New **optional** field `userId?: string \|null`|✓ ADDITIVE (Type interface, optional field)|
|
|
316
314
|
|Database schema|New nullable column `integration_credentials.user_id uuid` via additive migration `Migration20260526154136`, plus partial unique index `integration_credentials_user_lookup_idx` on `(integration_id, organization_id, tenant_id, user_id)` `WHERE user_id IS NOT NULL AND deleted_at IS NULL`|✓ ADDITIVE (NULL default; the partial index leaves existing tenant-wide rows untouched)|
|
|
317
315
|
|`createCredentialsService` API|`getRaw` / `resolve` / `save` / `saveField` signatures unchanged; when `scope.userId` is falsy the lookup filter pins `user_id = NULL`, reproducing the prior tenant-wide behaviour exactly|✓ Behaviour-preserving for existing callers|
|
|
318
316
|
|
|
@@ -423,7 +421,7 @@ Deleting a user who had customised their sidebar failed on the `user_sidebar_pre
|
|
|
423
421
|
|Surface|Change|Classification|
|
|
424
422
|
|---|---|---|
|
|
425
423
|
|Function signatures|New export `onModulesRegistered(listener)` on `@open-mercato/shared/lib/modules/registry`|✓ ADDITIVE (new function)|
|
|
426
|
-
|Type definitions|New export `ModulesRegisteredListener = (modules: Module[]) => void \|
|
|
424
|
+
|Type definitions|New export `ModulesRegisteredListener = (modules: Module[]) => void \|PromiseLike<void>`|✓ ADDITIVE (new type, no rename)|
|
|
427
425
|
|`registerModules(modules)`|Signature, return type, and synchronous behavior unchanged; it now also notifies listeners after the reconciliation it already performed|✓ Behaviour-preserving for existing callers|
|
|
428
426
|
|Import paths|None — both exports ship from the existing registry path|✓ No change|
|
|
429
427
|
|Event IDs, API routes, DB schema, DI names, ACL features, notification IDs, CLI commands, generated files|No change|✓ n/a|
|
|
@@ -470,7 +468,7 @@ Issue #3852 removed the non-cryptographic passkey verification shape from `Passk
|
|
|
470
468
|
|
|
471
469
|
|Surface|Change|Classification|
|
|
472
470
|
|---|---|---|
|
|
473
|
-
|Type definitions (§2)|New optional method `DataSyncAdapter.supportsStartControl?(control, entityType)`; new exported type `DataSyncStartControl = 'fullSync' \|
|
|
471
|
+
|Type definitions (§2)|New optional method `DataSyncAdapter.supportsStartControl?(control, entityType)`; new exported type `DataSyncStartControl = 'fullSync' \|'batchSize'`|✓ ADDITIVE (optional member, new type — same shape as the `persistsSharedCursor` and `runParameters` additions before it)|
|
|
474
472
|
|Import paths (§4)|New module `data_sync/lib/start-controls.ts` exporting `resolveStartControlMap`, `applicableStartControls`, `StartControlMap`, `StartControlApplicability`, `DATA_SYNC_START_CONTROLS`|✓ ADDITIVE (new path; nothing moved or re-exported)|
|
|
475
473
|
|API route URLs (§7)|`GET /api/data_sync/options` items gain a `startControls` object; `POST /api/data_sync/run` is unchanged and keeps honouring `fullSync` and `batchSize` whatever an adapter declares|✓ ADDITIVE (new optional response field, no request-shape change)|
|
|
476
474
|
|Auto-discovery, function signatures, event IDs, widget spot IDs, DB schema, DI names, ACL features, notification IDs, CLI commands, generated files|No change|✓ n/a|
|
|
@@ -546,11 +544,11 @@ Clients use WebAuthn; operators audit key provenance, re-enroll with recovery. [
|
|
|
546
544
|
|Type definitions (`CommandHandler`, `CommandRuntimeContext`, `CommandExecuteResult`)|New optional `atomicReplay?: boolean` and `stabilizeReplay(...)` handler capabilities, optional `replayTransactionGuard` request guard, optional caller-owned `transactionLifetime`, and optional `replaySourceFinalized?: boolean` result signal. `TransactionLifetime` plus its observation/completion-registration helpers are new exports; lifetime creation/completion remains owned by `withAtomicFlush`|✓ ADDITIVE (optional fields and exports; omitted handlers and contexts keep the prior flow)|
|
|
547
545
|
|`ActionLogService` method signatures|`log`, `claimForUndo`, `releaseUndoClaim`, and `markUndone` accept an optional trailing transactional `EntityManager`; new `claimForRedo` method|✓ ADDITIVE (optional parameters appended and a new method; existing calls retain behavior)|
|
|
548
546
|
|`RbacService`|New `loadAclWithEntityManager`, `userHasAllFeaturesWithEntityManager`, and `getGrantedFeaturesWithEntityManager` methods bypass caches and bind every query to the supplied transaction|✓ ADDITIVE (new methods; existing cache-backed methods are unchanged)|
|
|
549
|
-
|
|
|
550
|
-
|
|
|
551
|
-
|
|
|
552
|
-
|
|
|
553
|
-
|
|
|
547
|
+
|Auth command replay behavior|Auth user/role handlers opt in so source-log state, domain changes, undo trace or new redo log, and redo source finalization commit or roll back together. Before the request guard or feature interceptors run, `stabilizeReplay` discovers and seals one actor/target/destination footprint and locks API keys, users, roles, tenant/organization hierarchy, and authorization children in a total order using the same transaction|⚠️ Intentional security hardening. A race that previously could deadlock or replay with stale authority is rejected with the existing domain `409`; successful, authorized replay keeps the same response shape|
|
|
548
|
+
|Action-log actor persistence and self replay|`actor_user_id` remains a UUID; new entries also store the canonical user or `api_key:<uuid>` subject in `context.actorSubject`. API-key list ownership, undo/redo ownership, exact-EM RBAC, locks, and latest replay queries use the canonical subject. Canonical history is selected before the legacy bare-UUID fallback, which additionally requires a coherent live `isApiKey`/`keyId`/`sub` tuple|✓ Database-compatible additive context metadata; same-UUID user, malformed, or ambiguous ownership cannot shadow canonical key history and fails closed|
|
|
549
|
+
|Auth authorization-state writers|First-party `UserRole`, `UserAcl`, and `RoleAcl` writers in commands, setup, CLI, execution principals, SSO, and agent orchestration now share the canonical parent-lock protocol; SSO membership and grant rows commit together|⚠️ Intentional concurrency hardening; no request, response, schema, import-path, event, feature, or CLI contract changes|
|
|
550
|
+
|Non-auth command replay|Handlers that omit `atomicReplay` retain the existing undo claim/release compensation and route-level redo finalization|✓ Behavior-preserving|
|
|
551
|
+
|API routes, response schemas, database schema, event IDs, ACL feature IDs, DI names, CLI commands, generated files|No shape or identifier change|✓ n/a|
|
|
554
552
|
|
|
555
553
|
**Migration path for existing modules**: none. Third-party commands remain on the established replay lifecycle unless they explicitly set `atomicReplay: true`. An opting-in handler must perform all replay database work through `ctx.transactionalEm`; when authorization depends on mutable domain rows it may add `stabilizeReplay` to acquire its complete footprint before guards and interceptors. The command bus supplies and owns the transaction by default. A caller deliberately composing replay inside an already-active `ctx.transactionalEm` must open that outer transaction with `withAtomicFlush(..., { transaction: true })`, obtain its exact `TransactionLifetime` inside the phase, and pass it as `ctx.transactionLifetime`; otherwise replay fails before mutation. Commit-only hooks and redo-finalization reporting follow the true outer completion. The capability does not claim that legacy non-opted-in action-log and domain writes are transactionally atomic.
|
|
556
554
|
|
|
@@ -560,11 +558,11 @@ Clients use WebAuthn; operators audit key provenance, re-enroll with recovery. [
|
|
|
560
558
|
|
|
561
559
|
`directory.organizations.update` treated an omitted `parentId` as `null` and an omitted `childIds` as `[]`, so a partial update — notably `PUT /api/directory/organization-branding`, which sends only logo fields — detached the organization from its parent and orphaned its children. Omitted hierarchy fields are now preserved:
|
|
562
560
|
|
|
563
|
-
|
|
|
561
|
+
|Surface|Change|Classification|
|
|
564
562
|
|---|---|---|
|
|
565
|
-
|
|
|
566
|
-
|
|
|
567
|
-
|
|
|
563
|
+
|Command behaviour (`directory.organizations.update`)|`parentId` is written and validated only when present in the input; children are reconciled only when `childIds` is present. Explicit `parentId: null` and `childIds: []` still clear. With `childIds` present and `parentId` omitted, listing the current parent answers `400 Child cannot equal parent` (it answered `400 Cannot assign ancestor as child`)|⚠️ Behaviour change on a previously-corrupting path. A caller that omitted the fields to clear the hierarchy must send the explicit values. Regression-tested in `updateOrganization.partial-hierarchy.test.ts` and `TC-DIR-018`|
|
|
564
|
+
|API routes (`PUT /api/directory/organizations`, `PUT /api/directory/organization-branding`)|Same URLs, request schema (`organizationUpdateSchema` already declares both fields optional) and response shapes|✓ No shape change|
|
|
565
|
+
|Database schema, event IDs, ACL features, DI names, CLI commands|No change|✓ n/a|
|
|
568
566
|
|
|
569
567
|
**Migration path for existing modules**: send `parentId: null` / `childIds: []` where clearing is intended. Trees flattened before the upgrade are not repaired (see UPGRADE_NOTES.md).
|
|
570
568
|
|
|
@@ -574,12 +572,12 @@ Clients use WebAuthn; operators audit key provenance, re-enroll with recovery. [
|
|
|
574
572
|
|
|
575
573
|
`POST /api/auth/logout` answered `401` before its handler ran once the access token expired, so the remember-me session was never revoked ([#7225](https://github.com/open-mercato/open-mercato/issues/7225)). It now declares `requireAuth: false`, like the portal logout:
|
|
576
574
|
|
|
577
|
-
|
|
|
575
|
+
|Surface|Change|Classification|
|
|
578
576
|
|---|---|---|
|
|
579
|
-
|
|
|
580
|
-
|
|
|
581
|
-
|
|
582
|
-
|
|
|
577
|
+
|API route gating|`requireAuth` `true` → `false`; the handler revokes only the sessions its own cookies identify|⚠️ Narrow relaxation: missing/unverifiable token or no cookie got `401`, now `307` (UPGRADE_NOTES.md)|
|
|
578
|
+
|URL, method, response shape|Unchanged|✓ n/a|
|
|
579
|
+
|`auth.logout` event|Emitted only for a verified staff `auth_token` (now incl. MFA-pending); `session_token`-only revocation emits none|✓ No ID or payload change|
|
|
580
|
+
|Database schema, ACL features, DI names, CLI commands|No change|✓ n/a|
|
|
583
581
|
|
|
584
582
|
**Migration path for existing modules**: none. A client that read a logout `401` as "already signed out" gets the redirect instead.
|
|
585
583
|
|
|
@@ -593,23 +591,23 @@ Clients use WebAuthn; operators audit key provenance, re-enroll with recovery. [
|
|
|
593
591
|
|
|
594
592
|
[`.ai/specs/2026-10-01-oauth2-grant-lifecycle-core.md`](.ai/specs/2026-10-01-oauth2-grant-lifecycle-core.md) (parent: [`.ai/specs/2026-09-27-app-spec-oauth2-grant-lifecycle.md`](.ai/specs/2026-09-27-app-spec-oauth2-grant-lifecycle.md) §10.1) adds a tenant-level OAuth2 grant core to `integrations` that no existing integration uses yet. **All changes are additive** except the reserved `__oauth_grant` suffix, an intentional security narrowing that no first-party integration or bundle id hits. Developer guide: `apps/docs/docs/framework/modules/integrations-oauth-grants.mdx`.
|
|
595
593
|
|
|
596
|
-
|
|
|
594
|
+
|Surface|Change|Classification|
|
|
597
595
|
|---|---|---|
|
|
598
|
-
|
|
|
599
|
-
|
|
|
600
|
-
|
|
|
601
|
-
|
|
|
602
|
-
|
|
|
603
|
-
|
|
|
604
|
-
|
|
|
605
|
-
|
|
|
606
|
-
|
|
|
607
|
-
|
|
|
608
|
-
|
|
|
609
|
-
|
|
|
610
|
-
|
|
|
611
|
-
|
|
|
612
|
-
|
|
|
596
|
+
|Import paths (§4)|New `@open-mercato/shared/lib/db/advisoryLock` (explicit `exports` entry); `@open-mercato/core/modules/integrations/lib/oauth/{token-endpoint,pkce,authorization,redirect,resource-challenge,descriptor,grant-service,health}` and `…/lib/oauth/testing/fakeAuthorizationServer` — exactly these files, no directory index. Every path, plus `…/lib/credentials-service`, `…/lib/log-service` and the hub's `…/communication_channels/lib/oauth-state`, is verified against the built `dist` by `scripts/check-oauth-publish-shape.mjs` in CI|✓ ADDITIVE (new import paths)|
|
|
597
|
+
|Type definitions (§2)|New `OAuthProviderDescriptor`, `OAuthGrantOwner`, `OAuthTokenEndpointResponse`, `OAuthClientAuthMethod`, the grant-service result and inspection types (the inspection carries no token), `AdvisoryLockOptions` (`waitDeadlineMs`, `maxConcurrentHolders`); the `FakeAuthorizationServer` handle with its options, `FakeInjection` and `FakeRotationMode`; error classes `OAuthGrantError`, `OAuthDescriptorError`, `AdvisoryLockUnavailableError` (`reason: AdvisoryLockUnavailableReason` = `'deadline' \|'transient_db' \|'commit_unknown'`); closed unions (`OAuthTokenFailure`, `OAuthConnectFailure`, `OAuthConnectionState`, `OAuthUnavailableReason`, …) that are additive-only, so consumers keep a default branch. `IntegrationOAuthGrantService` is a type to call, not to implement: adding a method is additive. Optional `IntegrationDetailPageConfig.connectTabId`. `CredentialsService`, `IntegrationLogService` and `IntegrationCredentialFieldOauth` are unchanged apart from `@internal` options|✓ ADDITIVE (new types; optional fields)|
|
|
598
|
+
|Function signatures (§3)|New `withAdvisoryXactLock`, `createPkcePair`, `buildAuthorizationUrl`, `exchangeAuthorizationCode`, `resolveOAuthRedirectUri`, `classifyResourceChallenge`, `mapInspectionToHealth` with `OAUTH_HEALTH_CODES`, `startFakeAuthorizationServer` with the methods of the handle it returns (`issueAuthorizationCode`, `inject`, `revokeAuthorization`, `reset`, `counters`, `requests`, `issuedTokens`, `close`) and the `IntegrationOAuthGrantService` methods|✓ ADDITIVE (new functions)|
|
|
599
|
+
|DI service names (§9)|New scoped `integrationOAuthGrantService`. Contract note: inside the grant lock the service builds its credentials and log services from the core factories, so DI overrides of `integrationCredentialsService` don't apply to grant rows|✓ ADDITIVE|
|
|
600
|
+
|API routes (§7)|`GET /api/integrations/:id` gains the nullable `oauthGrant: { status: 'active' \|'invalidated' \|'unavailable' } \|null` (always present; `null` without a live grant) and returns `integration.detailPage.connectTabId`|✓ ADDITIVE (response fields)|
|
|
601
|
+
|Widget injection context (§6)|Spot IDs unchanged; the `integrations.detail.v1` context gains the optional `detail.oauthGrant` and `integration.detailPage.connectTabId`|✓ ADDITIVE (context fields)|
|
|
602
|
+
|Log and health codes|Log codes `integrations.oauth_*` and the `OAUTH_HEALTH_CODES` values with `OAuthHealthCode`|✓ ADDITIVE; STABLE once released, additive-only|
|
|
603
|
+
|Persisted formats|The grant row id `<integrationId>__oauth_grant`; the blob `version`; the lock key `oauth_grant:<integrationId>:<tenantId>:<organizationId>:<userId or ->` and its mapping `pg_try_advisory_xact_lock(hashtextextended(key, 0))`; `resourceKind` `integrations.oauth_grant`; the `Symbol.for` brands `@open-mercato/shared:AdvisoryLockUnavailableError`, `@open-mercato/core:OAuthGrantError` and `@open-mercato/core:OAuthDescriptorError` that keep `instanceof` reliable across module copies. The codes `integrations.oauth_disconnected` and `integrations.oauth_revocation_{pending,confirmed,failed,unsupported,skipped_reconnected,skipped_invalidated}` with their `disconnectId` payload key are read back to derive `lastDisconnect`; the per-process holder-slot registry `globalThis.__openMercatoAdvisoryLockSlots__` is shared by every `@open-mercato/shared` instance|The lock key, its mapping and the brand keys FROZEN for every existing Grant Owner (processes of two versions must exclude each other during a rolling deploy); everything else ADDITIVE-ONLY|
|
|
604
|
+
|External dependency|Provider routes import the hub-owned `@open-mercato/core/modules/communication_channels/lib/oauth-state`: `createOAuthState`, `verifyOAuthState`, `consumeOAuthStateOnce`, `OAuthStatePayload`, `OAuthStateConsumeStore` and `OAuthStateError` (its `code` values additive-only, `replay` included) are documented as STABLE; the path's other exports are not covered|✓ No change to the path (now a documented STABLE import)|
|
|
605
|
+
|Testing contract|With `OM_ENABLE_TEST_OAUTH_GRANTS` on (or outside production), a descriptor may use `http:` endpoints on a loopback host (`localhost`, `127.0.0.1`, `[::1]`), so a provider's test seam can point its descriptor at an in-process fake; otherwise endpoints are `https:`|STABLE; the flag itself enables nothing else for providers|
|
|
606
|
+
|API routes (§7): `GET` / `PUT /api/integrations/:id/credentials`|Answer 404 for any id ending in `__oauth_grant`, also when an integration with that id is registered (I4: grant secrets never reach the admin credentials API)|⚠️ Intentional security narrowing only (no first-party integration id ends in the suffix)|
|
|
607
|
+
|Function behaviour (§3, §9): `resolve()` and `resolveUpdatedAt()` of `createCredentialsService` / DI `integrationCredentialsService`|Don't fall through to a `bundleId` ending in `__oauth_grant`, for every caller (integration list and detail GETs, the credentials route, the health service, data_sync); the grant service's Client Configuration read skips it too|⚠️ Intentional security narrowing only (I4, I7; no first-party bundle id ends in the suffix)|
|
|
608
|
+
|Explicitly not covered (`@internal`)|`createIntegrationOAuthGrantService`, `IntegrationOAuthGrantServiceDeps`, `requestTokenEndpoint`, `revokeToken`, `OAuthTokenEndpointError` with `OAuthTokenEndpointErrorKind` and its brand, `OAUTH_RESPONSE_MAX_BYTES`, `OAuthClientCredentials`, `OAuthInvalidatedReason`, `oauthProviderDescriptorSchema`, `resolveOAuthProviderDescriptor`, `AdvisoryLockOptions.onWait` with `AdvisoryLockWaitResult`, `isTransientLockDbError` (`@open-mercato/shared/lib/db/pg-errors`), the third parameter `{ kms }` of `createCredentialsService`, `CredentialsWriteOptions.ensureEncryptionMap`, `eraseIntegrationCredentials`, `readCredentialRowLayered`, `LayeredCredentialRead`, `isReservedOAuthGrantId`, `bundleFallthroughId`, `findLatestIntegrationLogsByCodes`, and every export of `lib/oauth/{grant-blob,pin-tenant-dek,error-brand}`|Not a contract surface; may change without the deprecation protocol|
|
|
609
|
+
|Not contracts|The test-only route `POST /api/integrations/test-oauth-grants`, its helper `@open-mercato/core/helpers/integration/oauthGrantTestRoute`, the flag `OM_ENABLE_TEST_OAUTH_GRANTS` (apart from the testing contract above) and the `test_oauth_grant` integration (like `test-seed`)|n/a|
|
|
610
|
+
|Event IDs, database schema, ACL features, notification types, AI agent and tool IDs, CLI commands|No change|✓ n/a|
|
|
613
611
|
|
|
614
612
|
**Migration path for existing modules**: none for first-party code. Third-party modules must not register an integration or bundle id that ends in `__oauth_grant` (see `UPGRADE_NOTES.md`).
|
|
615
613
|
|
|
@@ -632,3 +630,7 @@ STABLE API §7: `GET /api/checkout/pay/:slug` omits admin fields; retaining them
|
|
|
632
630
|
## #3805 2026-10-31
|
|
633
631
|
|
|
634
632
|
STABLE tools/execute writes bypass approval; no bridge. [Migrate](UPGRADE_NOTES.md#issue-3805)
|
|
633
|
+
|
|
634
|
+
## SCIM rate limiting (2026-10-27)
|
|
635
|
+
|
|
636
|
+
SCIM adds 429/503 before credentials; honor Retry-After. Optional `beforeAuth: ApiRouteBeforeAuth` is additive. See [contract and migration](.ai/specs/enterprise/implemented/SPEC-ENT-004-2026-02-19-sso-directory-sync.md#migration--backward-compatibility).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"generator": "@open-mercato/cli@0.10.1-develop.
|
|
3
|
+
"generator": "@open-mercato/cli@0.10.1-develop.7813.1.83931e7add",
|
|
4
4
|
"files": {
|
|
5
5
|
"AGENTS.md": "b27342ee5f61e805ba52703fdb7ec822b030490f734b4d80f48dfd1e05fa4cf5",
|
|
6
|
-
"BACKWARD_COMPATIBILITY.md": "
|
|
6
|
+
"BACKWARD_COMPATIBILITY.md": "ffcf62846c1d7ab3238979c4915203fd13ee183c6b5064b10bd397142d1b2683"
|
|
7
7
|
}
|
|
8
8
|
}
|
|
@@ -45,9 +45,11 @@ function addImportSpec(sourceFile, spec) {
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
function addImportSpecs(sourceFile, specs) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
if (specs.length === 0) return;
|
|
49
|
+
sourceFile.addImportDeclarations(specs.map((spec) => ({
|
|
50
|
+
kind: StructureKind.ImportDeclaration,
|
|
51
|
+
...spec
|
|
52
|
+
})));
|
|
51
53
|
}
|
|
52
54
|
function addImportStatement(sourceFile, statement) {
|
|
53
55
|
const trimmed = statement.trim();
|
|
@@ -55,9 +57,12 @@ function addImportStatement(sourceFile, statement) {
|
|
|
55
57
|
addImportSpec(sourceFile, toImportSpec(trimmed));
|
|
56
58
|
}
|
|
57
59
|
function addImportStatements(sourceFile, statements) {
|
|
60
|
+
const specs = [];
|
|
58
61
|
for (const statement of statements) {
|
|
59
|
-
|
|
62
|
+
const trimmed = statement.trim();
|
|
63
|
+
if (trimmed) specs.push(toImportSpec(trimmed));
|
|
60
64
|
}
|
|
65
|
+
addImportSpecs(sourceFile, specs);
|
|
61
66
|
}
|
|
62
67
|
export {
|
|
63
68
|
addImportSpec,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/generators/ast/imports.ts"],
|
|
4
|
-
"sourcesContent": ["import ts from 'typescript-js'\nimport {\n StructureKind,\n type ImportDeclarationStructure,\n type OptionalKind,\n type SourceFile,\n} from 'ts-morph'\n\nexport type GeneratedImportSpec = OptionalKind<ImportDeclarationStructure>\n\nfunction toImportSpec(statement: string): GeneratedImportSpec {\n const trimmed = statement.trim()\n const sourceFile = ts.createSourceFile('import.ts', trimmed, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const importDeclaration = sourceFile.statements.find(ts.isImportDeclaration)\n if (!importDeclaration) {\n throw new Error(`Expected import declaration, received: ${statement}`)\n }\n\n const moduleSpecifier = importDeclaration.moduleSpecifier\n if (!ts.isStringLiteral(moduleSpecifier)) {\n throw new Error(`Unsupported import declaration: ${statement}`)\n }\n\n const spec: GeneratedImportSpec = {\n kind: StructureKind.ImportDeclaration,\n moduleSpecifier: moduleSpecifier.text,\n }\n\n const clause = importDeclaration.importClause\n if (!clause) {\n return spec\n }\n\n spec.isTypeOnly = clause.isTypeOnly\n\n if (clause.name) {\n spec.defaultImport = clause.name.text\n }\n\n if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {\n spec.namespaceImport = clause.namedBindings.name.text\n }\n\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n spec.namedImports = clause.namedBindings.elements.map((element) => ({\n kind: StructureKind.ImportSpecifier,\n name: element.propertyName?.text ?? element.name.text,\n alias: element.propertyName ? element.name.text : undefined,\n isTypeOnly: element.isTypeOnly,\n }))\n }\n\n return spec\n}\n\nexport function addImportSpec(sourceFile: SourceFile, spec: GeneratedImportSpec): void {\n sourceFile.addImportDeclaration({\n kind: StructureKind.ImportDeclaration,\n ...spec,\n })\n}\n\nexport function addImportSpecs(sourceFile: SourceFile, specs: GeneratedImportSpec[]): void {\n
|
|
5
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf;AAAA,EACE;AAAA,OAIK;AAIP,SAAS,aAAa,WAAwC;AAC5D,QAAM,UAAU,UAAU,KAAK;AAC/B,QAAM,aAAa,GAAG,iBAAiB,aAAa,SAAS,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,EAAE;AAC3G,QAAM,oBAAoB,WAAW,WAAW,KAAK,GAAG,mBAAmB;AAC3E,MAAI,CAAC,mBAAmB;AACtB,UAAM,IAAI,MAAM,0CAA0C,SAAS,EAAE;AAAA,EACvE;AAEA,QAAM,kBAAkB,kBAAkB;AAC1C,MAAI,CAAC,GAAG,gBAAgB,eAAe,GAAG;AACxC,UAAM,IAAI,MAAM,mCAAmC,SAAS,EAAE;AAAA,EAChE;AAEA,QAAM,OAA4B;AAAA,IAChC,MAAM,cAAc;AAAA,IACpB,iBAAiB,gBAAgB;AAAA,EACnC;AAEA,QAAM,SAAS,kBAAkB;AACjC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,OAAK,aAAa,OAAO;AAEzB,MAAI,OAAO,MAAM;AACf,SAAK,gBAAgB,OAAO,KAAK;AAAA,EACnC;AAEA,MAAI,OAAO,iBAAiB,GAAG,kBAAkB,OAAO,aAAa,GAAG;AACtE,SAAK,kBAAkB,OAAO,cAAc,KAAK;AAAA,EACnD;AAEA,MAAI,OAAO,iBAAiB,GAAG,eAAe,OAAO,aAAa,GAAG;AACnE,SAAK,eAAe,OAAO,cAAc,SAAS,IAAI,CAAC,aAAa;AAAA,MAClE,MAAM,cAAc;AAAA,MACpB,MAAM,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,MACjD,OAAO,QAAQ,eAAe,QAAQ,KAAK,OAAO;AAAA,MAClD,YAAY,QAAQ;AAAA,IACtB,EAAE;AAAA,EACJ;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,YAAwB,MAAiC;AACrF,aAAW,qBAAqB;AAAA,IAC9B,MAAM,cAAc;AAAA,IACpB,GAAG;AAAA,EACL,CAAC;AACH;
|
|
4
|
+
"sourcesContent": ["import ts from 'typescript-js'\nimport {\n StructureKind,\n type ImportDeclarationStructure,\n type OptionalKind,\n type SourceFile,\n} from 'ts-morph'\n\nexport type GeneratedImportSpec = OptionalKind<ImportDeclarationStructure>\n\nfunction toImportSpec(statement: string): GeneratedImportSpec {\n const trimmed = statement.trim()\n const sourceFile = ts.createSourceFile('import.ts', trimmed, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const importDeclaration = sourceFile.statements.find(ts.isImportDeclaration)\n if (!importDeclaration) {\n throw new Error(`Expected import declaration, received: ${statement}`)\n }\n\n const moduleSpecifier = importDeclaration.moduleSpecifier\n if (!ts.isStringLiteral(moduleSpecifier)) {\n throw new Error(`Unsupported import declaration: ${statement}`)\n }\n\n const spec: GeneratedImportSpec = {\n kind: StructureKind.ImportDeclaration,\n moduleSpecifier: moduleSpecifier.text,\n }\n\n const clause = importDeclaration.importClause\n if (!clause) {\n return spec\n }\n\n spec.isTypeOnly = clause.isTypeOnly\n\n if (clause.name) {\n spec.defaultImport = clause.name.text\n }\n\n if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {\n spec.namespaceImport = clause.namedBindings.name.text\n }\n\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n spec.namedImports = clause.namedBindings.elements.map((element) => ({\n kind: StructureKind.ImportSpecifier,\n name: element.propertyName?.text ?? element.name.text,\n alias: element.propertyName ? element.name.text : undefined,\n isTypeOnly: element.isTypeOnly,\n }))\n }\n\n return spec\n}\n\nexport function addImportSpec(sourceFile: SourceFile, spec: GeneratedImportSpec): void {\n sourceFile.addImportDeclaration({\n kind: StructureKind.ImportDeclaration,\n ...spec,\n })\n}\n\n/**\n * Inserts every import in one ts-morph manipulation. Each `addImportDeclaration` call\n * re-prints and re-parses the whole source file, so adding registry imports one by one is\n * quadratic in the import count and dominated `mercato generate` peak memory.\n */\nexport function addImportSpecs(sourceFile: SourceFile, specs: GeneratedImportSpec[]): void {\n if (specs.length === 0) return\n sourceFile.addImportDeclarations(specs.map((spec) => ({\n kind: StructureKind.ImportDeclaration,\n ...spec,\n })))\n}\n\nexport function addImportStatement(sourceFile: SourceFile, statement: string): void {\n const trimmed = statement.trim()\n if (!trimmed) return\n addImportSpec(sourceFile, toImportSpec(trimmed))\n}\n\nexport function addImportStatements(sourceFile: SourceFile, statements: string[]): void {\n const specs: GeneratedImportSpec[] = []\n for (const statement of statements) {\n const trimmed = statement.trim()\n if (trimmed) specs.push(toImportSpec(trimmed))\n }\n addImportSpecs(sourceFile, specs)\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,QAAQ;AACf;AAAA,EACE;AAAA,OAIK;AAIP,SAAS,aAAa,WAAwC;AAC5D,QAAM,UAAU,UAAU,KAAK;AAC/B,QAAM,aAAa,GAAG,iBAAiB,aAAa,SAAS,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,EAAE;AAC3G,QAAM,oBAAoB,WAAW,WAAW,KAAK,GAAG,mBAAmB;AAC3E,MAAI,CAAC,mBAAmB;AACtB,UAAM,IAAI,MAAM,0CAA0C,SAAS,EAAE;AAAA,EACvE;AAEA,QAAM,kBAAkB,kBAAkB;AAC1C,MAAI,CAAC,GAAG,gBAAgB,eAAe,GAAG;AACxC,UAAM,IAAI,MAAM,mCAAmC,SAAS,EAAE;AAAA,EAChE;AAEA,QAAM,OAA4B;AAAA,IAChC,MAAM,cAAc;AAAA,IACpB,iBAAiB,gBAAgB;AAAA,EACnC;AAEA,QAAM,SAAS,kBAAkB;AACjC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,OAAK,aAAa,OAAO;AAEzB,MAAI,OAAO,MAAM;AACf,SAAK,gBAAgB,OAAO,KAAK;AAAA,EACnC;AAEA,MAAI,OAAO,iBAAiB,GAAG,kBAAkB,OAAO,aAAa,GAAG;AACtE,SAAK,kBAAkB,OAAO,cAAc,KAAK;AAAA,EACnD;AAEA,MAAI,OAAO,iBAAiB,GAAG,eAAe,OAAO,aAAa,GAAG;AACnE,SAAK,eAAe,OAAO,cAAc,SAAS,IAAI,CAAC,aAAa;AAAA,MAClE,MAAM,cAAc;AAAA,MACpB,MAAM,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,MACjD,OAAO,QAAQ,eAAe,QAAQ,KAAK,OAAO;AAAA,MAClD,YAAY,QAAQ;AAAA,IACtB,EAAE;AAAA,EACJ;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,YAAwB,MAAiC;AACrF,aAAW,qBAAqB;AAAA,IAC9B,MAAM,cAAc;AAAA,IACpB,GAAG;AAAA,EACL,CAAC;AACH;AAOO,SAAS,eAAe,YAAwB,OAAoC;AACzF,MAAI,MAAM,WAAW,EAAG;AACxB,aAAW,sBAAsB,MAAM,IAAI,CAAC,UAAU;AAAA,IACpD,MAAM,cAAc;AAAA,IACpB,GAAG;AAAA,EACL,EAAE,CAAC;AACL;AAEO,SAAS,mBAAmB,YAAwB,WAAyB;AAClF,QAAM,UAAU,UAAU,KAAK;AAC/B,MAAI,CAAC,QAAS;AACd,gBAAc,YAAY,aAAa,OAAO,CAAC;AACjD;AAEO,SAAS,oBAAoB,YAAwB,YAA4B;AACtF,QAAM,QAA+B,CAAC;AACtC,aAAW,aAAa,YAAY;AAClC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAS,OAAM,KAAK,aAAa,OAAO,CAAC;AAAA,EAC/C;AACA,iBAAe,YAAY,KAAK;AAClC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -181,18 +181,16 @@ function writePerEntityFieldFiles(outRoot, fieldsByEntity, result) {
|
|
|
181
181
|
const entDir = path.join(outRoot, entity);
|
|
182
182
|
fs.mkdirSync(entDir, { recursive: true });
|
|
183
183
|
const sourceFile = createGeneratedSourceFile(`${entity}/index.ts`);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
});
|
|
195
|
-
}
|
|
184
|
+
sourceFile.addVariableStatements(fields.map((field) => ({
|
|
185
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
186
|
+
isExported: true,
|
|
187
|
+
declarations: [
|
|
188
|
+
{
|
|
189
|
+
name: toVar(field),
|
|
190
|
+
initializer: JSON.stringify(field)
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
})));
|
|
196
194
|
writeTrackedFile(path.join(entDir, "index.ts"), getSourceText(sourceFile), result);
|
|
197
195
|
}
|
|
198
196
|
const existingEntries = fs.existsSync(outRoot) ? fs.readdirSync(outRoot, { withFileTypes: true }) : [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/generators/entity-ids.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript-js'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n toVar,\n toSnake,\n rimrafDir,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n writeIfChanged,\n} from '../utils'\nimport { addAutoGeneratedComment, createGeneratedSourceFile, elementAccess, getSourceText, identifier, returnStatement } from './ast'\n\ntype GroupKey = '@app' | '@open-mercato/core' | string\ntype EntityFieldMap = Record<string, string[]>\n\nexport interface EntityIdsOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\n/**\n * Extract exported class names from a TypeScript source file without dynamic import.\n * This is used for @app modules since Node.js can't import TypeScript files directly.\n */\nfunction parseExportedClassNamesFromFile(filePath: string): string[] {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n const classNames: string[] = []\n\n sf.forEachChild((node) => {\n // Check for exported class declarations\n if (ts.isClassDeclaration(node) && node.name) {\n const hasExport = node.modifiers?.some(\n (m) => m.kind === ts.SyntaxKind.ExportKeyword\n )\n if (hasExport) {\n classNames.push(node.name.text)\n }\n }\n })\n\n return classNames\n}\n\nfunction unwrapObjectLiteralExpression(\n expression: ts.Expression | undefined,\n): ts.ObjectLiteralExpression | undefined {\n if (!expression) return undefined\n if (ts.isObjectLiteralExpression(expression)) return expression\n if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n if (ts.isParenthesizedExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n return undefined\n}\n\nfunction readPropertyInitializer(\n objectLiteral: ts.ObjectLiteralExpression,\n propertyName: string,\n): ts.Expression | undefined {\n for (const property of objectLiteral.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name === propertyName) {\n return property.initializer\n }\n }\n return undefined\n}\n\nfunction parseGeneratedModuleEntityNames(filePath: string, moduleId: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n const declaration = statement.declarationList.declarations.find((candidate) =>\n ts.isIdentifier(candidate.name) && candidate.name.text === 'E')\n if (!declaration) continue\n\n const eObject = unwrapObjectLiteralExpression(declaration.initializer)\n if (!eObject) continue\n\n const moduleObject = unwrapObjectLiteralExpression(readPropertyInitializer(eObject, moduleId))\n if (!moduleObject) return []\n\n const names: string[] = []\n for (const property of moduleObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name) names.push(name)\n }\n return names\n }\n\n return []\n}\n\nfunction parseGeneratedEntityFieldsFile(filePath: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n const fields: string[] = []\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n if (!ts.isStringLiteralLike(declaration.initializer)) continue\n fields.push(declaration.initializer.text)\n }\n }\n\n return Array.from(new Set(fields))\n}\n\nfunction resolveExistingFile(candidates: string[]): string | null {\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nfunction loadStandaloneGeneratedPackageEntities(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): { entityNames: string[]; entityFieldMap: EntityFieldMap } | null {\n if (resolver.isMonorepo() || !entry.from || entry.from === '@app') return null\n\n const packageRoot = resolver.getPackageRoot(entry.from)\n const generatedRoot = fs.existsSync(path.join(packageRoot, 'generated'))\n ? path.join(packageRoot, 'generated')\n : path.join(packageRoot, 'dist', 'generated')\n const idsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities.ids.generated.ts'),\n path.join(generatedRoot, 'entities.ids.generated.js'),\n ])\n if (!idsFile) return null\n const entityNames = parseGeneratedModuleEntityNames(idsFile, entry.id)\n\n if (entityNames.length === 0) return null\n\n const entityFieldMap: EntityFieldMap = {}\n for (const entityName of entityNames) {\n const fieldsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities', entityName, 'index.ts'),\n path.join(generatedRoot, 'entities', entityName, 'index.js'),\n ])\n if (!fieldsFile) continue\n const fields = parseGeneratedEntityFieldsFile(fieldsFile)\n entityFieldMap[entityName] = fields\n }\n\n return { entityNames, entityFieldMap }\n}\n\nfunction parseEntityFieldsFromFile(filePath: string, exportedClassNames: string[]): EntityFieldMap {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n\n const exported = new Set(exportedClassNames)\n const result: EntityFieldMap = {}\n\n function getDecoratorArgNameLiteral(dec: ts.Decorator | undefined): string | undefined {\n if (!dec) return undefined\n const expr = dec.expression\n if (!ts.isCallExpression(expr)) return undefined\n if (!expr.arguments.length) return undefined\n const first = expr.arguments[0]\n if (!ts.isObjectLiteralExpression(first)) return undefined\n for (const prop of first.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'name') {\n if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text\n }\n }\n return undefined\n }\n\n function normalizeDbName(propertyName: string, _decoratorName?: string, nameOverride?: string): string {\n if (nameOverride) return nameOverride\n return toSnake(propertyName)\n }\n\n sf.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n const clsName = node.name.text\n if (!exported.has(clsName)) return\n const entityKey = toSnake(clsName)\n const fields: string[] = []\n\n for (const member of node.members) {\n if (!ts.isPropertyDeclaration(member) || !member.name) continue\n const name = ts.isIdentifier(member.name)\n ? member.name.text\n : ts.isStringLiteral(member.name)\n ? member.name.text\n : undefined\n if (!name) continue\n if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue\n const decorators = ts.canHaveDecorators(member)\n ? ts.getDecorators(member) ?? []\n : []\n let dbName: string | undefined\n if (decorators && decorators.length) {\n for (const d of decorators) {\n const nameOverride = getDecoratorArgNameLiteral(d)\n dbName = normalizeDbName(name, undefined, nameOverride)\n if (dbName) break\n }\n }\n if (!dbName) dbName = normalizeDbName(name)\n fields.push(dbName)\n }\n result[entityKey] = Array.from(new Set(fields))\n })\n\n return result\n}\n\nfunction writeTrackedFile(\n filePath: string,\n content: string,\n result: GeneratorResult,\n): void {\n if (writeIfChanged(filePath, content)) {\n result.filesWritten.push(filePath)\n } else {\n result.filesUnchanged.push(filePath)\n }\n}\n\nfunction writePerEntityFieldFiles(\n outRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n fs.mkdirSync(outRoot, { recursive: true })\n const desiredEntities = new Set(Object.keys(fieldsByEntity))\n for (const [entity, fields] of Object.entries(fieldsByEntity)) {\n const entDir = path.join(outRoot, entity)\n fs.mkdirSync(entDir, { recursive: true })\n const sourceFile = createGeneratedSourceFile(`${entity}/index.ts`)\n for (const field of fields) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: toVar(field),\n initializer: JSON.stringify(field),\n },\n ],\n })\n }\n writeTrackedFile(path.join(entDir, 'index.ts'), getSourceText(sourceFile), result)\n }\n\n const existingEntries = fs.existsSync(outRoot) ? fs.readdirSync(outRoot, { withFileTypes: true }) : []\n for (const entry of existingEntries) {\n if (!entry.isDirectory()) continue\n if (desiredEntities.has(entry.name)) continue\n const staleDirectory = path.join(outRoot, entry.name)\n rimrafDir(staleDirectory)\n result.filesWritten.push(staleDirectory)\n }\n}\n\nfunction writeEntityFieldsRegistry(\n generatedRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n const entities = Object.keys(fieldsByEntity).sort((a, b) => a.localeCompare(b))\n const registry: Record<string, Record<string, string>> = {}\n for (const entity of entities) {\n registry[toVar(entity)] = {}\n for (const field of fieldsByEntity[entity] ?? []) {\n registry[toVar(entity)][toVar(field)] = field\n }\n }\n\n const sourceFile = createGeneratedSourceFile('entity-fields-registry.ts')\n addAutoGeneratedComment(sourceFile, 'entity-ids')\n sourceFile.insertText(sourceFile.getFullText().length, '// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility\\n')\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entityFieldsRegistry',\n type: 'Record<string, Record<string, string>>',\n initializer: JSON.stringify(registry, null, 2),\n },\n ],\n })\n sourceFile.addFunction({\n name: 'getEntityFields',\n isExported: true,\n parameters: [{ name: 'slug', type: 'string' }],\n returnType: 'Record<string, string> | undefined',\n statements: [returnStatement(elementAccess(identifier('entityFieldsRegistry'), identifier('slug')))],\n })\n const outPath = path.join(generatedRoot, 'entity-fields-registry.ts')\n writeTrackedFile(outPath, getSourceText(sourceFile), result)\n}\n\nexport async function generateEntityIds(options: EntityIdsOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.ids.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.ids.generated.checksum')\n\n const entries = resolver.loadEnabledModules()\n\n const consolidated: Record<string, Record<string, string>> = {}\n const grouped: Record<GroupKey, Record<string, Record<string, string>>> = {}\n const modulesDict: Record<string, string> = {}\n const groupedModulesDict: Record<GroupKey, Record<string, string>> = {}\n\n const fieldsByGroup: Record<GroupKey, Record<string, EntityFieldMap>> = {}\n\n for (const entry of entries) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const group: GroupKey = (entry.from as GroupKey) || '@open-mercato/core'\n\n const standaloneGeneratedPackageEntities = loadStandaloneGeneratedPackageEntities(resolver, entry)\n\n // Locate entities definition file (prefer app override)\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override', 'entities', 'schema']\n let importPath: string | null = null\n let filePath: string | null = null\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = resolveConventionFile(base, f)\n if (p) {\n const fromApp = base.startsWith(roots.appBase)\n const sub = path.basename(base) // 'data' | 'db'\n importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f}`\n filePath = p\n break\n }\n }\n if (importPath) break\n }\n\n // No entities file found -> still register module id\n if (!filePath && !standaloneGeneratedPackageEntities) {\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n\n const exportNames = filePath ? parseExportedClassNamesFromFile(filePath) : []\n\n const entityNames = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityNames\n : exportNames\n .map((k) => toSnake(k))\n .filter((k, idx, arr) => arr.indexOf(k) === idx)\n\n // Build dictionaries\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n\n consolidated[modId] = consolidated[modId] || {}\n grouped[group] = grouped[group] || {}\n grouped[group][modId] = grouped[group][modId] || {}\n\n for (const en of entityNames) {\n consolidated[modId][en] = `${modId}:${en}`\n grouped[group][modId][en] = `${modId}:${en}`\n }\n\n // Parse entity fields from TypeScript source\n const entityFieldMap = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityFieldMap\n : parseEntityFieldsFromFile(filePath!, exportNames)\n fieldsByGroup[group] = fieldsByGroup[group] || {}\n fieldsByGroup[group][modId] = entityFieldMap\n }\n\n // Write consolidated output\n const consolidatedSourceFile = createGeneratedSourceFile('entities.ids.generated.ts')\n addAutoGeneratedComment(consolidatedSourceFile, 'entity-ids')\n consolidatedSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(modulesDict, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(consolidated, null, 2)} as const` },\n ],\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const consolidatedSrc = getSourceText(consolidatedSourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: consolidatedSrc,\n structureChecksum: '',\n result,\n quiet,\n })\n\n // Write per-group outputs\n const groups = Object.keys(grouped) as GroupKey[]\n for (const g of groups) {\n if (!resolver.isMonorepo() && g !== '@app') {\n continue\n }\n\n const pkgOutputDir = resolver.getPackageOutputDir(g)\n // Skip @app group since it writes to the same location as the consolidated output\n if (g === '@app' && pkgOutputDir === outputDir) {\n continue\n }\n const out = path.join(pkgOutputDir, 'entities.ids.generated.ts')\n\n const groupSourceFile = createGeneratedSourceFile(`${String(g)}/entities.ids.generated.ts`)\n addAutoGeneratedComment(groupSourceFile, 'entity-ids')\n groupSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(grouped[g] || {}, null, 2)} as const` },\n ],\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const src = getSourceText(groupSourceFile)\n writeTrackedFile(out, src, result)\n\n const fieldsRoot = path.join(pkgOutputDir, 'entities')\n const fieldsByModule = fieldsByGroup[g] || {}\n const combined: EntityFieldMap = {}\n for (const mId of Object.keys(fieldsByModule)) {\n const mMap = fieldsByModule[mId]\n for (const [entity, fields] of Object.entries(mMap)) {\n combined[entity] = Array.from(new Set([...(combined[entity] || []), ...fields]))\n }\n }\n writePerEntityFieldFiles(fieldsRoot, combined, result)\n\n // Generate static entity fields registry for Turbopack compatibility\n writeEntityFieldsRegistry(pkgOutputDir, combined, result)\n }\n\n // Write combined entity fields to root generated/ folder\n const combinedAll: EntityFieldMap = {}\n for (const groupFields of Object.values(fieldsByGroup)) {\n for (const mMap of Object.values(groupFields)) {\n for (const [entity, fields] of Object.entries(mMap)) {\n combinedAll[entity] = Array.from(new Set([...(combinedAll[entity] || []), ...fields]))\n }\n }\n }\n writePerEntityFieldFiles(path.join(outputDir, 'entities'), combinedAll, result)\n writeEntityFieldsRegistry(outputDir, combinedAll, result)\n\n return result\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript-js'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n toVar,\n toSnake,\n rimrafDir,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n writeIfChanged,\n} from '../utils'\nimport { addAutoGeneratedComment, createGeneratedSourceFile, elementAccess, getSourceText, identifier, returnStatement } from './ast'\n\ntype GroupKey = '@app' | '@open-mercato/core' | string\ntype EntityFieldMap = Record<string, string[]>\n\nexport interface EntityIdsOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\n/**\n * Extract exported class names from a TypeScript source file without dynamic import.\n * This is used for @app modules since Node.js can't import TypeScript files directly.\n */\nfunction parseExportedClassNamesFromFile(filePath: string): string[] {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n const classNames: string[] = []\n\n sf.forEachChild((node) => {\n // Check for exported class declarations\n if (ts.isClassDeclaration(node) && node.name) {\n const hasExport = node.modifiers?.some(\n (m) => m.kind === ts.SyntaxKind.ExportKeyword\n )\n if (hasExport) {\n classNames.push(node.name.text)\n }\n }\n })\n\n return classNames\n}\n\nfunction unwrapObjectLiteralExpression(\n expression: ts.Expression | undefined,\n): ts.ObjectLiteralExpression | undefined {\n if (!expression) return undefined\n if (ts.isObjectLiteralExpression(expression)) return expression\n if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n if (ts.isParenthesizedExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n return undefined\n}\n\nfunction readPropertyInitializer(\n objectLiteral: ts.ObjectLiteralExpression,\n propertyName: string,\n): ts.Expression | undefined {\n for (const property of objectLiteral.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name === propertyName) {\n return property.initializer\n }\n }\n return undefined\n}\n\nfunction parseGeneratedModuleEntityNames(filePath: string, moduleId: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n const declaration = statement.declarationList.declarations.find((candidate) =>\n ts.isIdentifier(candidate.name) && candidate.name.text === 'E')\n if (!declaration) continue\n\n const eObject = unwrapObjectLiteralExpression(declaration.initializer)\n if (!eObject) continue\n\n const moduleObject = unwrapObjectLiteralExpression(readPropertyInitializer(eObject, moduleId))\n if (!moduleObject) return []\n\n const names: string[] = []\n for (const property of moduleObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name) names.push(name)\n }\n return names\n }\n\n return []\n}\n\nfunction parseGeneratedEntityFieldsFile(filePath: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n const fields: string[] = []\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n if (!ts.isStringLiteralLike(declaration.initializer)) continue\n fields.push(declaration.initializer.text)\n }\n }\n\n return Array.from(new Set(fields))\n}\n\nfunction resolveExistingFile(candidates: string[]): string | null {\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nfunction loadStandaloneGeneratedPackageEntities(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): { entityNames: string[]; entityFieldMap: EntityFieldMap } | null {\n if (resolver.isMonorepo() || !entry.from || entry.from === '@app') return null\n\n const packageRoot = resolver.getPackageRoot(entry.from)\n const generatedRoot = fs.existsSync(path.join(packageRoot, 'generated'))\n ? path.join(packageRoot, 'generated')\n : path.join(packageRoot, 'dist', 'generated')\n const idsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities.ids.generated.ts'),\n path.join(generatedRoot, 'entities.ids.generated.js'),\n ])\n if (!idsFile) return null\n const entityNames = parseGeneratedModuleEntityNames(idsFile, entry.id)\n\n if (entityNames.length === 0) return null\n\n const entityFieldMap: EntityFieldMap = {}\n for (const entityName of entityNames) {\n const fieldsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities', entityName, 'index.ts'),\n path.join(generatedRoot, 'entities', entityName, 'index.js'),\n ])\n if (!fieldsFile) continue\n const fields = parseGeneratedEntityFieldsFile(fieldsFile)\n entityFieldMap[entityName] = fields\n }\n\n return { entityNames, entityFieldMap }\n}\n\nfunction parseEntityFieldsFromFile(filePath: string, exportedClassNames: string[]): EntityFieldMap {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n\n const exported = new Set(exportedClassNames)\n const result: EntityFieldMap = {}\n\n function getDecoratorArgNameLiteral(dec: ts.Decorator | undefined): string | undefined {\n if (!dec) return undefined\n const expr = dec.expression\n if (!ts.isCallExpression(expr)) return undefined\n if (!expr.arguments.length) return undefined\n const first = expr.arguments[0]\n if (!ts.isObjectLiteralExpression(first)) return undefined\n for (const prop of first.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'name') {\n if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text\n }\n }\n return undefined\n }\n\n function normalizeDbName(propertyName: string, _decoratorName?: string, nameOverride?: string): string {\n if (nameOverride) return nameOverride\n return toSnake(propertyName)\n }\n\n sf.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n const clsName = node.name.text\n if (!exported.has(clsName)) return\n const entityKey = toSnake(clsName)\n const fields: string[] = []\n\n for (const member of node.members) {\n if (!ts.isPropertyDeclaration(member) || !member.name) continue\n const name = ts.isIdentifier(member.name)\n ? member.name.text\n : ts.isStringLiteral(member.name)\n ? member.name.text\n : undefined\n if (!name) continue\n if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue\n const decorators = ts.canHaveDecorators(member)\n ? ts.getDecorators(member) ?? []\n : []\n let dbName: string | undefined\n if (decorators && decorators.length) {\n for (const d of decorators) {\n const nameOverride = getDecoratorArgNameLiteral(d)\n dbName = normalizeDbName(name, undefined, nameOverride)\n if (dbName) break\n }\n }\n if (!dbName) dbName = normalizeDbName(name)\n fields.push(dbName)\n }\n result[entityKey] = Array.from(new Set(fields))\n })\n\n return result\n}\n\nfunction writeTrackedFile(\n filePath: string,\n content: string,\n result: GeneratorResult,\n): void {\n if (writeIfChanged(filePath, content)) {\n result.filesWritten.push(filePath)\n } else {\n result.filesUnchanged.push(filePath)\n }\n}\n\nfunction writePerEntityFieldFiles(\n outRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n fs.mkdirSync(outRoot, { recursive: true })\n const desiredEntities = new Set(Object.keys(fieldsByEntity))\n for (const [entity, fields] of Object.entries(fieldsByEntity)) {\n const entDir = path.join(outRoot, entity)\n fs.mkdirSync(entDir, { recursive: true })\n const sourceFile = createGeneratedSourceFile(`${entity}/index.ts`)\n sourceFile.addVariableStatements(fields.map((field) => ({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: toVar(field),\n initializer: JSON.stringify(field),\n },\n ],\n })))\n writeTrackedFile(path.join(entDir, 'index.ts'), getSourceText(sourceFile), result)\n }\n\n const existingEntries = fs.existsSync(outRoot) ? fs.readdirSync(outRoot, { withFileTypes: true }) : []\n for (const entry of existingEntries) {\n if (!entry.isDirectory()) continue\n if (desiredEntities.has(entry.name)) continue\n const staleDirectory = path.join(outRoot, entry.name)\n rimrafDir(staleDirectory)\n result.filesWritten.push(staleDirectory)\n }\n}\n\nfunction writeEntityFieldsRegistry(\n generatedRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n const entities = Object.keys(fieldsByEntity).sort((a, b) => a.localeCompare(b))\n const registry: Record<string, Record<string, string>> = {}\n for (const entity of entities) {\n registry[toVar(entity)] = {}\n for (const field of fieldsByEntity[entity] ?? []) {\n registry[toVar(entity)][toVar(field)] = field\n }\n }\n\n const sourceFile = createGeneratedSourceFile('entity-fields-registry.ts')\n addAutoGeneratedComment(sourceFile, 'entity-ids')\n sourceFile.insertText(sourceFile.getFullText().length, '// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility\\n')\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entityFieldsRegistry',\n type: 'Record<string, Record<string, string>>',\n initializer: JSON.stringify(registry, null, 2),\n },\n ],\n })\n sourceFile.addFunction({\n name: 'getEntityFields',\n isExported: true,\n parameters: [{ name: 'slug', type: 'string' }],\n returnType: 'Record<string, string> | undefined',\n statements: [returnStatement(elementAccess(identifier('entityFieldsRegistry'), identifier('slug')))],\n })\n const outPath = path.join(generatedRoot, 'entity-fields-registry.ts')\n writeTrackedFile(outPath, getSourceText(sourceFile), result)\n}\n\nexport async function generateEntityIds(options: EntityIdsOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.ids.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.ids.generated.checksum')\n\n const entries = resolver.loadEnabledModules()\n\n const consolidated: Record<string, Record<string, string>> = {}\n const grouped: Record<GroupKey, Record<string, Record<string, string>>> = {}\n const modulesDict: Record<string, string> = {}\n const groupedModulesDict: Record<GroupKey, Record<string, string>> = {}\n\n const fieldsByGroup: Record<GroupKey, Record<string, EntityFieldMap>> = {}\n\n for (const entry of entries) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const group: GroupKey = (entry.from as GroupKey) || '@open-mercato/core'\n\n const standaloneGeneratedPackageEntities = loadStandaloneGeneratedPackageEntities(resolver, entry)\n\n // Locate entities definition file (prefer app override)\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override', 'entities', 'schema']\n let importPath: string | null = null\n let filePath: string | null = null\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = resolveConventionFile(base, f)\n if (p) {\n const fromApp = base.startsWith(roots.appBase)\n const sub = path.basename(base) // 'data' | 'db'\n importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f}`\n filePath = p\n break\n }\n }\n if (importPath) break\n }\n\n // No entities file found -> still register module id\n if (!filePath && !standaloneGeneratedPackageEntities) {\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n\n const exportNames = filePath ? parseExportedClassNamesFromFile(filePath) : []\n\n const entityNames = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityNames\n : exportNames\n .map((k) => toSnake(k))\n .filter((k, idx, arr) => arr.indexOf(k) === idx)\n\n // Build dictionaries\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n\n consolidated[modId] = consolidated[modId] || {}\n grouped[group] = grouped[group] || {}\n grouped[group][modId] = grouped[group][modId] || {}\n\n for (const en of entityNames) {\n consolidated[modId][en] = `${modId}:${en}`\n grouped[group][modId][en] = `${modId}:${en}`\n }\n\n // Parse entity fields from TypeScript source\n const entityFieldMap = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityFieldMap\n : parseEntityFieldsFromFile(filePath!, exportNames)\n fieldsByGroup[group] = fieldsByGroup[group] || {}\n fieldsByGroup[group][modId] = entityFieldMap\n }\n\n // Write consolidated output\n const consolidatedSourceFile = createGeneratedSourceFile('entities.ids.generated.ts')\n addAutoGeneratedComment(consolidatedSourceFile, 'entity-ids')\n consolidatedSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(modulesDict, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(consolidated, null, 2)} as const` },\n ],\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const consolidatedSrc = getSourceText(consolidatedSourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: consolidatedSrc,\n structureChecksum: '',\n result,\n quiet,\n })\n\n // Write per-group outputs\n const groups = Object.keys(grouped) as GroupKey[]\n for (const g of groups) {\n if (!resolver.isMonorepo() && g !== '@app') {\n continue\n }\n\n const pkgOutputDir = resolver.getPackageOutputDir(g)\n // Skip @app group since it writes to the same location as the consolidated output\n if (g === '@app' && pkgOutputDir === outputDir) {\n continue\n }\n const out = path.join(pkgOutputDir, 'entities.ids.generated.ts')\n\n const groupSourceFile = createGeneratedSourceFile(`${String(g)}/entities.ids.generated.ts`)\n addAutoGeneratedComment(groupSourceFile, 'entity-ids')\n groupSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(grouped[g] || {}, null, 2)} as const` },\n ],\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const src = getSourceText(groupSourceFile)\n writeTrackedFile(out, src, result)\n\n const fieldsRoot = path.join(pkgOutputDir, 'entities')\n const fieldsByModule = fieldsByGroup[g] || {}\n const combined: EntityFieldMap = {}\n for (const mId of Object.keys(fieldsByModule)) {\n const mMap = fieldsByModule[mId]\n for (const [entity, fields] of Object.entries(mMap)) {\n combined[entity] = Array.from(new Set([...(combined[entity] || []), ...fields]))\n }\n }\n writePerEntityFieldFiles(fieldsRoot, combined, result)\n\n // Generate static entity fields registry for Turbopack compatibility\n writeEntityFieldsRegistry(pkgOutputDir, combined, result)\n }\n\n // Write combined entity fields to root generated/ folder\n const combinedAll: EntityFieldMap = {}\n for (const groupFields of Object.values(fieldsByGroup)) {\n for (const mMap of Object.values(groupFields)) {\n for (const [entity, fields] of Object.entries(mMap)) {\n combinedAll[entity] = Array.from(new Set([...(combinedAll[entity] || []), ...fields]))\n }\n }\n }\n writePerEntityFieldFiles(path.join(outputDir, 'entities'), combinedAll, result)\n writeEntityFieldsRegistry(outputDir, combinedAll, result)\n\n return result\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { VariableDeclarationKind } from "ts-morph";
|
|
4
4
|
import { MODULE_CODE_EXTENSIONS } from "./scanner.js";
|
|
5
5
|
import {
|
|
6
6
|
toVar,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "../utils.js";
|
|
10
10
|
import {
|
|
11
11
|
addAutoGeneratedComment,
|
|
12
|
-
|
|
12
|
+
addImportSpecs,
|
|
13
13
|
arrayLiteral,
|
|
14
14
|
createGeneratedSourceFile,
|
|
15
15
|
getSourceText,
|
|
@@ -48,13 +48,10 @@ async function generateModuleDi(options) {
|
|
|
48
48
|
}
|
|
49
49
|
const sourceFile = createGeneratedSourceFile("di.generated.ts");
|
|
50
50
|
addAutoGeneratedComment(sourceFile, "di");
|
|
51
|
-
imports.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
moduleSpecifier: entry.moduleSpecifier
|
|
56
|
-
});
|
|
57
|
-
});
|
|
51
|
+
addImportSpecs(sourceFile, imports.map((entry) => ({
|
|
52
|
+
namespaceImport: entry.name,
|
|
53
|
+
moduleSpecifier: entry.moduleSpecifier
|
|
54
|
+
})));
|
|
58
55
|
sourceFile.addVariableStatement({
|
|
59
56
|
declarationKind: VariableDeclarationKind.Const,
|
|
60
57
|
declarations: [
|