@open-mercato/cli 0.5.1-develop.3036.f02c281f23 → 0.5.1-develop.3045.b4b3320cc2
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/shared/AGENTS.md.template +1 -1
- package/dist/lib/__integration__/TC-INT-007.spec.js +201 -0
- package/dist/lib/__integration__/TC-INT-007.spec.js.map +7 -0
- package/dist/lib/dev-env-reload.js +89 -0
- package/dist/lib/dev-env-reload.js.map +7 -0
- package/dist/lib/generators/extensions/ai-agents.js +218 -0
- package/dist/lib/generators/extensions/ai-agents.js.map +7 -0
- package/dist/lib/generators/extensions/ai-tools.js +56 -1
- package/dist/lib/generators/extensions/ai-tools.js.map +2 -2
- package/dist/lib/generators/extensions/index.js +2 -0
- package/dist/lib/generators/extensions/index.js.map +2 -2
- package/dist/lib/testing/integration-discovery.js +102 -5
- package/dist/lib/testing/integration-discovery.js.map +2 -2
- package/dist/mercato.js +85 -44
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +112 -0
- package/src/lib/__integration__/TC-INT-007.spec.ts +228 -0
- package/src/lib/__tests__/dev-env-reload.test.ts +62 -0
- package/src/lib/dev-env-reload.ts +110 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +14 -0
- package/src/lib/generators/__tests__/output-snapshots.test.ts +17 -0
- package/src/lib/generators/__tests__/scanner.test.ts +1 -1
- package/src/lib/generators/__tests__/structural-contracts.test.ts +26 -0
- package/src/lib/generators/extensions/ai-agents.ts +240 -0
- package/src/lib/generators/extensions/ai-tools.ts +72 -1
- package/src/lib/generators/extensions/index.ts +2 -0
- package/src/lib/testing/__tests__/integration-discovery.test.ts +68 -0
- package/src/lib/testing/integration-discovery.ts +127 -3
- package/src/mercato.ts +100 -46
|
@@ -5,11 +5,14 @@ import {
|
|
|
5
5
|
binaryExpression,
|
|
6
6
|
identifier,
|
|
7
7
|
methodCall,
|
|
8
|
+
objectLiteral,
|
|
9
|
+
parenthesized,
|
|
8
10
|
propertyAccess,
|
|
9
11
|
writeValue
|
|
10
12
|
} from "../ast/index.js";
|
|
11
13
|
import {
|
|
12
14
|
emptyArray,
|
|
15
|
+
emptyObject,
|
|
13
16
|
moduleEntry,
|
|
14
17
|
namespaceFallback,
|
|
15
18
|
renderGeneratedTsSource
|
|
@@ -39,6 +42,15 @@ function createAiToolsExtension() {
|
|
|
39
42
|
fallback: emptyArray(),
|
|
40
43
|
castType: "unknown[]"
|
|
41
44
|
})
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "overrides",
|
|
48
|
+
value: namespaceFallback({
|
|
49
|
+
importName,
|
|
50
|
+
members: ["aiToolOverrides"],
|
|
51
|
+
fallback: emptyObject(),
|
|
52
|
+
castType: "Record<string, unknown>"
|
|
53
|
+
})
|
|
42
54
|
}
|
|
43
55
|
])
|
|
44
56
|
});
|
|
@@ -50,7 +62,11 @@ function createAiToolsExtension() {
|
|
|
50
62
|
build(sourceFile) {
|
|
51
63
|
sourceFile.addTypeAlias({
|
|
52
64
|
name: "AiToolConfigEntry",
|
|
53
|
-
type: "{ moduleId: string; tools: unknown[] }"
|
|
65
|
+
type: "{ moduleId: string; tools: unknown[]; overrides: Record<string, unknown> }"
|
|
66
|
+
});
|
|
67
|
+
sourceFile.addTypeAlias({
|
|
68
|
+
name: "AiToolOverrideConfigEntry",
|
|
69
|
+
type: "{ moduleId: string; overrides: Record<string, unknown> }"
|
|
54
70
|
});
|
|
55
71
|
sourceFile.addVariableStatement({
|
|
56
72
|
declarationKind: VariableDeclarationKind.Const,
|
|
@@ -93,6 +109,45 @@ function createAiToolsExtension() {
|
|
|
93
109
|
}
|
|
94
110
|
]
|
|
95
111
|
});
|
|
112
|
+
sourceFile.addVariableStatement({
|
|
113
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
114
|
+
isExported: true,
|
|
115
|
+
declarations: [
|
|
116
|
+
{
|
|
117
|
+
name: "aiToolOverrideEntries",
|
|
118
|
+
type: "AiToolOverrideConfigEntry[]",
|
|
119
|
+
initializer: methodCall(
|
|
120
|
+
methodCall(identifier("aiToolConfigEntriesRaw"), "filter", [
|
|
121
|
+
arrowFunction({
|
|
122
|
+
parameters: ["entry"],
|
|
123
|
+
body: binaryExpression(
|
|
124
|
+
propertyAccess(
|
|
125
|
+
methodCall(identifier("Object"), "keys", [
|
|
126
|
+
propertyAccess(identifier("entry"), "overrides")
|
|
127
|
+
]),
|
|
128
|
+
"length"
|
|
129
|
+
),
|
|
130
|
+
">",
|
|
131
|
+
0
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
]),
|
|
135
|
+
"map",
|
|
136
|
+
[
|
|
137
|
+
arrowFunction({
|
|
138
|
+
parameters: ["entry"],
|
|
139
|
+
body: parenthesized(
|
|
140
|
+
objectLiteral([
|
|
141
|
+
{ name: "moduleId", value: propertyAccess(identifier("entry"), "moduleId") },
|
|
142
|
+
{ name: "overrides", value: propertyAccess(identifier("entry"), "overrides") }
|
|
143
|
+
])
|
|
144
|
+
)
|
|
145
|
+
})
|
|
146
|
+
]
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
});
|
|
96
151
|
}
|
|
97
152
|
});
|
|
98
153
|
return /* @__PURE__ */ new Map([["ai-tools.generated.ts", output]]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/generators/extensions/ai-tools.ts"],
|
|
4
|
-
"sourcesContent": ["import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'\nimport type { GeneratorExtension } from '../extension'\nimport {\n arrayLiteral,\n arrowFunction,\n binaryExpression,\n identifier,\n methodCall,\n propertyAccess,\n writeValue,\n} from '../ast'\nimport {\n emptyArray,\n moduleEntry,\n namespaceFallback,\n namespaceImportSpec,\n renderGeneratedTsSource,\n} from './shared'\n\nexport function createAiToolsExtension(): GeneratorExtension {\n const imports = [] as Array<ReturnType<typeof namespaceImportSpec>>\n const entries: WriterFunction[] = []\n\n return {\n id: 'registry.ai-tools',\n outputFiles: ['ai-tools.generated.ts'],\n scanModule(ctx) {\n ctx.processStandaloneConfig({\n roots: ctx.roots,\n imps: ctx.imps,\n modId: ctx.moduleId,\n relativePath: 'ai-tools.ts',\n prefix: 'AI_TOOLS',\n importIdRef: ctx.importIdRef,\n standaloneImports: imports,\n standaloneEntries: entries,\n writeConfig: ({ importName, moduleId }) =>\n moduleEntry(moduleId, [\n {\n name: 'tools',\n value: namespaceFallback({\n importName,\n members: ['aiTools', 'default'],\n fallback: emptyArray(),\n castType: 'unknown[]',\n }),\n },\n ]),\n })\n },\n generateOutput() {\n const output = renderGeneratedTsSource({\n fileName: 'ai-tools.generated.ts',\n imports,\n build(sourceFile) {\n sourceFile.addTypeAlias({\n name: 'AiToolConfigEntry',\n type: '{ moduleId: string; tools: unknown[] }',\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'aiToolConfigEntriesRaw',\n type: 'AiToolConfigEntry[]',\n initializer: arrayLiteral(entries, writeValue),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiToolConfigEntries',\n type: 'AiToolConfigEntry[]',\n initializer: methodCall(identifier('aiToolConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(propertyAccess(propertyAccess(identifier('entry'), 'tools'), 'length'), '>', 0),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'allAiTools',\n initializer: methodCall(identifier('aiToolConfigEntries'), 'flatMap', [\n arrowFunction({\n parameters: ['entry'],\n body: propertyAccess(identifier('entry'), 'tools'),\n }),\n ]),\n },\n ],\n })\n },\n })\n\n return new Map([['ai-tools.generated.ts', output]])\n },\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,+BAAoD;AAE7D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;
|
|
4
|
+
"sourcesContent": ["import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'\nimport type { GeneratorExtension } from '../extension'\nimport {\n arrayLiteral,\n arrowFunction,\n binaryExpression,\n identifier,\n methodCall,\n objectLiteral,\n parenthesized,\n propertyAccess,\n writeValue,\n} from '../ast'\nimport {\n emptyArray,\n emptyObject,\n moduleEntry,\n namespaceFallback,\n namespaceImportSpec,\n renderGeneratedTsSource,\n} from './shared'\n\n/**\n * Generator extension for `<module>/ai-tools.ts` files.\n *\n * Each module's `ai-tools.ts` may export both base tool contributions\n * (`aiTools`) AND cross-module override declarations (`aiToolOverrides`).\n * The generator scans the file once and emits two filtered exports\n * inside `ai-tools.generated.ts`:\n *\n * - `aiToolConfigEntries` (entries that declare base tools)\n * - `aiToolOverrideEntries` (entries that declare overrides)\n *\n * The runtime (`@open-mercato/ai-assistant`) reads `aiToolConfigEntries`\n * to populate the tool registry and `aiToolOverrideEntries` to apply\n * cross-module replacements after the base load. See spec\n * `.ai/specs/2026-04-30-ai-overrides-and-module-disable.md`.\n */\nexport function createAiToolsExtension(): GeneratorExtension {\n const imports = [] as Array<ReturnType<typeof namespaceImportSpec>>\n const entries: WriterFunction[] = []\n\n return {\n id: 'registry.ai-tools',\n outputFiles: ['ai-tools.generated.ts'],\n scanModule(ctx) {\n ctx.processStandaloneConfig({\n roots: ctx.roots,\n imps: ctx.imps,\n modId: ctx.moduleId,\n relativePath: 'ai-tools.ts',\n prefix: 'AI_TOOLS',\n importIdRef: ctx.importIdRef,\n standaloneImports: imports,\n standaloneEntries: entries,\n writeConfig: ({ importName, moduleId }) =>\n moduleEntry(moduleId, [\n {\n name: 'tools',\n value: namespaceFallback({\n importName,\n members: ['aiTools', 'default'],\n fallback: emptyArray(),\n castType: 'unknown[]',\n }),\n },\n {\n name: 'overrides',\n value: namespaceFallback({\n importName,\n members: ['aiToolOverrides'],\n fallback: emptyObject(),\n castType: 'Record<string, unknown>',\n }),\n },\n ]),\n })\n },\n generateOutput() {\n const output = renderGeneratedTsSource({\n fileName: 'ai-tools.generated.ts',\n imports,\n build(sourceFile) {\n sourceFile.addTypeAlias({\n name: 'AiToolConfigEntry',\n type: '{ moduleId: string; tools: unknown[]; overrides: Record<string, unknown> }',\n })\n sourceFile.addTypeAlias({\n name: 'AiToolOverrideConfigEntry',\n type: '{ moduleId: string; overrides: Record<string, unknown> }',\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'aiToolConfigEntriesRaw',\n type: 'AiToolConfigEntry[]',\n initializer: arrayLiteral(entries, writeValue),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiToolConfigEntries',\n type: 'AiToolConfigEntry[]',\n initializer: methodCall(identifier('aiToolConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(propertyAccess(propertyAccess(identifier('entry'), 'tools'), 'length'), '>', 0),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'allAiTools',\n initializer: methodCall(identifier('aiToolConfigEntries'), 'flatMap', [\n arrowFunction({\n parameters: ['entry'],\n body: propertyAccess(identifier('entry'), 'tools'),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiToolOverrideEntries',\n type: 'AiToolOverrideConfigEntry[]',\n initializer: methodCall(\n methodCall(identifier('aiToolConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(\n propertyAccess(\n methodCall(identifier('Object'), 'keys', [\n propertyAccess(identifier('entry'), 'overrides'),\n ]),\n 'length',\n ),\n '>',\n 0,\n ),\n }),\n ]),\n 'map',\n [\n arrowFunction({\n parameters: ['entry'],\n body: parenthesized(\n objectLiteral([\n { name: 'moduleId', value: propertyAccess(identifier('entry'), 'moduleId') },\n { name: 'overrides', value: propertyAccess(identifier('entry'), 'overrides') },\n ]),\n ),\n }),\n ],\n ),\n },\n ],\n })\n },\n })\n\n return new Map([['ai-tools.generated.ts', output]])\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAiAgentsExtension } from "./ai-agents.js";
|
|
1
2
|
import { createAiToolsExtension } from "./ai-tools.js";
|
|
2
3
|
import { createAnalyticsExtension } from "./analytics.js";
|
|
3
4
|
import { createCommandInterceptorsExtension } from "./command-interceptors.js";
|
|
@@ -20,6 +21,7 @@ function loadGeneratorExtensions() {
|
|
|
20
21
|
createNotificationsExtension(),
|
|
21
22
|
createMessagesExtension(),
|
|
22
23
|
createAiToolsExtension(),
|
|
24
|
+
createAiAgentsExtension(),
|
|
23
25
|
createEventsExtension(),
|
|
24
26
|
createAnalyticsExtension(),
|
|
25
27
|
createTranslatableFieldsExtension(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/generators/extensions/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { GeneratorExtension } from '../extension'\nimport { createAiToolsExtension } from './ai-tools'\nimport { createAnalyticsExtension } from './analytics'\nimport { createCommandInterceptorsExtension } from './command-interceptors'\nimport { createComponentOverridesExtension } from './component-overrides'\nimport { createDashboardWidgetsExtension } from './dashboard-widgets'\nimport { createEnrichersExtension } from './enrichers'\nimport { createEventsExtension } from './events'\nimport { createGuardsExtension } from './guards'\nimport { createInboxActionsExtension } from './inbox-actions'\nimport { createInjectionWidgetsExtension } from './injection-widgets'\nimport { createInterceptorsExtension } from './interceptors'\nimport { createMessagesExtension } from './messages'\nimport { createNotificationsExtension } from './notifications'\nimport { createPageMiddlewareExtension } from './page-middleware'\nimport { createSearchExtension } from './search'\nimport { createTranslatableFieldsExtension } from './translatable-fields'\n\nexport function loadGeneratorExtensions(): GeneratorExtension[] {\n return [\n createSearchExtension(),\n createNotificationsExtension(),\n createMessagesExtension(),\n createAiToolsExtension(),\n createEventsExtension(),\n createAnalyticsExtension(),\n createTranslatableFieldsExtension(),\n createEnrichersExtension(),\n createInterceptorsExtension(),\n createComponentOverridesExtension(),\n createInboxActionsExtension(),\n createGuardsExtension(),\n createCommandInterceptorsExtension(),\n createPageMiddlewareExtension(),\n createDashboardWidgetsExtension(),\n createInjectionWidgetsExtension(),\n ]\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,8BAA8B;AACvC,SAAS,gCAAgC;AACzC,SAAS,0CAA0C;AACnD,SAAS,yCAAyC;AAClD,SAAS,uCAAuC;AAChD,SAAS,gCAAgC;AACzC,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;AACtC,SAAS,mCAAmC;AAC5C,SAAS,uCAAuC;AAChD,SAAS,mCAAmC;AAC5C,SAAS,+BAA+B;AACxC,SAAS,oCAAoC;AAC7C,SAAS,qCAAqC;AAC9C,SAAS,6BAA6B;AACtC,SAAS,yCAAyC;AAE3C,SAAS,0BAAgD;AAC9D,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,6BAA6B;AAAA,IAC7B,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,kCAAkC;AAAA,IAClC,yBAAyB;AAAA,IACzB,4BAA4B;AAAA,IAC5B,kCAAkC;AAAA,IAClC,4BAA4B;AAAA,IAC5B,sBAAsB;AAAA,IACtB,mCAAmC;AAAA,IACnC,8BAA8B;AAAA,IAC9B,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,EAClC;AACF;",
|
|
4
|
+
"sourcesContent": ["import type { GeneratorExtension } from '../extension'\nimport { createAiAgentsExtension } from './ai-agents'\nimport { createAiToolsExtension } from './ai-tools'\nimport { createAnalyticsExtension } from './analytics'\nimport { createCommandInterceptorsExtension } from './command-interceptors'\nimport { createComponentOverridesExtension } from './component-overrides'\nimport { createDashboardWidgetsExtension } from './dashboard-widgets'\nimport { createEnrichersExtension } from './enrichers'\nimport { createEventsExtension } from './events'\nimport { createGuardsExtension } from './guards'\nimport { createInboxActionsExtension } from './inbox-actions'\nimport { createInjectionWidgetsExtension } from './injection-widgets'\nimport { createInterceptorsExtension } from './interceptors'\nimport { createMessagesExtension } from './messages'\nimport { createNotificationsExtension } from './notifications'\nimport { createPageMiddlewareExtension } from './page-middleware'\nimport { createSearchExtension } from './search'\nimport { createTranslatableFieldsExtension } from './translatable-fields'\n\nexport function loadGeneratorExtensions(): GeneratorExtension[] {\n return [\n createSearchExtension(),\n createNotificationsExtension(),\n createMessagesExtension(),\n createAiToolsExtension(),\n createAiAgentsExtension(),\n createEventsExtension(),\n createAnalyticsExtension(),\n createTranslatableFieldsExtension(),\n createEnrichersExtension(),\n createInterceptorsExtension(),\n createComponentOverridesExtension(),\n createInboxActionsExtension(),\n createGuardsExtension(),\n createCommandInterceptorsExtension(),\n createPageMiddlewareExtension(),\n createDashboardWidgetsExtension(),\n createInjectionWidgetsExtension(),\n ]\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,gCAAgC;AACzC,SAAS,0CAA0C;AACnD,SAAS,yCAAyC;AAClD,SAAS,uCAAuC;AAChD,SAAS,gCAAgC;AACzC,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;AACtC,SAAS,mCAAmC;AAC5C,SAAS,uCAAuC;AAChD,SAAS,mCAAmC;AAC5C,SAAS,+BAA+B;AACxC,SAAS,oCAAoC;AAC7C,SAAS,qCAAqC;AAC9C,SAAS,6BAA6B;AACtC,SAAS,yCAAyC;AAE3C,SAAS,0BAAgD;AAC9D,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,6BAA6B;AAAA,IAC7B,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,kCAAkC;AAAA,IAClC,yBAAyB;AAAA,IACzB,4BAA4B;AAAA,IAC5B,kCAAkC;AAAA,IAClC,4BAA4B;AAAA,IAC5B,sBAAsB;AAAA,IACtB,mCAAmC;AAAA,IACnC,8BAA8B;AAAA,IAC9B,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,EAClC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -18,6 +18,8 @@ const DISCOVERY_IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
|
18
18
|
]);
|
|
19
19
|
const INTEGRATION_META_FILE_NAMES = ["meta.ts", "index.ts"];
|
|
20
20
|
const INTEGRATION_META_DEPENDENCY_KEYS = ["dependsOnModules", "requiredModules", "requiresModules"];
|
|
21
|
+
const INTEGRATION_META_REQUIRED_ENV_KEYS = ["requiredEnvVars", "requiresEnvVars"];
|
|
22
|
+
const INTEGRATION_META_REQUIRED_ANY_ENV_KEYS = ["requiredAnyEnvVars", "requiresAnyEnvVars"];
|
|
21
23
|
const DEFAULT_OVERLAY_ROOT = "packages/enterprise";
|
|
22
24
|
function normalizePath(filePath) {
|
|
23
25
|
return filePath.split(path.sep).join("/");
|
|
@@ -131,15 +133,15 @@ function resolveOverlayRootPath() {
|
|
|
131
133
|
function isOverlayIntegrationPath(relativePath, overlayRoot) {
|
|
132
134
|
return normalizePath(relativePath).startsWith(`${normalizePath(overlayRoot)}/`);
|
|
133
135
|
}
|
|
134
|
-
function
|
|
136
|
+
function extractStringArrayFromSource(source, keys) {
|
|
135
137
|
const collected = /* @__PURE__ */ new Set();
|
|
136
|
-
for (const key of
|
|
138
|
+
for (const key of keys) {
|
|
137
139
|
const keyPattern = new RegExp(`${key}\\s*:\\s*\\[([\\s\\S]*?)\\]`, "m");
|
|
138
140
|
const keyMatch = source.match(keyPattern);
|
|
139
141
|
if (!keyMatch?.[1]) continue;
|
|
140
142
|
const valuesPattern = /['"`]([a-zA-Z0-9_.-]+)['"`]/g;
|
|
141
143
|
for (const valueMatch of keyMatch[1].matchAll(valuesPattern)) {
|
|
142
|
-
const value =
|
|
144
|
+
const value = String(valueMatch[1] ?? "").trim();
|
|
143
145
|
if (value) {
|
|
144
146
|
collected.add(value);
|
|
145
147
|
}
|
|
@@ -147,6 +149,15 @@ function extractDependencyListFromSource(source) {
|
|
|
147
149
|
}
|
|
148
150
|
return Array.from(collected);
|
|
149
151
|
}
|
|
152
|
+
function extractDependencyListFromSource(source) {
|
|
153
|
+
return extractStringArrayFromSource(source, INTEGRATION_META_DEPENDENCY_KEYS).map(normalizeModuleId);
|
|
154
|
+
}
|
|
155
|
+
function extractRequiredEnvVarsFromSource(source) {
|
|
156
|
+
return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ENV_KEYS);
|
|
157
|
+
}
|
|
158
|
+
function extractRequiredAnyEnvVarsFromSource(source) {
|
|
159
|
+
return extractStringArrayFromSource(source, INTEGRATION_META_REQUIRED_ANY_ENV_KEYS);
|
|
160
|
+
}
|
|
150
161
|
function readDependenciesFromMetadataFile(absolutePath) {
|
|
151
162
|
try {
|
|
152
163
|
return extractDependencyListFromSource(readFileSync(absolutePath, "utf8"));
|
|
@@ -154,6 +165,20 @@ function readDependenciesFromMetadataFile(absolutePath) {
|
|
|
154
165
|
return [];
|
|
155
166
|
}
|
|
156
167
|
}
|
|
168
|
+
function readRequiredEnvVarsFromMetadataFile(absolutePath) {
|
|
169
|
+
try {
|
|
170
|
+
return extractRequiredEnvVarsFromSource(readFileSync(absolutePath, "utf8"));
|
|
171
|
+
} catch {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function readRequiredAnyEnvVarsFromMetadataFile(absolutePath) {
|
|
176
|
+
try {
|
|
177
|
+
return extractRequiredAnyEnvVarsFromSource(readFileSync(absolutePath, "utf8"));
|
|
178
|
+
} catch {
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
157
182
|
function resolveIntegrationRootDirectory(relativeSpecPath) {
|
|
158
183
|
const segments = normalizePath(relativeSpecPath).split("/");
|
|
159
184
|
const integrationDirectoryIndex = segments.indexOf(MODULE_INTEGRATION_DIRECTORY_NAME);
|
|
@@ -191,6 +216,68 @@ function resolveRequiredModulesForSpec(projectRoot, relativeSpecPath) {
|
|
|
191
216
|
readDependenciesFromMetadataFile(perTestMetadataPath).forEach((dependency) => requiredModules.add(dependency));
|
|
192
217
|
return Array.from(requiredModules);
|
|
193
218
|
}
|
|
219
|
+
function resolveRequiredEnvVarsForSpec(projectRoot, relativeSpecPath) {
|
|
220
|
+
const requiredEnvVars = /* @__PURE__ */ new Set();
|
|
221
|
+
const normalizedSpecPath = normalizePath(relativeSpecPath);
|
|
222
|
+
const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath);
|
|
223
|
+
const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath);
|
|
224
|
+
if (integrationRoot) {
|
|
225
|
+
const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath));
|
|
226
|
+
const integrationRootAbsolute = path.join(projectRoot, integrationRoot);
|
|
227
|
+
const directoryAbsolute = path.join(projectRoot, relativeDirectory);
|
|
228
|
+
const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute));
|
|
229
|
+
const pathSegments = relativeFromIntegrationRoot === "." ? [] : relativeFromIntegrationRoot.split("/").filter(Boolean);
|
|
230
|
+
let currentDirectory = integrationRootAbsolute;
|
|
231
|
+
const traversal = [currentDirectory, ...pathSegments.map((segment) => {
|
|
232
|
+
currentDirectory = path.join(currentDirectory, segment);
|
|
233
|
+
return currentDirectory;
|
|
234
|
+
})];
|
|
235
|
+
for (const directoryPath of traversal) {
|
|
236
|
+
for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {
|
|
237
|
+
const metadataPath = path.join(directoryPath, metadataFileName);
|
|
238
|
+
readRequiredEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredEnvVars.add(envVar));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
readRequiredEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredEnvVars.add(envVar));
|
|
243
|
+
const specFileName = path.basename(normalizedSpecPath, ".spec.ts");
|
|
244
|
+
const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`);
|
|
245
|
+
readRequiredEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredEnvVars.add(envVar));
|
|
246
|
+
return Array.from(requiredEnvVars);
|
|
247
|
+
}
|
|
248
|
+
function resolveRequiredAnyEnvVarsForSpec(projectRoot, relativeSpecPath) {
|
|
249
|
+
const requiredAnyEnvVars = /* @__PURE__ */ new Set();
|
|
250
|
+
const normalizedSpecPath = normalizePath(relativeSpecPath);
|
|
251
|
+
const absoluteSpecPath = path.join(projectRoot, normalizedSpecPath);
|
|
252
|
+
const integrationRoot = resolveIntegrationRootDirectory(normalizedSpecPath);
|
|
253
|
+
if (integrationRoot) {
|
|
254
|
+
const relativeDirectory = normalizePath(path.dirname(normalizedSpecPath));
|
|
255
|
+
const integrationRootAbsolute = path.join(projectRoot, integrationRoot);
|
|
256
|
+
const directoryAbsolute = path.join(projectRoot, relativeDirectory);
|
|
257
|
+
const relativeFromIntegrationRoot = normalizePath(path.relative(integrationRootAbsolute, directoryAbsolute));
|
|
258
|
+
const pathSegments = relativeFromIntegrationRoot === "." ? [] : relativeFromIntegrationRoot.split("/").filter(Boolean);
|
|
259
|
+
let currentDirectory = integrationRootAbsolute;
|
|
260
|
+
const traversal = [currentDirectory, ...pathSegments.map((segment) => {
|
|
261
|
+
currentDirectory = path.join(currentDirectory, segment);
|
|
262
|
+
return currentDirectory;
|
|
263
|
+
})];
|
|
264
|
+
for (const directoryPath of traversal) {
|
|
265
|
+
for (const metadataFileName of INTEGRATION_META_FILE_NAMES) {
|
|
266
|
+
const metadataPath = path.join(directoryPath, metadataFileName);
|
|
267
|
+
readRequiredAnyEnvVarsFromMetadataFile(metadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
readRequiredAnyEnvVarsFromMetadataFile(absoluteSpecPath).forEach((envVar) => requiredAnyEnvVars.add(envVar));
|
|
272
|
+
const specFileName = path.basename(normalizedSpecPath, ".spec.ts");
|
|
273
|
+
const perTestMetadataPath = path.join(path.dirname(absoluteSpecPath), `${specFileName}.meta.ts`);
|
|
274
|
+
readRequiredAnyEnvVarsFromMetadataFile(perTestMetadataPath).forEach((envVar) => requiredAnyEnvVars.add(envVar));
|
|
275
|
+
return Array.from(requiredAnyEnvVars);
|
|
276
|
+
}
|
|
277
|
+
function isEnvironmentVariableConfigured(name) {
|
|
278
|
+
const value = process.env[name];
|
|
279
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
280
|
+
}
|
|
194
281
|
function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
|
|
195
282
|
const discoveredByPath = /* @__PURE__ */ new Map();
|
|
196
283
|
const overlayRoot = resolveOverlayRootPath();
|
|
@@ -207,7 +294,9 @@ function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
|
|
|
207
294
|
path: relativePath,
|
|
208
295
|
moduleName: extractModuleNameFromIntegrationPath(relativePath),
|
|
209
296
|
isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),
|
|
210
|
-
requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath)
|
|
297
|
+
requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),
|
|
298
|
+
requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),
|
|
299
|
+
requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath)
|
|
211
300
|
});
|
|
212
301
|
}
|
|
213
302
|
for (const root of discoveryRoots) {
|
|
@@ -218,7 +307,9 @@ function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
|
|
|
218
307
|
path: relativePath,
|
|
219
308
|
moduleName: extractModuleNameFromIntegrationPath(relativePath),
|
|
220
309
|
isOverlay: isOverlayIntegrationPath(relativePath, overlayRoot),
|
|
221
|
-
requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath)
|
|
310
|
+
requiredModules: resolveRequiredModulesForSpec(projectRoot, relativePath),
|
|
311
|
+
requiredEnvVars: resolveRequiredEnvVarsForSpec(projectRoot, relativePath),
|
|
312
|
+
requiredAnyEnvVars: resolveRequiredAnyEnvVarsForSpec(projectRoot, relativePath)
|
|
222
313
|
});
|
|
223
314
|
}
|
|
224
315
|
}
|
|
@@ -235,6 +326,12 @@ function discoverIntegrationSpecFiles(projectRoot, legacyIntegrationRoot) {
|
|
|
235
326
|
if (file.requiredModules.some((moduleId) => !enabledModules.has(normalizeModuleId(moduleId)))) {
|
|
236
327
|
return false;
|
|
237
328
|
}
|
|
329
|
+
if (file.requiredEnvVars.some((envVar) => !isEnvironmentVariableConfigured(envVar))) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
if (file.requiredAnyEnvVars.length > 0 && !file.requiredAnyEnvVars.some((envVar) => isEnvironmentVariableConfigured(envVar))) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
238
335
|
if (!file.isOverlay) {
|
|
239
336
|
return true;
|
|
240
337
|
}
|
|
@@ -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'\n\nexport type IntegrationSpecDiscoveryItem = {\n path: string\n moduleName: string | null\n isOverlay: boolean\n requiredModules: 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 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 resolveEnabledModuleIds(projectRoot: string): Set<string> {\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 extractDependencyListFromSource(source: string): string[] {\n const collected = new Set<string>()\n for (const key of INTEGRATION_META_DEPENDENCY_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 = normalizeModuleId(valueMatch[1] ?? '')\n if (value) {\n collected.add(value)\n }\n }\n }\n return Array.from(collected)\n}\n\nfunction readDependenciesFromMetadataFile(absolutePath: string): string[] {\n try {\n return extractDependencyListFromSource(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\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 })\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 })\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.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,cAAc,mBAAmB;AAC1C,OAAO,UAAU;
|
|
4
|
+
"sourcesContent": ["import { readFileSync, readdirSync } from 'node:fs'\nimport path from 'node:path'\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 resolveEnabledModuleIds(projectRoot: string): Set<string> {\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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/mercato.js
CHANGED
|
@@ -7,10 +7,12 @@ import { resolveInitDerivedSecrets } from "./lib/init-secrets.js";
|
|
|
7
7
|
import { parseModuleInstallArgs } from "./lib/module-install-args.js";
|
|
8
8
|
import { resolveNextBuildIdCandidate } from "./lib/next-build-id.js";
|
|
9
9
|
import { acquireServerStartLock } from "./lib/server-start-lock.js";
|
|
10
|
+
import { createDevEnvReloader, watchDevEnvFiles } from "./lib/dev-env-reload.js";
|
|
10
11
|
const lazyIntegration = () => import("./lib/testing/integration.js");
|
|
11
12
|
import path from "node:path";
|
|
12
13
|
import fs from "node:fs";
|
|
13
14
|
let envLoaded = false;
|
|
15
|
+
const initialProcessEnvironmentEntries = Object.entries(process.env);
|
|
14
16
|
async function runWithCapturedExitCode(action) {
|
|
15
17
|
const previousExitCode = process.exitCode;
|
|
16
18
|
process.exitCode = void 0;
|
|
@@ -248,6 +250,9 @@ function formatManagedProcessExitStatus(result) {
|
|
|
248
250
|
function createManagedProcessExitError(result) {
|
|
249
251
|
return new Error(`[server] ${result.label} exited unexpectedly with ${formatManagedProcessExitStatus(result)}.`);
|
|
250
252
|
}
|
|
253
|
+
function isDevServerRestartResult(result) {
|
|
254
|
+
return "restart" in result && result.restart === true;
|
|
255
|
+
}
|
|
251
256
|
function formatQueueWorkerLabel(queueNames) {
|
|
252
257
|
if (queueNames.length === 0) return "Queue worker";
|
|
253
258
|
const sorted = [...queueNames].sort((a, b) => a.localeCompare(b));
|
|
@@ -1373,12 +1378,11 @@ async function run(argv = process.argv) {
|
|
|
1373
1378
|
const env = resolveEnvironment();
|
|
1374
1379
|
const appDir = env.appDir;
|
|
1375
1380
|
const nodeModulesBases = Array.from(/* @__PURE__ */ new Set([env.rootDir, appDir]));
|
|
1376
|
-
|
|
1377
|
-
const autoSpawnWorkers = process.env.AUTO_SPAWN_WORKERS !== "false";
|
|
1378
|
-
const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== "false";
|
|
1379
|
-
const queueStrategy = process.env.QUEUE_STRATEGY || "local";
|
|
1381
|
+
let processes = [];
|
|
1380
1382
|
let didRetryCorruptedTurbopackCache = false;
|
|
1381
|
-
|
|
1383
|
+
let stopping = false;
|
|
1384
|
+
let envChangePromiseResolve = null;
|
|
1385
|
+
const envReloader = createDevEnvReloader(appDir, process.env, initialProcessEnvironmentEntries);
|
|
1382
1386
|
function cleanup() {
|
|
1383
1387
|
console.log("[server] Shutting down...");
|
|
1384
1388
|
for (const proc of processes) {
|
|
@@ -1402,19 +1406,36 @@ async function run(argv = process.argv) {
|
|
|
1402
1406
|
fs.unlinkSync(lockFile);
|
|
1403
1407
|
} catch {
|
|
1404
1408
|
}
|
|
1409
|
+
processes = [];
|
|
1405
1410
|
}
|
|
1406
|
-
process.on("SIGTERM",
|
|
1407
|
-
|
|
1411
|
+
process.on("SIGTERM", () => {
|
|
1412
|
+
stopping = true;
|
|
1413
|
+
cleanup();
|
|
1414
|
+
});
|
|
1415
|
+
process.on("SIGINT", () => {
|
|
1416
|
+
stopping = true;
|
|
1417
|
+
cleanup();
|
|
1418
|
+
});
|
|
1408
1419
|
console.log("[server] Starting Open Mercato in dev mode...");
|
|
1409
1420
|
const { createResolver: createResolverForSources } = await import("./lib/resolver.js");
|
|
1410
1421
|
const { generateModulePackageSources } = await import("./lib/generators/index.js");
|
|
1411
1422
|
await generateModulePackageSources({ resolver: createResolverForSources(), quiet: true });
|
|
1412
1423
|
const nextBin = resolveInstalledBinary(nodeModulesBases, "next/dist/bin/next");
|
|
1413
1424
|
const mercatoBin = resolveInstalledBinary(nodeModulesBases, "@open-mercato/cli/bin/mercato");
|
|
1414
|
-
const
|
|
1425
|
+
const stopEnvWatcher = watchDevEnvFiles(appDir, (filePath) => {
|
|
1426
|
+
envChangePromiseResolve?.({
|
|
1427
|
+
label: "Environment file change",
|
|
1428
|
+
restart: true,
|
|
1429
|
+
filePath
|
|
1430
|
+
});
|
|
1431
|
+
});
|
|
1432
|
+
const waitForEnvChange = () => new Promise((resolve) => {
|
|
1433
|
+
envChangePromiseResolve = resolve;
|
|
1434
|
+
});
|
|
1435
|
+
const startNextDev = (runtimeEnv) => new Promise((resolve) => {
|
|
1415
1436
|
const nextProcess = spawn("node", [nextBin, "dev", "--turbopack"], {
|
|
1416
1437
|
stdio: ["inherit", "pipe", "pipe"],
|
|
1417
|
-
env:
|
|
1438
|
+
env: runtimeEnv,
|
|
1418
1439
|
cwd: appDir
|
|
1419
1440
|
});
|
|
1420
1441
|
processes.push(nextProcess);
|
|
@@ -1440,7 +1461,7 @@ async function run(argv = process.argv) {
|
|
|
1440
1461
|
didRetryCorruptedTurbopackCache = true;
|
|
1441
1462
|
console.log("[server] Detected corrupted Turbopack dev cache. Clearing .mercato/next/dev and restarting Next.js once...");
|
|
1442
1463
|
removeTurbopackDevCache(appDir);
|
|
1443
|
-
return resolve(await startNextDev());
|
|
1464
|
+
return resolve(await startNextDev(runtimeEnv));
|
|
1444
1465
|
}
|
|
1445
1466
|
resolve({
|
|
1446
1467
|
label: "Next.js dev server",
|
|
@@ -1449,41 +1470,61 @@ async function run(argv = process.argv) {
|
|
|
1449
1470
|
});
|
|
1450
1471
|
});
|
|
1451
1472
|
});
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
const
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1473
|
+
try {
|
|
1474
|
+
while (!stopping) {
|
|
1475
|
+
envReloader.reload();
|
|
1476
|
+
const runtimeEnv = buildServerProcessEnvironment(process.env);
|
|
1477
|
+
const autoSpawnWorkers = process.env.AUTO_SPAWN_WORKERS !== "false";
|
|
1478
|
+
const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== "false";
|
|
1479
|
+
const queueStrategy = process.env.QUEUE_STRATEGY || "local";
|
|
1480
|
+
const schedulerCommand = lookupModuleCommand(getCliModules(), "scheduler", "start");
|
|
1481
|
+
const managedExitPromises = [
|
|
1482
|
+
startNextDev(runtimeEnv),
|
|
1483
|
+
waitForEnvChange()
|
|
1484
|
+
];
|
|
1485
|
+
if (autoSpawnWorkers) {
|
|
1486
|
+
const discoveredWorkerQueues = [...new Set(getRegisteredCliWorkers().map((worker) => worker.queue))];
|
|
1487
|
+
if (discoveredWorkerQueues.length === 0) {
|
|
1488
|
+
console.error("[server] AUTO_SPAWN_WORKERS is enabled, but no queues were discovered from CLI modules. Run `yarn generate` and verify `.mercato/generated/modules.cli.generated.ts` contains worker entries. Continuing without auto-spawned workers.");
|
|
1489
|
+
} else {
|
|
1490
|
+
console.log("[server] Starting workers for all queues...");
|
|
1491
|
+
const workerProcess = spawn("node", [mercatoBin, "queue", "worker", "--all"], {
|
|
1492
|
+
stdio: "inherit",
|
|
1493
|
+
env: runtimeEnv,
|
|
1494
|
+
cwd: appDir
|
|
1495
|
+
});
|
|
1496
|
+
processes.push(workerProcess);
|
|
1497
|
+
managedExitPromises.push(waitForManagedProcessExit(workerProcess, formatQueueWorkerLabel(discoveredWorkerQueues)));
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
if (autoSpawnScheduler && queueStrategy === "local") {
|
|
1501
|
+
if (schedulerCommand.status !== "ok") {
|
|
1502
|
+
console.log(`[server] Skipping scheduler auto-start \u2014 ${describeMissingModuleCommand(schedulerCommand)}`);
|
|
1503
|
+
} else {
|
|
1504
|
+
console.log("[server] Starting scheduler polling engine...");
|
|
1505
|
+
const schedulerProcess = spawn("node", [mercatoBin, "scheduler", "start"], {
|
|
1506
|
+
stdio: "inherit",
|
|
1507
|
+
env: runtimeEnv,
|
|
1508
|
+
cwd: appDir
|
|
1509
|
+
});
|
|
1510
|
+
processes.push(schedulerProcess);
|
|
1511
|
+
managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, "Scheduler polling engine"));
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
const firstExit = await Promise.race(managedExitPromises);
|
|
1515
|
+
await cleanupAndWait();
|
|
1516
|
+
envChangePromiseResolve = null;
|
|
1517
|
+
if (isDevServerRestartResult(firstExit)) {
|
|
1518
|
+
console.log(`[server] Detected environment file change (${path.basename(firstExit.filePath)}). Restarting app runtime...`);
|
|
1519
|
+
continue;
|
|
1520
|
+
}
|
|
1521
|
+
if (!isExpectedManagedExitSignal(firstExit.signal)) {
|
|
1522
|
+
throw createManagedProcessExitError(firstExit);
|
|
1523
|
+
}
|
|
1524
|
+
stopping = true;
|
|
1481
1525
|
}
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
await cleanupAndWait();
|
|
1485
|
-
if (!isExpectedManagedExitSignal(firstExit.signal)) {
|
|
1486
|
-
throw createManagedProcessExitError(firstExit);
|
|
1526
|
+
} finally {
|
|
1527
|
+
stopEnvWatcher();
|
|
1487
1528
|
}
|
|
1488
1529
|
}
|
|
1489
1530
|
},
|