@open-mercato/cli 0.10.1-develop.7827.1.5c631908e4 → 0.10.1-develop.7833.1.d6cbf0e3ab

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 (91) hide show
  1. package/dist/agentic/guides/module-facts.json +162 -162
  2. package/dist/agentic/guides/module-facts.v2.json +162 -162
  3. package/dist/agentic/guides/modules/agent_orchestrator/index.md +1 -1
  4. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  5. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  6. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  7. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  8. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  9. package/dist/agentic/guides/modules/auth/index.md +1 -1
  10. package/dist/agentic/guides/modules/availability/index.md +1 -1
  11. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  12. package/dist/agentic/guides/modules/carrier_inpost/index.md +1 -1
  13. package/dist/agentic/guides/modules/cart/index.md +1 -1
  14. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  15. package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
  16. package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
  17. package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
  18. package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
  19. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  20. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  21. package/dist/agentic/guides/modules/channel_resend/index.md +1 -1
  22. package/dist/agentic/guides/modules/channel_ses/index.md +1 -1
  23. package/dist/agentic/guides/modules/channel_smtp/index.md +1 -1
  24. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  25. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  26. package/dist/agentic/guides/modules/configs/index.md +1 -1
  27. package/dist/agentic/guides/modules/content/index.md +1 -1
  28. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  29. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  30. package/dist/agentic/guides/modules/customer_groups/index.md +1 -1
  31. package/dist/agentic/guides/modules/customers/index.md +1 -1
  32. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  33. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  34. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  35. package/dist/agentic/guides/modules/devices/index.md +1 -1
  36. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  37. package/dist/agentic/guides/modules/directory/index.md +1 -1
  38. package/dist/agentic/guides/modules/documents/index.md +1 -1
  39. package/dist/agentic/guides/modules/ecommerce/index.md +1 -1
  40. package/dist/agentic/guides/modules/entities/index.md +1 -1
  41. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  42. package/dist/agentic/guides/modules/events/index.md +1 -1
  43. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  44. package/dist/agentic/guides/modules/forms/index.md +1 -1
  45. package/dist/agentic/guides/modules/gateway_autopay/index.md +1 -1
  46. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  47. package/dist/agentic/guides/modules/gateway_tpay/index.md +1 -1
  48. package/dist/agentic/guides/modules/generators/index.md +1 -1
  49. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  50. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  51. package/dist/agentic/guides/modules/messages/index.md +1 -1
  52. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  53. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  54. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  55. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  56. package/dist/agentic/guides/modules/phone_calls/index.md +1 -1
  57. package/dist/agentic/guides/modules/planner/index.md +1 -1
  58. package/dist/agentic/guides/modules/portal/index.md +1 -1
  59. package/dist/agentic/guides/modules/progress/index.md +1 -1
  60. package/dist/agentic/guides/modules/promotions/index.md +1 -1
  61. package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
  62. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  63. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  64. package/dist/agentic/guides/modules/resources/index.md +1 -1
  65. package/dist/agentic/guides/modules/sales/index.md +1 -1
  66. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  67. package/dist/agentic/guides/modules/search/index.md +1 -1
  68. package/dist/agentic/guides/modules/security/index.md +1 -1
  69. package/dist/agentic/guides/modules/seeds/index.md +1 -1
  70. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  71. package/dist/agentic/guides/modules/sso/index.md +1 -1
  72. package/dist/agentic/guides/modules/staff/index.md +1 -1
  73. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  74. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  75. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  76. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  77. package/dist/agentic/guides/modules/telemetry/index.md +1 -1
  78. package/dist/agentic/guides/modules/tillio/index.md +1 -1
  79. package/dist/agentic/guides/modules/translations/index.md +1 -1
  80. package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
  81. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  82. package/dist/agentic/guides/modules/wms/index.md +1 -1
  83. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  84. package/dist/agentic/guides/reference-module-facts.json +2 -2
  85. package/dist/agentic/guides/reference-modules/example/index.md +1 -1
  86. package/dist/agentic/guides/upstream/manifest.json +1 -1
  87. package/dist/lib/testing/integration-discovery.js +61 -21
  88. package/dist/lib/testing/integration-discovery.js.map +2 -2
  89. package/package.json +7 -7
  90. package/src/lib/testing/__tests__/integration-discovery.test.ts +89 -0
  91. package/src/lib/testing/integration-discovery.ts +101 -32
@@ -1,5 +1,5 @@
1
1
  # staff — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.10.1-develop.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/storage-s3 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/sync-akeneo 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/enterprise 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/telemetry 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/tillio 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/webhooks 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — 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.7827.1.5c631908e4; core 0.10.1-develop.7827.1.5c631908e4 — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab; core 0.10.1-develop.7833.1.d6cbf0e3ab — R1 staleness stamp -->
3
3
  Source root: node_modules/@open-mercato/core/src/modules/workflows
4
4
 
5
5
  ## Sections
@@ -4,7 +4,7 @@
4
4
  "projectionKind": "activated-reference",
5
5
  "sourceKind": "local-reference",
6
6
  "runtimeSelected": false,
7
- "sourceFingerprint": "7da2b6dd1cbf271bd509629a8092e7e75b4605dba5af3e888f1e980a792af2b1",
7
+ "sourceFingerprint": "2ff6dd2663c08314f41d33170bba9e2f65ed5a24639597aef89d1f649e7637c4",
8
8
  "taxonomyFingerprint": "b6afb1c19fa5325d47cb28db4b5bf6f6e88088a6707d311c322f157230975553",
9
9
  "factCoverage": [
10
10
  {
@@ -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.7827.1.5c631908e4",
1188
+ "coreVersion": "0.10.1-develop.7833.1.d6cbf0e3ab",
1189
1189
  "sourcePackage": null,
1190
1190
  "sourceVersion": null,
1191
1191
  "sourceRoot": "src/modules/example",
@@ -1,5 +1,5 @@
1
1
  # example — module facts (generated reference projection, do not edit)
2
- <!-- generated from local reference src/modules/example; source-fingerprint 7da2b6dd1cbf271bd509629a8092e7e75b4605dba5af3e888f1e980a792af2b1; taxonomy-fingerprint b6afb1c19fa5325d47cb28db4b5bf6f6e88088a6707d311c322f157230975553 — R1 staleness stamp -->
2
+ <!-- generated from local reference src/modules/example; source-fingerprint 2ff6dd2663c08314f41d33170bba9e2f65ed5a24639597aef89d1f649e7637c4; taxonomy-fingerprint b6afb1c19fa5325d47cb28db4b5bf6f6e88088a6707d311c322f157230975553 — R1 staleness stamp -->
3
3
  > Reference projection: `example` is not selected by the current runtime. Its activations and exact override targets describe behavior only after opt-in in `src/modules.ts`.
4
4
  Source root: src/modules/example
5
5
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generator": "@open-mercato/cli@0.10.1-develop.7827.1.5c631908e4",
3
+ "generator": "@open-mercato/cli@0.10.1-develop.7833.1.d6cbf0e3ab",
4
4
  "files": {
5
5
  "AGENTS.md": "b27342ee5f61e805ba52703fdb7ec822b030490f734b4d80f48dfd1e05fa4cf5",
6
6
  "BACKWARD_COMPATIBILITY.md": "d47c2fbbf55f4363511576ac9ad009895afb5f4433c5b1527342e2ea1037b701"
@@ -1,4 +1,4 @@
1
- import { readFileSync, readdirSync } from "node:fs";
1
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import ts from "typescript-js";
4
4
  const MODULE_INTEGRATION_DIRECTORY_NAME = "__integration__";
@@ -85,7 +85,19 @@ function collectModuleIdsFromModulesRoot(modulesRoot, enabledModules) {
85
85
  enabledModules.add(normalizeModuleId(moduleName));
86
86
  }
87
87
  }
88
- function readDeclaredModuleIdsFromConfig(registryPath) {
88
+ function readModuleEntryId(element) {
89
+ if (!ts.isObjectLiteralExpression(element)) return [];
90
+ const idProperty = element.properties.find(
91
+ (property) => ts.isPropertyAssignment(property) && (ts.isIdentifier(property.name) && property.name.text === "id" || ts.isStringLiteralLike(property.name) && property.name.text === "id")
92
+ );
93
+ return idProperty && ts.isStringLiteralLike(idProperty.initializer) ? [idProperty.initializer.text] : [];
94
+ }
95
+ function isPushOntoVariable(node, variableName) {
96
+ return ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "push" && ts.isIdentifier(node.expression.expression) && node.expression.expression.text === variableName;
97
+ }
98
+ function readDeclaredModuleIdsFromConfig(registryPath, options = {}) {
99
+ const variableName = options.variableName ?? "enabledModules";
100
+ if (options.optional && !existsSync(registryPath)) return [];
89
101
  const source = readFileSync(registryPath, "utf8");
90
102
  const sourceFile = ts.createSourceFile(
91
103
  registryPath,
@@ -94,29 +106,39 @@ function readDeclaredModuleIdsFromConfig(registryPath) {
94
106
  true,
95
107
  ts.ScriptKind.TS
96
108
  );
97
- for (const statement of sourceFile.statements) {
98
- if (!ts.isVariableStatement(statement)) continue;
99
- for (const declaration of statement.declarationList.declarations) {
100
- if (!ts.isIdentifier(declaration.name) || declaration.name.text !== "enabledModules" || !declaration.initializer || !ts.isArrayLiteralExpression(declaration.initializer)) {
101
- continue;
102
- }
103
- return declaration.initializer.elements.flatMap((element) => {
104
- if (!ts.isObjectLiteralExpression(element)) return [];
105
- const idProperty = element.properties.find(
106
- (property) => ts.isPropertyAssignment(property) && (ts.isIdentifier(property.name) && property.name.text === "id" || ts.isStringLiteralLike(property.name) && property.name.text === "id")
107
- );
108
- return idProperty && ts.isStringLiteralLike(idProperty.initializer) ? [idProperty.initializer.text] : [];
109
- });
109
+ const declared = [];
110
+ const visit = (node) => {
111
+ if (ts.isVariableDeclaration(node) && ts.isVariableStatement(node.parent.parent) && node.parent.parent.parent === sourceFile && ts.isIdentifier(node.name) && node.name.text === variableName && node.initializer && ts.isArrayLiteralExpression(node.initializer)) {
112
+ declared.push(...node.initializer.elements.flatMap(readModuleEntryId));
110
113
  }
111
- }
112
- return [];
114
+ if (options.includePushes && isPushOntoVariable(node, variableName)) {
115
+ declared.push(...node.arguments.flatMap(readModuleEntryId));
116
+ }
117
+ ts.forEachChild(node, visit);
118
+ };
119
+ visit(sourceFile);
120
+ return declared;
113
121
  }
114
- function resolveEnabledModuleIds(projectRoot) {
122
+ function resolveTestAppRoot() {
115
123
  const configuredTestAppRoot = process.env.OM_TEST_APP_ROOT?.trim();
116
- if (configuredTestAppRoot) {
117
- const registryPath = path.join(path.resolve(configuredTestAppRoot), "src", "modules.ts");
124
+ return configuredTestAppRoot ? path.resolve(configuredTestAppRoot) : null;
125
+ }
126
+ function resolvePossiblyEnabledTestAppModuleIds(testAppRoot) {
127
+ return new Set(
128
+ [
129
+ ...readDeclaredModuleIdsFromConfig(path.join(testAppRoot, "src", "modules.ts"), { includePushes: true }),
130
+ ...readDeclaredModuleIdsFromConfig(
131
+ path.join(testAppRoot, "src", "official-modules.generated.ts"),
132
+ { variableName: "officialModuleEntries", includePushes: true, optional: true }
133
+ )
134
+ ].map(normalizeModuleId)
135
+ );
136
+ }
137
+ function resolveEnabledModuleIds(projectRoot) {
138
+ const testAppRoot = resolveTestAppRoot();
139
+ if (testAppRoot) {
118
140
  return new Set(
119
- readDeclaredModuleIdsFromConfig(registryPath).map(normalizeModuleId)
141
+ readDeclaredModuleIdsFromConfig(path.join(testAppRoot, "src", "modules.ts")).map(normalizeModuleId)
120
142
  );
121
143
  }
122
144
  const enabledModules = /* @__PURE__ */ new Set();
@@ -157,6 +179,16 @@ function extractModuleNameFromIntegrationPath(relativePath) {
157
179
  const moduleSegment = segments[integrationDirectoryIndex - 1];
158
180
  return moduleSegment && moduleSegment.length > 0 ? moduleSegment : null;
159
181
  }
182
+ function resolveOwningModuleId(projectRoot, relativeSpecPath) {
183
+ const segments = normalizePath(relativeSpecPath).split("/");
184
+ const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME);
185
+ if (integrationDirectoryIndex <= 0) return null;
186
+ const modulesSegmentIndex = segments.lastIndexOf("modules", integrationDirectoryIndex - 1);
187
+ if (modulesSegmentIndex === -1 || modulesSegmentIndex + 1 >= integrationDirectoryIndex) return null;
188
+ const moduleRoot = path.join(projectRoot, ...segments.slice(0, modulesSegmentIndex + 2));
189
+ const isRealModule = ["index.ts", "index.js"].some((fileName) => existsSync(path.join(moduleRoot, fileName)));
190
+ return isRealModule ? normalizeModuleId(segments[modulesSegmentIndex + 1]) : null;
191
+ }
160
192
  function resolveOverlayRootPath() {
161
193
  const configured = process.env.OM_INTEGRATION_OVERLAY_ROOT?.trim();
162
194
  if (!configured) {
@@ -350,6 +382,8 @@ function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
350
382
  }
351
383
  const discovered = Array.from(discoveredByPath.values());
352
384
  const enabledModules = resolveEnabledModuleIds(projectRoot);
385
+ const testAppRoot = resolveTestAppRoot();
386
+ const testAppModules = testAppRoot ? resolvePossiblyEnabledTestAppModuleIds(testAppRoot) : null;
353
387
  const enabledModuleNames = /* @__PURE__ */ new Set();
354
388
  for (const file of discovered) {
355
389
  if (!file.isOverlay && file.moduleName) {
@@ -360,6 +394,12 @@ function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
360
394
  if (file.requiredModules.some((moduleId) => !enabledModules.has(normalizeModuleId(moduleId)))) {
361
395
  return false;
362
396
  }
397
+ if (testAppModules && !file.isOverlay) {
398
+ const owningModuleId = resolveOwningModuleId(projectRoot, file.path);
399
+ if (owningModuleId && !testAppModules.has(owningModuleId)) {
400
+ return false;
401
+ }
402
+ }
363
403
  if (file.requiredEnvVars.some((envVar) => !isEnvironmentVariableConfigured(envVar))) {
364
404
  return false;
365
405
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/testing/integration-discovery.ts"],
4
- "sourcesContent": ["import { readFileSync, readdirSync } from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript-js'\n\nexport type IntegrationSpecDiscoveryItem = {\n path: string\n moduleName: string | null\n isOverlay: boolean\n requiredModules: string[]\n requiredEnvVars: string[]\n requiredAnyEnvVars: string[]\n}\n\nconst MODULE_INTEGRATION_DIRECTORY_NAME = '__integration__'\nconst DISCOVERY_IGNORED_DIRS = new Set([\n 'node_modules',\n '.git',\n '.next',\n 'dist',\n '.turbo',\n 'coverage',\n 'test-results',\n '.yarn',\n '.cache',\n 'tmp',\n 'temp',\n '.claude',\n '.codex',\n])\nconst INTEGRATION_META_FILE_NAMES = ['meta.ts', 'index.ts'] as const\nconst INTEGRATION_META_DEPENDENCY_KEYS = ['dependsOnModules', 'requiredModules', 'requiresModules'] as const\nconst INTEGRATION_META_REQUIRED_ENV_KEYS = ['requiredEnvVars', 'requiresEnvVars'] as const\nconst INTEGRATION_META_REQUIRED_ANY_ENV_KEYS = ['requiredAnyEnvVars', 'requiresAnyEnvVars'] as const\nconst DEFAULT_OVERLAY_ROOT = 'packages/enterprise'\n\nexport function normalizePath(filePath: string): string {\n return filePath.split(path.sep).join('/')\n}\n\nfunction normalizeModuleId(moduleId: string): string {\n return moduleId.trim().toLowerCase()\n}\n\nfunction isEnterpriseModulesEnabled(): boolean {\n const rawValue = process.env.OM_ENABLE_ENTERPRISE_MODULES?.trim().toLowerCase()\n return rawValue === 'true' || rawValue === '1' || rawValue === 'yes' || rawValue === 'on'\n}\n\nfunction collectNamedDirectories(rootPath: string, directoryName: string): string[] {\n let entries\n try {\n entries = readdirSync(rootPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n\n const collected: string[] = []\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n if (DISCOVERY_IGNORED_DIRS.has(entry.name)) continue\n const absolutePath = path.join(rootPath, entry.name)\n if (entry.name === directoryName) {\n collected.push(absolutePath)\n }\n collected.push(...collectNamedDirectories(absolutePath, directoryName))\n }\n return collected\n}\n\nfunction collectSpecFilesFromDirectory(directoryPath: string): string[] {\n let entries\n try {\n entries = readdirSync(directoryPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n\n const collected: string[] = []\n for (const entry of entries) {\n const absolutePath = path.join(directoryPath, entry.name)\n if (entry.isDirectory()) {\n collected.push(...collectSpecFilesFromDirectory(absolutePath))\n continue\n }\n if (entry.isFile() && entry.name.endsWith('.spec.ts')) {\n collected.push(absolutePath)\n }\n }\n return collected\n}\n\nfunction collectDirectDirectoryNames(directoryPath: string): string[] {\n let entries\n try {\n entries = readdirSync(directoryPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n return entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))\n .map((entry) => entry.name)\n}\n\nfunction collectModuleIdsFromModulesRoot(modulesRoot: string, enabledModules: Set<string>): void {\n for (const moduleName of collectDirectDirectoryNames(modulesRoot)) {\n enabledModules.add(normalizeModuleId(moduleName))\n }\n}\n\nfunction readDeclaredModuleIdsFromConfig(registryPath: string): string[] {\n const source = readFileSync(registryPath, 'utf8')\n const sourceFile = ts.createSourceFile(\n registryPath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n )\n\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (\n !ts.isIdentifier(declaration.name)\n || declaration.name.text !== 'enabledModules'\n || !declaration.initializer\n || !ts.isArrayLiteralExpression(declaration.initializer)\n ) {\n continue\n }\n\n return declaration.initializer.elements.flatMap((element) => {\n if (!ts.isObjectLiteralExpression(element)) return []\n const idProperty = element.properties.find((property): property is ts.PropertyAssignment =>\n ts.isPropertyAssignment(property)\n && (\n (ts.isIdentifier(property.name) && property.name.text === 'id')\n || (ts.isStringLiteralLike(property.name) && property.name.text === 'id')\n ),\n )\n return idProperty && ts.isStringLiteralLike(idProperty.initializer)\n ? [idProperty.initializer.text]\n : []\n })\n }\n }\n\n return []\n}\n\nfunction resolveEnabledModuleIds(projectRoot: string): Set<string> {\n const configuredTestAppRoot = process.env.OM_TEST_APP_ROOT?.trim()\n if (configuredTestAppRoot) {\n const registryPath = path.join(path.resolve(configuredTestAppRoot), 'src', 'modules.ts')\n return new Set(\n readDeclaredModuleIdsFromConfig(registryPath).map(normalizeModuleId),\n )\n }\n\n const enabledModules = new Set<string>()\n const appModulesRoot = path.join(projectRoot, 'src', 'modules')\n const appsRoot = path.join(projectRoot, 'apps')\n const packagesRoot = path.join(projectRoot, 'packages')\n const installedPackagesRoot = path.join(projectRoot, 'node_modules', '@open-mercato')\n const enterpriseEnabled = isEnterpriseModulesEnabled()\n\n // Standalone app: src/modules at project root\n collectModuleIdsFromModulesRoot(appModulesRoot, enabledModules)\n\n for (const appName of collectDirectDirectoryNames(appsRoot)) {\n const moduleRoot = path.join(appsRoot, appName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n for (const packageName of collectDirectDirectoryNames(packagesRoot)) {\n if (packageName === 'enterprise' && !enterpriseEnabled) {\n continue\n }\n const moduleRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n // Standalone app: installed @open-mercato packages in node_modules\n for (const packageName of collectDirectDirectoryNames(installedPackagesRoot)) {\n if (packageName === 'enterprise' && !enterpriseEnabled) {\n continue\n }\n const moduleRoot = path.join(installedPackagesRoot, packageName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n const createAppTemplateModulesRoot = path.join(projectRoot, 'packages', 'create-app', 'template', 'src', 'modules')\n collectModuleIdsFromModulesRoot(createAppTemplateModulesRoot, enabledModules)\n\n return enabledModules\n}\n\nfunction extractModuleNameFromIntegrationPath(relativePath: string): string | null {\n const segments = normalizePath(relativePath).split('/')\n const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME)\n if (integrationDirectoryIndex <= 0) {\n return null\n }\n const moduleSegment = segments[integrationDirectoryIndex - 1]\n return moduleSegment && moduleSegment.length > 0 ? moduleSegment : null\n}\n\nfunction resolveOverlayRootPath(): string {\n const configured = process.env.OM_INTEGRATION_OVERLAY_ROOT?.trim()\n if (!configured) {\n return DEFAULT_OVERLAY_ROOT\n }\n return configured.replace(/\\/+$/, '')\n}\n\nfunction isOverlayIntegrationPath(relativePath: string, overlayRoot: string): boolean {\n return normalizePath(relativePath).startsWith(`${normalizePath(overlayRoot)}/`)\n}\n\nfunction extractStringArrayFromSource(source: string, keys: readonly string[]): string[] {\n const collected = new Set<string>()\n for (const key of keys) {\n const keyPattern = new RegExp(`${key}\\\\s*:\\\\s*\\\\[([\\\\s\\\\S]*?)\\\\]`, 'm')\n const keyMatch = source.match(keyPattern)\n if (!keyMatch?.[1]) continue\n const valuesPattern = /['\"`]([a-zA-Z0-9_.-]+)['\"`]/g\n for (const valueMatch of keyMatch[1].matchAll(valuesPattern)) {\n const value = String(valueMatch[1] ?? '').trim()\n if (value) {\n collected.add(value)\n }\n }\n }\n return Array.from(collected)\n}\n\nfunction extractDependencyListFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_DEPENDENCY_KEYS).map(normalizeModuleId)\n}\n\nfunction extractRequiredEnvVarsFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ENV_KEYS)\n}\n\nfunction extractRequiredAnyEnvVarsFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ANY_ENV_KEYS)\n}\n\nfunction readDependenciesFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractDependencyListFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction readRequiredEnvVarsFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractRequiredEnvVarsFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction readRequiredAnyEnvVarsFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractRequiredAnyEnvVarsFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction resolveIntegrationRootDirectory(relativeSpecPath: string): string | null {\n const segments = normalizePath(relativeSpecPath).split('/')\n const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME)\n if (integrationDirectoryIndex === -1) {\n return null\n }\n return segments.slice(0, integrationDirectoryIndex + 1).join('/')\n}\n\nfunction resolveRequiredModulesForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredModules = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readDependenciesFromMetadataFile(metadataPath).forEach((dependency) => requiredModules.add(dependency))\n }\n }\n }\n\n readDependenciesFromMetadataFile(absoluteSpecPath).forEach((dependency) => requiredModules.add(dependency))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readDependenciesFromMetadataFile(perTestMetadataPath).forEach((dependency) => requiredModules.add(dependency))\n\n return Array.from(requiredModules)\n}\n\nfunction resolveRequiredEnvVarsForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredEnvVars = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readRequiredEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredEnvVars.add(envVar))\n }\n }\n }\n\n readRequiredEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredEnvVars.add(envVar))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readRequiredEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredEnvVars.add(envVar))\n\n return Array.from(requiredEnvVars)\n}\n\nfunction resolveRequiredAnyEnvVarsForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredAnyEnvVars = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readRequiredAnyEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n }\n }\n }\n\n readRequiredAnyEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readRequiredAnyEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n\n return Array.from(requiredAnyEnvVars)\n}\n\nfunction isEnvironmentVariableConfigured(name: string): boolean {\n const value = process.env[name]\n return typeof value === 'string' && value.trim().length > 0\n}\n\nexport function discoverIntegrationSpecFiles(projectRoot: string, legacyIntegrationRoot: string): IntegrationSpecDiscoveryItem[] {\n const discoveredByPath = new Map<string, IntegrationSpecDiscoveryItem>()\n const overlayRoot = resolveOverlayRootPath()\n const enterpriseEnabled = isEnterpriseModulesEnabled()\n const discoveryRoots = [\n path.join(projectRoot, 'src', 'modules'),\n path.join(projectRoot, 'apps'),\n path.join(projectRoot, 'packages'),\n path.join(projectRoot, 'node_modules', '@open-mercato'),\n ]\n\n for (const specFile of collectSpecFilesFromDirectory(legacyIntegrationRoot)) {\n const relativePath = normalizePath(path.relative(projectRoot, specFile))\n discoveredByPath.set(relativePath, {\n path: relativePath,\n moduleName: extractModuleNameFromIntegrationPath(relativePath),\n isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),\n requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),\n requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),\n requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath),\n })\n }\n\n for (const root of discoveryRoots) {\n for (const integrationDirectory of collectNamedDirectories(root, MODULE_INTEGRATION_DIRECTORY_NAME)) {\n for (const specFile of collectSpecFilesFromDirectory(integrationDirectory)) {\n const relativePath = normalizePath(path.relative(projectRoot, specFile))\n discoveredByPath.set(relativePath, {\n path: relativePath,\n moduleName: extractModuleNameFromIntegrationPath(relativePath),\n isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),\n requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),\n requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),\n requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath),\n })\n }\n }\n }\n\n const discovered = Array.from(discoveredByPath.values())\n const enabledModules = resolveEnabledModuleIds(projectRoot)\n const enabledModuleNames = new Set<string>()\n for (const file of discovered) {\n if (!file.isOverlay && file.moduleName) {\n enabledModuleNames.add(file.moduleName)\n }\n }\n\n return discovered\n .filter((file) => {\n if (file.requiredModules.some((moduleId) => !enabledModules.has(normalizeModuleId(moduleId)))) {\n return false\n }\n if (file.requiredEnvVars.some((envVar) => !isEnvironmentVariableConfigured(envVar))) {\n return false\n }\n if (\n file.requiredAnyEnvVars.length > 0 &&\n !file.requiredAnyEnvVars.some((envVar) => isEnvironmentVariableConfigured(envVar))\n ) {\n return false\n }\n if (!file.isOverlay) {\n return true\n }\n if (!enterpriseEnabled) {\n return false\n }\n if (!file.moduleName) {\n return true\n }\n if (enabledModuleNames.has(file.moduleName)) {\n return true\n }\n return enabledModules.has(normalizeModuleId(file.moduleName))\n })\n .sort((left, right) => left.path.localeCompare(right.path))\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript-js'\n\nexport type IntegrationSpecDiscoveryItem = {\n path: string\n moduleName: string | null\n isOverlay: boolean\n requiredModules: string[]\n requiredEnvVars: string[]\n requiredAnyEnvVars: string[]\n}\n\nconst MODULE_INTEGRATION_DIRECTORY_NAME = '__integration__'\nconst DISCOVERY_IGNORED_DIRS = new Set([\n 'node_modules',\n '.git',\n '.next',\n 'dist',\n '.turbo',\n 'coverage',\n 'test-results',\n '.yarn',\n '.cache',\n 'tmp',\n 'temp',\n '.claude',\n '.codex',\n])\nconst INTEGRATION_META_FILE_NAMES = ['meta.ts', 'index.ts'] as const\nconst INTEGRATION_META_DEPENDENCY_KEYS = ['dependsOnModules', 'requiredModules', 'requiresModules'] as const\nconst INTEGRATION_META_REQUIRED_ENV_KEYS = ['requiredEnvVars', 'requiresEnvVars'] as const\nconst INTEGRATION_META_REQUIRED_ANY_ENV_KEYS = ['requiredAnyEnvVars', 'requiresAnyEnvVars'] as const\nconst DEFAULT_OVERLAY_ROOT = 'packages/enterprise'\n\nexport function normalizePath(filePath: string): string {\n return filePath.split(path.sep).join('/')\n}\n\nfunction normalizeModuleId(moduleId: string): string {\n return moduleId.trim().toLowerCase()\n}\n\nfunction isEnterpriseModulesEnabled(): boolean {\n const rawValue = process.env.OM_ENABLE_ENTERPRISE_MODULES?.trim().toLowerCase()\n return rawValue === 'true' || rawValue === '1' || rawValue === 'yes' || rawValue === 'on'\n}\n\nfunction collectNamedDirectories(rootPath: string, directoryName: string): string[] {\n let entries\n try {\n entries = readdirSync(rootPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n\n const collected: string[] = []\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n if (DISCOVERY_IGNORED_DIRS.has(entry.name)) continue\n const absolutePath = path.join(rootPath, entry.name)\n if (entry.name === directoryName) {\n collected.push(absolutePath)\n }\n collected.push(...collectNamedDirectories(absolutePath, directoryName))\n }\n return collected\n}\n\nfunction collectSpecFilesFromDirectory(directoryPath: string): string[] {\n let entries\n try {\n entries = readdirSync(directoryPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n\n const collected: string[] = []\n for (const entry of entries) {\n const absolutePath = path.join(directoryPath, entry.name)\n if (entry.isDirectory()) {\n collected.push(...collectSpecFilesFromDirectory(absolutePath))\n continue\n }\n if (entry.isFile() && entry.name.endsWith('.spec.ts')) {\n collected.push(absolutePath)\n }\n }\n return collected\n}\n\nfunction collectDirectDirectoryNames(directoryPath: string): string[] {\n let entries\n try {\n entries = readdirSync(directoryPath, { withFileTypes: true, encoding: 'utf8' })\n } catch {\n return []\n }\n return entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))\n .map((entry) => entry.name)\n}\n\nfunction collectModuleIdsFromModulesRoot(modulesRoot: string, enabledModules: Set<string>): void {\n for (const moduleName of collectDirectDirectoryNames(modulesRoot)) {\n enabledModules.add(normalizeModuleId(moduleName))\n }\n}\n\nfunction readModuleEntryId(element: ts.Expression): string[] {\n if (!ts.isObjectLiteralExpression(element)) return []\n const idProperty = element.properties.find((property): property is ts.PropertyAssignment =>\n ts.isPropertyAssignment(property)\n && (\n (ts.isIdentifier(property.name) && property.name.text === 'id')\n || (ts.isStringLiteralLike(property.name) && property.name.text === 'id')\n ),\n )\n return idProperty && ts.isStringLiteralLike(idProperty.initializer)\n ? [idProperty.initializer.text]\n : []\n}\n\nfunction isPushOntoVariable(node: ts.Node, variableName: string): node is ts.CallExpression {\n return ts.isCallExpression(node)\n && ts.isPropertyAccessExpression(node.expression)\n && node.expression.name.text === 'push'\n && ts.isIdentifier(node.expression.expression)\n && node.expression.expression.text === variableName\n}\n\n/**\n * Module ids a registry file declares for `variableName`: the entries of its array\n * literal initializer and, with `includePushes`, every `variableName.push({ id })` call.\n * Pushes are usually conditional (enterprise or env-gated modules), so including them\n * yields an upper bound of what the app can register, never narrower than the runtime set.\n */\nfunction readDeclaredModuleIdsFromConfig(\n registryPath: string,\n options: { variableName?: string; includePushes?: boolean; optional?: boolean } = {},\n): string[] {\n const variableName = options.variableName ?? 'enabledModules'\n if (options.optional && !existsSync(registryPath)) return []\n const source = readFileSync(registryPath, 'utf8')\n const sourceFile = ts.createSourceFile(\n registryPath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n )\n\n const declared: string[] = []\n const visit = (node: ts.Node): void => {\n if (\n ts.isVariableDeclaration(node)\n && ts.isVariableStatement(node.parent.parent)\n && node.parent.parent.parent === sourceFile\n && ts.isIdentifier(node.name)\n && node.name.text === variableName\n && node.initializer\n && ts.isArrayLiteralExpression(node.initializer)\n ) {\n declared.push(...node.initializer.elements.flatMap(readModuleEntryId))\n }\n if (options.includePushes && isPushOntoVariable(node, variableName)) {\n declared.push(...node.arguments.flatMap(readModuleEntryId))\n }\n ts.forEachChild(node, visit)\n }\n visit(sourceFile)\n return declared\n}\n\nfunction resolveTestAppRoot(): string | null {\n const configuredTestAppRoot = process.env.OM_TEST_APP_ROOT?.trim()\n return configuredTestAppRoot ? path.resolve(configuredTestAppRoot) : null\n}\n\n/**\n * Every module a standalone test app may register: its `enabledModules` literal, its\n * conditional `enabledModules.push(...)` entries, and its official-module activations.\n * Used to skip specs whose owning module the app does not ship at all.\n */\nfunction resolvePossiblyEnabledTestAppModuleIds(testAppRoot: string): Set<string> {\n return new Set(\n [\n ...readDeclaredModuleIdsFromConfig(path.join(testAppRoot, 'src', 'modules.ts'), { includePushes: true }),\n ...readDeclaredModuleIdsFromConfig(\n path.join(testAppRoot, 'src', 'official-modules.generated.ts'),\n { variableName: 'officialModuleEntries', includePushes: true, optional: true },\n ),\n ].map(normalizeModuleId),\n )\n}\n\nfunction resolveEnabledModuleIds(projectRoot: string): Set<string> {\n const testAppRoot = resolveTestAppRoot()\n if (testAppRoot) {\n return new Set(\n readDeclaredModuleIdsFromConfig(path.join(testAppRoot, 'src', 'modules.ts')).map(normalizeModuleId),\n )\n }\n\n const enabledModules = new Set<string>()\n const appModulesRoot = path.join(projectRoot, 'src', 'modules')\n const appsRoot = path.join(projectRoot, 'apps')\n const packagesRoot = path.join(projectRoot, 'packages')\n const installedPackagesRoot = path.join(projectRoot, 'node_modules', '@open-mercato')\n const enterpriseEnabled = isEnterpriseModulesEnabled()\n\n // Standalone app: src/modules at project root\n collectModuleIdsFromModulesRoot(appModulesRoot, enabledModules)\n\n for (const appName of collectDirectDirectoryNames(appsRoot)) {\n const moduleRoot = path.join(appsRoot, appName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n for (const packageName of collectDirectDirectoryNames(packagesRoot)) {\n if (packageName === 'enterprise' && !enterpriseEnabled) {\n continue\n }\n const moduleRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n // Standalone app: installed @open-mercato packages in node_modules\n for (const packageName of collectDirectDirectoryNames(installedPackagesRoot)) {\n if (packageName === 'enterprise' && !enterpriseEnabled) {\n continue\n }\n const moduleRoot = path.join(installedPackagesRoot, packageName, 'src', 'modules')\n collectModuleIdsFromModulesRoot(moduleRoot, enabledModules)\n }\n const createAppTemplateModulesRoot = path.join(projectRoot, 'packages', 'create-app', 'template', 'src', 'modules')\n collectModuleIdsFromModulesRoot(createAppTemplateModulesRoot, enabledModules)\n\n return enabledModules\n}\n\nfunction extractModuleNameFromIntegrationPath(relativePath: string): string | null {\n const segments = normalizePath(relativePath).split('/')\n const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME)\n if (integrationDirectoryIndex <= 0) {\n return null\n }\n const moduleSegment = segments[integrationDirectoryIndex - 1]\n return moduleSegment && moduleSegment.length > 0 ? moduleSegment : null\n}\n\n/**\n * The module a spec belongs to: the directory directly under the closest `modules/`\n * ancestor of `__integration__`, provided that directory is a real module (it ships an\n * `index.ts`/`index.js`). Returns null for specs outside a module, e.g. `packages/ui`.\n */\nfunction resolveOwningModuleId(projectRoot: string, relativeSpecPath: string): string | null {\n const segments = normalizePath(relativeSpecPath).split('/')\n const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME)\n if (integrationDirectoryIndex <= 0) return null\n const modulesSegmentIndex = segments.lastIndexOf('modules', integrationDirectoryIndex - 1)\n if (modulesSegmentIndex === -1 || modulesSegmentIndex + 1 >= integrationDirectoryIndex) return null\n const moduleRoot = path.join(projectRoot, ...segments.slice(0, modulesSegmentIndex + 2))\n const isRealModule = ['index.ts', 'index.js'].some((fileName) => existsSync(path.join(moduleRoot, fileName)))\n return isRealModule ? normalizeModuleId(segments[modulesSegmentIndex + 1]) : null\n}\n\nfunction resolveOverlayRootPath(): string {\n const configured = process.env.OM_INTEGRATION_OVERLAY_ROOT?.trim()\n if (!configured) {\n return DEFAULT_OVERLAY_ROOT\n }\n return configured.replace(/\\/+$/, '')\n}\n\nfunction isOverlayIntegrationPath(relativePath: string, overlayRoot: string): boolean {\n return normalizePath(relativePath).startsWith(`${normalizePath(overlayRoot)}/`)\n}\n\nfunction extractStringArrayFromSource(source: string, keys: readonly string[]): string[] {\n const collected = new Set<string>()\n for (const key of keys) {\n const keyPattern = new RegExp(`${key}\\\\s*:\\\\s*\\\\[([\\\\s\\\\S]*?)\\\\]`, 'm')\n const keyMatch = source.match(keyPattern)\n if (!keyMatch?.[1]) continue\n const valuesPattern = /['\"`]([a-zA-Z0-9_.-]+)['\"`]/g\n for (const valueMatch of keyMatch[1].matchAll(valuesPattern)) {\n const value = String(valueMatch[1] ?? '').trim()\n if (value) {\n collected.add(value)\n }\n }\n }\n return Array.from(collected)\n}\n\nfunction extractDependencyListFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_DEPENDENCY_KEYS).map(normalizeModuleId)\n}\n\nfunction extractRequiredEnvVarsFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ENV_KEYS)\n}\n\nfunction extractRequiredAnyEnvVarsFromSource(source: string): string[] {\n return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ANY_ENV_KEYS)\n}\n\nfunction readDependenciesFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractDependencyListFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction readRequiredEnvVarsFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractRequiredEnvVarsFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction readRequiredAnyEnvVarsFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractRequiredAnyEnvVarsFromSource(readFileSync(absolutePath, 'utf8'))\n } catch {\n return []\n }\n}\n\nfunction resolveIntegrationRootDirectory(relativeSpecPath: string): string | null {\n const segments = normalizePath(relativeSpecPath).split('/')\n const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME)\n if (integrationDirectoryIndex === -1) {\n return null\n }\n return segments.slice(0, integrationDirectoryIndex + 1).join('/')\n}\n\nfunction resolveRequiredModulesForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredModules = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readDependenciesFromMetadataFile(metadataPath).forEach((dependency) => requiredModules.add(dependency))\n }\n }\n }\n\n readDependenciesFromMetadataFile(absoluteSpecPath).forEach((dependency) => requiredModules.add(dependency))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readDependenciesFromMetadataFile(perTestMetadataPath).forEach((dependency) => requiredModules.add(dependency))\n\n return Array.from(requiredModules)\n}\n\nfunction resolveRequiredEnvVarsForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredEnvVars = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readRequiredEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredEnvVars.add(envVar))\n }\n }\n }\n\n readRequiredEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredEnvVars.add(envVar))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readRequiredEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredEnvVars.add(envVar))\n\n return Array.from(requiredEnvVars)\n}\n\nfunction resolveRequiredAnyEnvVarsForSpec(projectRoot: string, relativeSpecPath: string): string[] {\n const requiredAnyEnvVars = new Set<string>()\n const normalizedSpecPath = normalizePath(relativeSpecPath)\n const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath)\n const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath)\n\n if (integrationRoot) {\n const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath))\n const integrationRootAbsolute = path.join(projectRoot, integrationRoot)\n const directoryAbsolute = path.join(projectRoot, relativeDirectory)\n const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute))\n const pathSegments = relativeFromIntegrationRoot === '.'\n ? []\n : relativeFromIntegrationRoot.split('/').filter(Boolean)\n\n let currentDirectory = integrationRootAbsolute\n const traversal = [currentDirectory, ...pathSegments.map((segment) => {\n currentDirectory = path.join(currentDirectory, segment)\n return currentDirectory\n })]\n\n for (const directoryPath of traversal) {\n for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {\n const metadataPath = path.join(directoryPath, metadataFileName)\n readRequiredAnyEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n }\n }\n }\n\n readRequiredAnyEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n const specFileName = path.basename(normalizedSpecPath, '.spec.ts')\n const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`)\n readRequiredAnyEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar))\n\n return Array.from(requiredAnyEnvVars)\n}\n\nfunction isEnvironmentVariableConfigured(name: string): boolean {\n const value = process.env[name]\n return typeof value === 'string' && value.trim().length > 0\n}\n\nexport function discoverIntegrationSpecFiles(projectRoot: string, legacyIntegrationRoot: string): IntegrationSpecDiscoveryItem[] {\n const discoveredByPath = new Map<string, IntegrationSpecDiscoveryItem>()\n const overlayRoot = resolveOverlayRootPath()\n const enterpriseEnabled = isEnterpriseModulesEnabled()\n const discoveryRoots = [\n path.join(projectRoot, 'src', 'modules'),\n path.join(projectRoot, 'apps'),\n path.join(projectRoot, 'packages'),\n path.join(projectRoot, 'node_modules', '@open-mercato'),\n ]\n\n for (const specFile of collectSpecFilesFromDirectory(legacyIntegrationRoot)) {\n const relativePath = normalizePath(path.relative(projectRoot, specFile))\n discoveredByPath.set(relativePath, {\n path: relativePath,\n moduleName: extractModuleNameFromIntegrationPath(relativePath),\n isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),\n requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),\n requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),\n requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath),\n })\n }\n\n for (const root of discoveryRoots) {\n for (const integrationDirectory of collectNamedDirectories(root, MODULE_INTEGRATION_DIRECTORY_NAME)) {\n for (const specFile of collectSpecFilesFromDirectory(integrationDirectory)) {\n const relativePath = normalizePath(path.relative(projectRoot, specFile))\n discoveredByPath.set(relativePath, {\n path: relativePath,\n moduleName: extractModuleNameFromIntegrationPath(relativePath),\n isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),\n requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),\n requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),\n requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath),\n })\n }\n }\n }\n\n const discovered = Array.from(discoveredByPath.values())\n const enabledModules = resolveEnabledModuleIds(projectRoot)\n const testAppRoot = resolveTestAppRoot()\n const testAppModules = testAppRoot ? resolvePossiblyEnabledTestAppModuleIds(testAppRoot) : null\n const enabledModuleNames = new Set<string>()\n for (const file of discovered) {\n if (!file.isOverlay && file.moduleName) {\n enabledModuleNames.add(file.moduleName)\n }\n }\n\n return discovered\n .filter((file) => {\n if (file.requiredModules.some((moduleId) => !enabledModules.has(normalizeModuleId(moduleId)))) {\n return false\n }\n if (testAppModules && !file.isOverlay) {\n const owningModuleId = resolveOwningModuleId(projectRoot, file.path)\n if (owningModuleId && !testAppModules.has(owningModuleId)) {\n return false\n }\n }\n if (file.requiredEnvVars.some((envVar) => !isEnvironmentVariableConfigured(envVar))) {\n return false\n }\n if (\n file.requiredAnyEnvVars.length > 0 &&\n !file.requiredAnyEnvVars.some((envVar) => isEnvironmentVariableConfigured(envVar))\n ) {\n return false\n }\n if (!file.isOverlay) {\n return true\n }\n if (!enterpriseEnabled) {\n return false\n }\n if (!file.moduleName) {\n return true\n }\n if (enabledModuleNames.has(file.moduleName)) {\n return true\n }\n return enabledModules.has(normalizeModuleId(file.moduleName))\n })\n .sort((left, right) => left.path.localeCompare(right.path))\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,cAAc,mBAAmB;AACtD,OAAO,UAAU;AACjB,OAAO,QAAQ;AAWf,MAAM,oCAAoC;AAC1C,MAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,MAAM,8BAA8B,CAAC,WAAW,UAAU;AAC1D,MAAM,mCAAmC,CAAC,oBAAoB,mBAAmB,iBAAiB;AAClG,MAAM,qCAAqC,CAAC,mBAAmB,iBAAiB;AAChF,MAAM,yCAAyC,CAAC,sBAAsB,oBAAoB;AAC1F,MAAM,uBAAuB;AAEtB,SAAS,cAAc,UAA0B;AACtD,SAAO,SAAS,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AAC1C;AAEA,SAAS,kBAAkB,UAA0B;AACnD,SAAO,SAAS,KAAK,EAAE,YAAY;AACrC;AAEA,SAAS,6BAAsC;AAC7C,QAAM,WAAW,QAAQ,IAAI,8BAA8B,KAAK,EAAE,YAAY;AAC9E,SAAO,aAAa,UAAU,aAAa,OAAO,aAAa,SAAS,aAAa;AACvF;AAEA,SAAS,wBAAwB,UAAkB,eAAiC;AAClF,MAAI;AACJ,MAAI;AACF,cAAU,YAAY,UAAU,EAAE,eAAe,MAAM,UAAU,OAAO,CAAC;AAAA,EAC3E,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAsB,CAAC;AAC7B,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,QAAI,uBAAuB,IAAI,MAAM,IAAI,EAAG;AAC5C,UAAM,eAAe,KAAK,KAAK,UAAU,MAAM,IAAI;AACnD,QAAI,MAAM,SAAS,eAAe;AAChC,gBAAU,KAAK,YAAY;AAAA,IAC7B;AACA,cAAU,KAAK,GAAG,wBAAwB,cAAc,aAAa,CAAC;AAAA,EACxE;AACA,SAAO;AACT;AAEA,SAAS,8BAA8B,eAAiC;AACtE,MAAI;AACJ,MAAI;AACF,cAAU,YAAY,eAAe,EAAE,eAAe,MAAM,UAAU,OAAO,CAAC;AAAA,EAChF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAsB,CAAC;AAC7B,aAAW,SAAS,SAAS;AAC3B,UAAM,eAAe,KAAK,KAAK,eAAe,MAAM,IAAI;AACxD,QAAI,MAAM,YAAY,GAAG;AACvB,gBAAU,KAAK,GAAG,8BAA8B,YAAY,CAAC;AAC7D;AAAA,IACF;AACA,QAAI,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,UAAU,GAAG;AACrD,gBAAU,KAAK,YAAY;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,eAAiC;AACpE,MAAI;AACJ,MAAI;AACF,cAAU,YAAY,eAAe,EAAE,eAAe,MAAM,UAAU,OAAO,CAAC;AAAA,EAChF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,SAAO,QACJ,OAAO,CAAC,UAAU,MAAM,YAAY,KAAK,CAAC,MAAM,KAAK,WAAW,GAAG,CAAC,EACpE,IAAI,CAAC,UAAU,MAAM,IAAI;AAC9B;AAEA,SAAS,gCAAgC,aAAqB,gBAAmC;AAC/F,aAAW,cAAc,4BAA4B,WAAW,GAAG;AACjE,mBAAe,IAAI,kBAAkB,UAAU,CAAC;AAAA,EAClD;AACF;AAEA,SAAS,kBAAkB,SAAkC;AAC3D,MAAI,CAAC,GAAG,0BAA0B,OAAO,EAAG,QAAO,CAAC;AACpD,QAAM,aAAa,QAAQ,WAAW;AAAA,IAAK,CAAC,aAC1C,GAAG,qBAAqB,QAAQ,MAE7B,GAAG,aAAa,SAAS,IAAI,KAAK,SAAS,KAAK,SAAS,QACtD,GAAG,oBAAoB,SAAS,IAAI,KAAK,SAAS,KAAK,SAAS;AAAA,EAExE;AACA,SAAO,cAAc,GAAG,oBAAoB,WAAW,WAAW,IAC9D,CAAC,WAAW,YAAY,IAAI,IAC5B,CAAC;AACP;AAEA,SAAS,mBAAmB,MAAe,cAAiD;AAC1F,SAAO,GAAG,iBAAiB,IAAI,KAC1B,GAAG,2BAA2B,KAAK,UAAU,KAC7C,KAAK,WAAW,KAAK,SAAS,UAC9B,GAAG,aAAa,KAAK,WAAW,UAAU,KAC1C,KAAK,WAAW,WAAW,SAAS;AAC3C;AAQA,SAAS,gCACP,cACA,UAAkF,CAAC,GACzE;AACV,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,MAAI,QAAQ,YAAY,CAAC,WAAW,YAAY,EAAG,QAAO,CAAC;AAC3D,QAAM,SAAS,aAAa,cAAc,MAAM;AAChD,QAAM,aAAa,GAAG;AAAA,IACpB;AAAA,IACA;AAAA,IACA,GAAG,aAAa;AAAA,IAChB;AAAA,IACA,GAAG,WAAW;AAAA,EAChB;AAEA,QAAM,WAAqB,CAAC;AAC5B,QAAM,QAAQ,CAAC,SAAwB;AACrC,QACE,GAAG,sBAAsB,IAAI,KAC1B,GAAG,oBAAoB,KAAK,OAAO,MAAM,KACzC,KAAK,OAAO,OAAO,WAAW,cAC9B,GAAG,aAAa,KAAK,IAAI,KACzB,KAAK,KAAK,SAAS,gBACnB,KAAK,eACL,GAAG,yBAAyB,KAAK,WAAW,GAC/C;AACA,eAAS,KAAK,GAAG,KAAK,YAAY,SAAS,QAAQ,iBAAiB,CAAC;AAAA,IACvE;AACA,QAAI,QAAQ,iBAAiB,mBAAmB,MAAM,YAAY,GAAG;AACnE,eAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,iBAAiB,CAAC;AAAA,IAC5D;AACA,OAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,QAAM,UAAU;AAChB,SAAO;AACT;AAEA,SAAS,qBAAoC;AAC3C,QAAM,wBAAwB,QAAQ,IAAI,kBAAkB,KAAK;AACjE,SAAO,wBAAwB,KAAK,QAAQ,qBAAqB,IAAI;AACvE;AAOA,SAAS,uCAAuC,aAAkC;AAChF,SAAO,IAAI;AAAA,IACT;AAAA,MACE,GAAG,gCAAgC,KAAK,KAAK,aAAa,OAAO,YAAY,GAAG,EAAE,eAAe,KAAK,CAAC;AAAA,MACvG,GAAG;AAAA,QACD,KAAK,KAAK,aAAa,OAAO,+BAA+B;AAAA,QAC7D,EAAE,cAAc,yBAAyB,eAAe,MAAM,UAAU,KAAK;AAAA,MAC/E;AAAA,IACF,EAAE,IAAI,iBAAiB;AAAA,EACzB;AACF;AAEA,SAAS,wBAAwB,aAAkC;AACjE,QAAM,cAAc,mBAAmB;AACvC,MAAI,aAAa;AACf,WAAO,IAAI;AAAA,MACT,gCAAgC,KAAK,KAAK,aAAa,OAAO,YAAY,CAAC,EAAE,IAAI,iBAAiB;AAAA,IACpG;AAAA,EACF;AAEA,QAAM,iBAAiB,oBAAI,IAAY;AACvC,QAAM,iBAAiB,KAAK,KAAK,aAAa,OAAO,SAAS;AAC9D,QAAM,WAAW,KAAK,KAAK,aAAa,MAAM;AAC9C,QAAM,eAAe,KAAK,KAAK,aAAa,UAAU;AACtD,QAAM,wBAAwB,KAAK,KAAK,aAAa,gBAAgB,eAAe;AACpF,QAAM,oBAAoB,2BAA2B;AAGrD,kCAAgC,gBAAgB,cAAc;AAE9D,aAAW,WAAW,4BAA4B,QAAQ,GAAG;AAC3D,UAAM,aAAa,KAAK,KAAK,UAAU,SAAS,OAAO,SAAS;AAChE,oCAAgC,YAAY,cAAc;AAAA,EAC5D;AACA,aAAW,eAAe,4BAA4B,YAAY,GAAG;AACnE,QAAI,gBAAgB,gBAAgB,CAAC,mBAAmB;AACtD;AAAA,IACF;AACA,UAAM,aAAa,KAAK,KAAK,cAAc,aAAa,OAAO,SAAS;AACxE,oCAAgC,YAAY,cAAc;AAAA,EAC5D;AAEA,aAAW,eAAe,4BAA4B,qBAAqB,GAAG;AAC5E,QAAI,gBAAgB,gBAAgB,CAAC,mBAAmB;AACtD;AAAA,IACF;AACA,UAAM,aAAa,KAAK,KAAK,uBAAuB,aAAa,OAAO,SAAS;AACjF,oCAAgC,YAAY,cAAc;AAAA,EAC5D;AACA,QAAM,+BAA+B,KAAK,KAAK,aAAa,YAAY,cAAc,YAAY,OAAO,SAAS;AAClH,kCAAgC,8BAA8B,cAAc;AAE5E,SAAO;AACT;AAEA,SAAS,qCAAqC,cAAqC;AACjF,QAAM,WAAW,cAAc,YAAY,EAAE,MAAM,GAAG;AACtD,QAAM,4BAA4B,SAAS,QAAQ,iCAAiC;AACpF,MAAI,6BAA6B,GAAG;AAClC,WAAO;AAAA,EACT;AACA,QAAM,gBAAgB,SAAS,4BAA4B,CAAC;AAC5D,SAAO,iBAAiB,cAAc,SAAS,IAAI,gBAAgB;AACrE;AAOA,SAAS,sBAAsB,aAAqB,kBAAyC;AAC3F,QAAM,WAAW,cAAc,gBAAgB,EAAE,MAAM,GAAG;AAC1D,QAAM,4BAA4B,SAAS,QAAQ,iCAAiC;AACpF,MAAI,6BAA6B,EAAG,QAAO;AAC3C,QAAM,sBAAsB,SAAS,YAAY,WAAW,4BAA4B,CAAC;AACzF,MAAI,wBAAwB,MAAM,sBAAsB,KAAK,0BAA2B,QAAO;AAC/F,QAAM,aAAa,KAAK,KAAK,aAAa,GAAG,SAAS,MAAM,GAAG,sBAAsB,CAAC,CAAC;AACvF,QAAM,eAAe,CAAC,YAAY,UAAU,EAAE,KAAK,CAAC,aAAa,WAAW,KAAK,KAAK,YAAY,QAAQ,CAAC,CAAC;AAC5G,SAAO,eAAe,kBAAkB,SAAS,sBAAsB,CAAC,CAAC,IAAI;AAC/E;AAEA,SAAS,yBAAiC;AACxC,QAAM,aAAa,QAAQ,IAAI,6BAA6B,KAAK;AACjE,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AACA,SAAO,WAAW,QAAQ,QAAQ,EAAE;AACtC;AAEA,SAAS,yBAAyB,cAAsB,aAA8B;AACpF,SAAO,cAAc,YAAY,EAAE,WAAW,GAAG,cAAc,WAAW,CAAC,GAAG;AAChF;AAEA,SAAS,6BAA6B,QAAgB,MAAmC;AACvF,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,OAAO,MAAM;AACtB,UAAM,aAAa,IAAI,OAAO,GAAG,GAAG,+BAA+B,GAAG;AACtE,UAAM,WAAW,OAAO,MAAM,UAAU;AACxC,QAAI,CAAC,WAAW,CAAC,EAAG;AACpB,UAAM,gBAAgB;AACtB,eAAW,cAAc,SAAS,CAAC,EAAE,SAAS,aAAa,GAAG;AAC5D,YAAM,QAAQ,OAAO,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK;AAC/C,UAAI,OAAO;AACT,kBAAU,IAAI,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,KAAK,SAAS;AAC7B;AAEA,SAAS,gCAAgC,QAA0B;AACjE,SAAO,6BAA6B,QAAQ,gCAAgC,EAAE,IAAI,iBAAiB;AACrG;AAEA,SAAS,iCAAiC,QAA0B;AAClE,SAAO,6BAA6B,QAAQ,kCAAkC;AAChF;AAEA,SAAS,oCAAoC,QAA0B;AACrE,SAAO,6BAA6B,QAAQ,sCAAsC;AACpF;AAEA,SAAS,iCAAiC,cAAgC;AACxE,MAAI;AACF,WAAO,gCAAgC,aAAa,cAAc,MAAM,CAAC;AAAA,EAC3E,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,oCAAoC,cAAgC;AAC3E,MAAI;AACF,WAAO,iCAAiC,aAAa,cAAc,MAAM,CAAC;AAAA,EAC5E,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,uCAAuC,cAAgC;AAC9E,MAAI;AACF,WAAO,oCAAoC,aAAa,cAAc,MAAM,CAAC;AAAA,EAC/E,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,gCAAgC,kBAAyC;AAChF,QAAM,WAAW,cAAc,gBAAgB,EAAE,MAAM,GAAG;AAC1D,QAAM,4BAA4B,SAAS,QAAQ,iCAAiC;AACpF,MAAI,8BAA8B,IAAI;AACpC,WAAO;AAAA,EACT;AACA,SAAO,SAAS,MAAM,GAAG,4BAA4B,CAAC,EAAE,KAAK,GAAG;AAClE;AAEA,SAAS,8BAA8B,aAAqB,kBAAoC;AAC9F,QAAM,kBAAkB,oBAAI,IAAY;AACxC,QAAM,qBAAqB,cAAc,gBAAgB;AACzD,QAAM,mBAAmB,KAAK,KAAK,aAAa,kBAAkB;AAClE,QAAM,kBAAkB,gCAAgC,kBAAkB;AAE1E,MAAI,iBAAiB;AACnB,UAAM,oBAAoB,cAAc,KAAK,QAAQ,kBAAkB,CAAC;AACxE,UAAM,0BAA0B,KAAK,KAAK,aAAa,eAAe;AACtE,UAAM,oBAAoB,KAAK,KAAK,aAAa,iBAAiB;AAClE,UAAM,8BAA8B,cAAc,KAAK,SAAS,yBAAyB,iBAAiB,CAAC;AAC3G,UAAM,eAAe,gCAAgC,MACjD,CAAC,IACD,4BAA4B,MAAM,GAAG,EAAE,OAAO,OAAO;AAEzD,QAAI,mBAAmB;AACvB,UAAM,YAAY,CAAC,kBAAkB,GAAG,aAAa,IAAI,CAAC,YAAY;AACpE,yBAAmB,KAAK,KAAK,kBAAkB,OAAO;AACtD,aAAO;AAAA,IACT,CAAC,CAAC;AAEF,eAAW,iBAAiB,WAAW;AACrC,iBAAW,oBAAoB,6BAA6B;AAC1D,cAAM,eAAe,KAAK,KAAK,eAAe,gBAAgB;AAC9D,yCAAiC,YAAY,EAAE,QAAQ,CAAC,eAAe,gBAAgB,IAAI,UAAU,CAAC;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AAEA,mCAAiC,gBAAgB,EAAE,QAAQ,CAAC,eAAe,gBAAgB,IAAI,UAAU,CAAC;AAC1G,QAAM,eAAe,KAAK,SAAS,oBAAoB,UAAU;AACjE,QAAM,sBAAsB,KAAK,KAAK,KAAK,QAAQ,gBAAgB,GAAG,GAAG,YAAY,UAAU;AAC/F,mCAAiC,mBAAmB,EAAE,QAAQ,CAAC,eAAe,gBAAgB,IAAI,UAAU,CAAC;AAE7G,SAAO,MAAM,KAAK,eAAe;AACnC;AAEA,SAAS,8BAA8B,aAAqB,kBAAoC;AAC9F,QAAM,kBAAkB,oBAAI,IAAY;AACxC,QAAM,qBAAqB,cAAc,gBAAgB;AACzD,QAAM,mBAAmB,KAAK,KAAK,aAAa,kBAAkB;AAClE,QAAM,kBAAkB,gCAAgC,kBAAkB;AAE1E,MAAI,iBAAiB;AACnB,UAAM,oBAAoB,cAAc,KAAK,QAAQ,kBAAkB,CAAC;AACxE,UAAM,0BAA0B,KAAK,KAAK,aAAa,eAAe;AACtE,UAAM,oBAAoB,KAAK,KAAK,aAAa,iBAAiB;AAClE,UAAM,8BAA8B,cAAc,KAAK,SAAS,yBAAyB,iBAAiB,CAAC;AAC3G,UAAM,eAAe,gCAAgC,MACjD,CAAC,IACD,4BAA4B,MAAM,GAAG,EAAE,OAAO,OAAO;AAEzD,QAAI,mBAAmB;AACvB,UAAM,YAAY,CAAC,kBAAkB,GAAG,aAAa,IAAI,CAAC,YAAY;AACpE,yBAAmB,KAAK,KAAK,kBAAkB,OAAO;AACtD,aAAO;AAAA,IACT,CAAC,CAAC;AAEF,eAAW,iBAAiB,WAAW;AACrC,iBAAW,oBAAoB,6BAA6B;AAC1D,cAAM,eAAe,KAAK,KAAK,eAAe,gBAAgB;AAC9D,4CAAoC,YAAY,EAAE,QAAQ,CAAC,WAAW,gBAAgB,IAAI,MAAM,CAAC;AAAA,MACnG;AAAA,IACF;AAAA,EACF;AAEA,sCAAoC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,gBAAgB,IAAI,MAAM,CAAC;AACrG,QAAM,eAAe,KAAK,SAAS,oBAAoB,UAAU;AACjE,QAAM,sBAAsB,KAAK,KAAK,KAAK,QAAQ,gBAAgB,GAAG,GAAG,YAAY,UAAU;AAC/F,sCAAoC,mBAAmB,EAAE,QAAQ,CAAC,WAAW,gBAAgB,IAAI,MAAM,CAAC;AAExG,SAAO,MAAM,KAAK,eAAe;AACnC;AAEA,SAAS,iCAAiC,aAAqB,kBAAoC;AACjG,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,qBAAqB,cAAc,gBAAgB;AACzD,QAAM,mBAAmB,KAAK,KAAK,aAAa,kBAAkB;AAClE,QAAM,kBAAkB,gCAAgC,kBAAkB;AAE1E,MAAI,iBAAiB;AACnB,UAAM,oBAAoB,cAAc,KAAK,QAAQ,kBAAkB,CAAC;AACxE,UAAM,0BAA0B,KAAK,KAAK,aAAa,eAAe;AACtE,UAAM,oBAAoB,KAAK,KAAK,aAAa,iBAAiB;AAClE,UAAM,8BAA8B,cAAc,KAAK,SAAS,yBAAyB,iBAAiB,CAAC;AAC3G,UAAM,eAAe,gCAAgC,MACjD,CAAC,IACD,4BAA4B,MAAM,GAAG,EAAE,OAAO,OAAO;AAEzD,QAAI,mBAAmB;AACvB,UAAM,YAAY,CAAC,kBAAkB,GAAG,aAAa,IAAI,CAAC,YAAY;AACpE,yBAAmB,KAAK,KAAK,kBAAkB,OAAO;AACtD,aAAO;AAAA,IACT,CAAC,CAAC;AAEF,eAAW,iBAAiB,WAAW;AACrC,iBAAW,oBAAoB,6BAA6B;AAC1D,cAAM,eAAe,KAAK,KAAK,eAAe,gBAAgB;AAC9D,+CAAuC,YAAY,EAAE,QAAQ,CAAC,WAAW,mBAAmB,IAAI,MAAM,CAAC;AAAA,MACzG;AAAA,IACF;AAAA,EACF;AAEA,yCAAuC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,mBAAmB,IAAI,MAAM,CAAC;AAC3G,QAAM,eAAe,KAAK,SAAS,oBAAoB,UAAU;AACjE,QAAM,sBAAsB,KAAK,KAAK,KAAK,QAAQ,gBAAgB,GAAG,GAAG,YAAY,UAAU;AAC/F,yCAAuC,mBAAmB,EAAE,QAAQ,CAAC,WAAW,mBAAmB,IAAI,MAAM,CAAC;AAE9G,SAAO,MAAM,KAAK,kBAAkB;AACtC;AAEA,SAAS,gCAAgC,MAAuB;AAC9D,QAAM,QAAQ,QAAQ,IAAI,IAAI;AAC9B,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAEO,SAAS,6BAA6B,aAAqB,uBAA+D;AAC/H,QAAM,mBAAmB,oBAAI,IAA0C;AACvE,QAAM,cAAc,uBAAuB;AAC3C,QAAM,oBAAoB,2BAA2B;AACrD,QAAM,iBAAiB;AAAA,IACrB,KAAK,KAAK,aAAa,OAAO,SAAS;AAAA,IACvC,KAAK,KAAK,aAAa,MAAM;AAAA,IAC7B,KAAK,KAAK,aAAa,UAAU;AAAA,IACjC,KAAK,KAAK,aAAa,gBAAgB,eAAe;AAAA,EACxD;AAEA,aAAW,YAAY,8BAA8B,qBAAqB,GAAG;AAC3E,UAAM,eAAe,cAAc,KAAK,SAAS,aAAa,QAAQ,CAAC;AACvE,qBAAiB,IAAI,cAAc;AAAA,MACjC,MAAM;AAAA,MACN,YAAY,qCAAqC,YAAY;AAAA,MAC7D,WAAW,yBAAyB,cAAc,WAAW;AAAA,MAC7D,iBAAiB,8BAA8B,aAAa,YAAY;AAAA,MACxE,iBAAiB,8BAA8B,aAAa,YAAY;AAAA,MACxE,oBAAoB,iCAAiC,aAAa,YAAY;AAAA,IAChF,CAAC;AAAA,EACH;AAEA,aAAW,QAAQ,gBAAgB;AACjC,eAAW,wBAAwB,wBAAwB,MAAM,iCAAiC,GAAG;AACnG,iBAAW,YAAY,8BAA8B,oBAAoB,GAAG;AAC1E,cAAM,eAAe,cAAc,KAAK,SAAS,aAAa,QAAQ,CAAC;AACvE,yBAAiB,IAAI,cAAc;AAAA,UACjC,MAAM;AAAA,UACN,YAAY,qCAAqC,YAAY;AAAA,UAC7D,WAAW,yBAAyB,cAAc,WAAW;AAAA,UAC7D,iBAAiB,8BAA8B,aAAa,YAAY;AAAA,UACxE,iBAAiB,8BAA8B,aAAa,YAAY;AAAA,UACxE,oBAAoB,iCAAiC,aAAa,YAAY;AAAA,QAChF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,KAAK,iBAAiB,OAAO,CAAC;AACvD,QAAM,iBAAiB,wBAAwB,WAAW;AAC1D,QAAM,cAAc,mBAAmB;AACvC,QAAM,iBAAiB,cAAc,uCAAuC,WAAW,IAAI;AAC3F,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,aAAW,QAAQ,YAAY;AAC7B,QAAI,CAAC,KAAK,aAAa,KAAK,YAAY;AACtC,yBAAmB,IAAI,KAAK,UAAU;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,WACJ,OAAO,CAAC,SAAS;AAChB,QAAI,KAAK,gBAAgB,KAAK,CAAC,aAAa,CAAC,eAAe,IAAI,kBAAkB,QAAQ,CAAC,CAAC,GAAG;AAC7F,aAAO;AAAA,IACT;AACA,QAAI,kBAAkB,CAAC,KAAK,WAAW;AACrC,YAAM,iBAAiB,sBAAsB,aAAa,KAAK,IAAI;AACnE,UAAI,kBAAkB,CAAC,eAAe,IAAI,cAAc,GAAG;AACzD,eAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,KAAK,gBAAgB,KAAK,CAAC,WAAW,CAAC,gCAAgC,MAAM,CAAC,GAAG;AACnF,aAAO;AAAA,IACT;AACA,QACE,KAAK,mBAAmB,SAAS,KACjC,CAAC,KAAK,mBAAmB,KAAK,CAAC,WAAW,gCAAgC,MAAM,CAAC,GACjF;AACA,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,mBAAmB;AACtB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAK,YAAY;AACpB,aAAO;AAAA,IACT;AACA,QAAI,mBAAmB,IAAI,KAAK,UAAU,GAAG;AAC3C,aAAO;AAAA,IACT;AACA,WAAO,eAAe,IAAI,kBAAkB,KAAK,UAAU,CAAC;AAAA,EAC9D,CAAC,EACA,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;AAC9D;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.10.1-develop.7827.1.5c631908e4",
3
+ "version": "0.10.1-develop.7833.1.d6cbf0e3ab",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "@mikro-orm/decorators": "^7.1.14",
61
61
  "@mikro-orm/migrations": "^7.1.14",
62
62
  "@mikro-orm/postgresql": "^7.1.14",
63
- "@open-mercato/events": "0.10.1-develop.7827.1.5c631908e4",
64
- "@open-mercato/queue": "0.10.1-develop.7827.1.5c631908e4",
65
- "@open-mercato/shared": "0.10.1-develop.7827.1.5c631908e4",
66
- "@open-mercato/telemetry": "0.10.1-develop.7827.1.5c631908e4",
63
+ "@open-mercato/events": "0.10.1-develop.7833.1.d6cbf0e3ab",
64
+ "@open-mercato/queue": "0.10.1-develop.7833.1.d6cbf0e3ab",
65
+ "@open-mercato/shared": "0.10.1-develop.7833.1.d6cbf0e3ab",
66
+ "@open-mercato/telemetry": "0.10.1-develop.7833.1.d6cbf0e3ab",
67
67
  "cross-spawn": "^7.0.6",
68
68
  "minisearch": "7.2.0",
69
69
  "pg": "8.23.0",
@@ -75,10 +75,10 @@
75
75
  "typescript-js": "npm:typescript@6.0.3"
76
76
  },
77
77
  "peerDependencies": {
78
- "@open-mercato/shared": "0.10.1-develop.7827.1.5c631908e4"
78
+ "@open-mercato/shared": "0.10.1-develop.7833.1.d6cbf0e3ab"
79
79
  },
80
80
  "devDependencies": {
81
- "@open-mercato/shared": "0.10.1-develop.7827.1.5c631908e4",
81
+ "@open-mercato/shared": "0.10.1-develop.7833.1.d6cbf0e3ab",
82
82
  "@types/jest": "^30.0.0",
83
83
  "jest": "^30.4.2",
84
84
  "ts-jest": "^29.4.12"
@@ -194,6 +194,95 @@ describe('integration discovery', () => {
194
194
  ])
195
195
  })
196
196
 
197
+ it('skips standalone specs whose owning module the OM_TEST_APP_ROOT app does not ship', async () => {
198
+ for (const moduleId of ['catalog', 'ecommerce', 'record_locks_probe', 'official_probe']) {
199
+ await writeTestFile(tempRoot, `packages/core/src/modules/${moduleId}/index.ts`)
200
+ await writeTestFile(tempRoot, `packages/core/src/modules/${moduleId}/__integration__/TC-${moduleId}.spec.ts`)
201
+ }
202
+ await writeTestFile(tempRoot, 'packages/core/src/modules/catalog/__integration__/nested/TC-catalog-nested.spec.ts')
203
+ await writeTestFile(tempRoot, 'packages/core/src/modules/core/__integration__/TC-core-shell.spec.ts')
204
+ await writeTestFile(tempRoot, 'packages/ui/__integration__/TC-ui.spec.ts')
205
+ await writeTestFile(
206
+ tempRoot,
207
+ 'standalone-app/src/modules.ts',
208
+ [
209
+ "export const enabledModules = [",
210
+ " { id: 'catalog', from: '@open-mercato/core' },",
211
+ " // { id: 'ecommerce', from: '@open-mercato/core' },",
212
+ ']',
213
+ "if (process.env.FLAG) enabledModules.push({ id: 'record_locks_probe', from: '@open-mercato/core' })",
214
+ '',
215
+ ].join('\n'),
216
+ )
217
+ await writeTestFile(
218
+ tempRoot,
219
+ 'standalone-app/src/official-modules.generated.ts',
220
+ "export const officialModuleEntries = [{ id: 'official_probe', from: '@open-mercato/official' }]\n",
221
+ )
222
+
223
+ let discovered = discoverIntegrationSpecFiles(tempRoot, path.join(tempRoot, '.ai', 'qa', 'tests'))
224
+ expect(discovered.map((entry) => entry.path)).toContain(
225
+ 'packages/core/src/modules/ecommerce/__integration__/TC-ecommerce.spec.ts',
226
+ )
227
+
228
+ process.env.OM_TEST_APP_ROOT = path.join(tempRoot, 'standalone-app')
229
+ discovered = discoverIntegrationSpecFiles(tempRoot, path.join(tempRoot, '.ai', 'qa', 'tests'))
230
+ expect(discovered.map((entry) => entry.path)).toEqual([
231
+ 'packages/core/src/modules/catalog/__integration__/nested/TC-catalog-nested.spec.ts',
232
+ 'packages/core/src/modules/catalog/__integration__/TC-catalog.spec.ts',
233
+ 'packages/core/src/modules/core/__integration__/TC-core-shell.spec.ts',
234
+ 'packages/core/src/modules/official_probe/__integration__/TC-official_probe.spec.ts',
235
+ 'packages/core/src/modules/record_locks_probe/__integration__/TC-record_locks_probe.spec.ts',
236
+ 'packages/ui/__integration__/TC-ui.spec.ts',
237
+ ])
238
+ })
239
+
240
+ it('keeps conditional enabledModules pushes out of standalone dependency filtering', async () => {
241
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/index.ts')
242
+ await writeTestFile(
243
+ tempRoot,
244
+ 'packages/core/src/modules/sales/__integration__/TC-SALES-030.meta.ts',
245
+ "export const integrationMeta = { dependsOnModules: ['gated_probe'] }\n",
246
+ )
247
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/__integration__/TC-SALES-030.spec.ts')
248
+ await writeTestFile(
249
+ tempRoot,
250
+ 'standalone-app/src/modules.ts',
251
+ "export const enabledModules = [{ id: 'sales', from: '@open-mercato/core' }]\nif (process.env.FLAG) enabledModules.push({ id: 'gated_probe', from: '@app' })\n",
252
+ )
253
+ process.env.OM_TEST_APP_ROOT = path.join(tempRoot, 'standalone-app')
254
+
255
+ const discovered = discoverIntegrationSpecFiles(tempRoot, path.join(tempRoot, '.ai', 'qa', 'tests'))
256
+ expect(discovered.map((entry) => entry.path)).toEqual([])
257
+ })
258
+
259
+ it('fails loudly when OM_TEST_APP_ROOT has no modules.ts instead of skipping every spec', async () => {
260
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/index.ts')
261
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/__integration__/TC-SALES-040.spec.ts')
262
+ process.env.OM_TEST_APP_ROOT = path.join(tempRoot, 'missing-standalone-app')
263
+
264
+ expect(() => discoverIntegrationSpecFiles(tempRoot, path.join(tempRoot, '.ai', 'qa', 'tests'))).toThrow(/modules\.ts/)
265
+ })
266
+
267
+ it('reads only the top-level enabledModules declaration of a standalone app', async () => {
268
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/index.ts')
269
+ await writeTestFile(
270
+ tempRoot,
271
+ 'packages/core/src/modules/sales/__integration__/TC-SALES-041.meta.ts',
272
+ "export const integrationMeta = { dependsOnModules: ['nested_probe'] }\n",
273
+ )
274
+ await writeTestFile(tempRoot, 'packages/core/src/modules/sales/__integration__/TC-SALES-041.spec.ts')
275
+ await writeTestFile(
276
+ tempRoot,
277
+ 'standalone-app/src/modules.ts',
278
+ "export const enabledModules = [{ id: 'sales', from: '@open-mercato/core' }]\nfunction preview() {\n const enabledModules = [{ id: 'nested_probe', from: '@app' }]\n return enabledModules\n}\n",
279
+ )
280
+ process.env.OM_TEST_APP_ROOT = path.join(tempRoot, 'standalone-app')
281
+
282
+ const discovered = discoverIntegrationSpecFiles(tempRoot, path.join(tempRoot, '.ai', 'qa', 'tests'))
283
+ expect(discovered.map((entry) => entry.path)).toEqual([])
284
+ })
285
+
197
286
  it('applies folder and per-test metadata environment requirements', async () => {
198
287
  await writeTestFile(tempRoot, 'packages/ai-assistant/src/modules/ai_assistant/.gitkeep')
199
288
  await writeTestFile(