@open-mercato/cli 0.4.9-develop.1038.2d16936bed → 0.4.9-develop.1045.7bcda4435a
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/dist/lib/generators/module-registry.js +17 -0
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/scanner.js +9 -1
- package/dist/lib/generators/scanner.js.map +2 -2
- package/dist/lib/testing/integration.js +4 -0
- package/dist/lib/testing/integration.js.map +2 -2
- package/package.json +4 -4
- package/src/lib/generators/module-registry.ts +19 -0
- package/src/lib/generators/scanner.ts +13 -1
- package/src/lib/testing/__tests__/integration.test.ts +51 -0
- package/src/lib/testing/integration.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.4.9-develop.
|
|
3
|
+
"version": "0.4.9-develop.1045.7bcda4435a",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -58,17 +58,17 @@
|
|
|
58
58
|
"@mikro-orm/core": "^6.6.2",
|
|
59
59
|
"@mikro-orm/migrations": "^6.6.2",
|
|
60
60
|
"@mikro-orm/postgresql": "^6.6.2",
|
|
61
|
-
"@open-mercato/shared": "0.4.9-develop.
|
|
61
|
+
"@open-mercato/shared": "0.4.9-develop.1045.7bcda4435a",
|
|
62
62
|
"pg": "8.20.0",
|
|
63
63
|
"semver": "^7.7.3",
|
|
64
64
|
"testcontainers": "^11.12.0",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
|
-
"@open-mercato/shared": "0.4.9-develop.
|
|
68
|
+
"@open-mercato/shared": "0.4.9-develop.1045.7bcda4435a"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@open-mercato/shared": "0.4.9-develop.
|
|
71
|
+
"@open-mercato/shared": "0.4.9-develop.1045.7bcda4435a",
|
|
72
72
|
"@types/jest": "^30.0.0",
|
|
73
73
|
"jest": "^30.2.0",
|
|
74
74
|
"ts-jest": "^29.4.6"
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
scanModuleDir,
|
|
14
14
|
resolveModuleFile,
|
|
15
|
+
resolveFirstModuleFile,
|
|
15
16
|
SCAN_CONFIGS,
|
|
16
17
|
type ModuleRoots,
|
|
17
18
|
type ModuleImports,
|
|
@@ -391,6 +392,8 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
391
392
|
const notificationsChecksumFile = path.join(outputDir, 'notifications.generated.checksum')
|
|
392
393
|
const notificationsClientOutFile = path.join(outputDir, 'notifications.client.generated.ts')
|
|
393
394
|
const notificationsClientChecksumFile = path.join(outputDir, 'notifications.client.generated.checksum')
|
|
395
|
+
const paymentsClientOutFile = path.join(outputDir, 'payments.client.generated.ts')
|
|
396
|
+
const paymentsClientChecksumFile = path.join(outputDir, 'payments.client.generated.checksum')
|
|
394
397
|
const notificationHandlersOutFile = path.join(outputDir, 'notification-handlers.generated.ts')
|
|
395
398
|
const notificationHandlersChecksumFile = path.join(outputDir, 'notification-handlers.generated.checksum')
|
|
396
399
|
const messageTypesOutFile = path.join(outputDir, 'message-types.generated.ts')
|
|
@@ -467,6 +470,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
467
470
|
const notificationImports: string[] = []
|
|
468
471
|
const notificationClientTypes: string[] = []
|
|
469
472
|
const notificationClientImports: string[] = []
|
|
473
|
+
const paymentsClientImports: string[] = []
|
|
470
474
|
const notificationHandlerEntries: string[] = []
|
|
471
475
|
const notificationHandlerImports: string[] = []
|
|
472
476
|
const messageTypeEntries: string[] = []
|
|
@@ -636,6 +640,16 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
636
640
|
configExpr: (n, id) => `{ moduleId: '${id}', types: (${n}.default ?? []) }`,
|
|
637
641
|
})
|
|
638
642
|
|
|
643
|
+
{
|
|
644
|
+
const resolved = resolveFirstModuleFile(roots, imps, [
|
|
645
|
+
'widgets/payments/client.tsx',
|
|
646
|
+
'widgets/payments/client.ts',
|
|
647
|
+
])
|
|
648
|
+
if (resolved) {
|
|
649
|
+
paymentsClientImports.push(`import '${resolved.importPath}'`)
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
639
653
|
processStandaloneConfig({
|
|
640
654
|
roots, imps, modId, importIdRef,
|
|
641
655
|
relativePath: 'notifications.handlers.ts',
|
|
@@ -1277,6 +1291,10 @@ ${notificationHandlersImportSection ? `\n${notificationHandlersImportSection}\n`
|
|
|
1277
1291
|
|
|
1278
1292
|
export const notificationHandlerEntries: NotificationHandlerEntry[] = [
|
|
1279
1293
|
${notificationHandlersEntriesLiteral ? ` ${notificationHandlersEntriesLiteral}\n` : ''}]
|
|
1294
|
+
`
|
|
1295
|
+
|
|
1296
|
+
const paymentsClientOutput = `// AUTO-GENERATED by mercato generate registry
|
|
1297
|
+
${paymentsClientImports.length ? paymentsClientImports.join('\n') + '\n' : '\n'}export const paymentGatewayClientModuleCount = ${paymentsClientImports.length}
|
|
1280
1298
|
`
|
|
1281
1299
|
|
|
1282
1300
|
const messageTypeEntriesLiteral = messageTypeEntries.join(',\n ')
|
|
@@ -1489,6 +1507,7 @@ export const allAiTools = aiToolConfigEntries.flatMap(e => e.tools)
|
|
|
1489
1507
|
writeGeneratedFile({ outFile: aiToolsOutFile, checksumFile: aiToolsChecksumFile, content: aiToolsOutput, structureChecksum, result, quiet })
|
|
1490
1508
|
writeGeneratedFile({ outFile: notificationsOutFile, checksumFile: notificationsChecksumFile, content: notificationsOutput, structureChecksum, result, quiet })
|
|
1491
1509
|
writeGeneratedFile({ outFile: notificationsClientOutFile, checksumFile: notificationsClientChecksumFile, content: notificationsClientOutput, structureChecksum, result, quiet })
|
|
1510
|
+
writeGeneratedFile({ outFile: paymentsClientOutFile, checksumFile: paymentsClientChecksumFile, content: paymentsClientOutput, structureChecksum, result, quiet })
|
|
1492
1511
|
writeGeneratedFile({ outFile: notificationHandlersOutFile, checksumFile: notificationHandlersChecksumFile, content: notificationHandlersOutput, structureChecksum, result, quiet })
|
|
1493
1512
|
writeGeneratedFile({ outFile: messageTypesOutFile, checksumFile: messageTypesChecksumFile, content: messageTypesOutput, structureChecksum, result, quiet })
|
|
1494
1513
|
writeGeneratedFile({ outFile: messageObjectsOutFile, checksumFile: messageObjectsChecksumFile, content: messageObjectsOutput, structureChecksum, result, quiet })
|
|
@@ -153,7 +153,19 @@ export function resolveModuleFile(
|
|
|
153
153
|
|
|
154
154
|
const fromApp = hasApp
|
|
155
155
|
const absolutePath = fromApp ? appFile : pkgFile
|
|
156
|
-
const importSuffix = relativePath.replace(/\.
|
|
156
|
+
const importSuffix = relativePath.replace(/\.tsx?$/, '')
|
|
157
157
|
const importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${importSuffix}`
|
|
158
158
|
return { absolutePath, fromApp, importPath }
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
export function resolveFirstModuleFile(
|
|
162
|
+
roots: ModuleRoots,
|
|
163
|
+
imps: ModuleImports,
|
|
164
|
+
relativePaths: string[],
|
|
165
|
+
): ResolvedFile | null {
|
|
166
|
+
for (const relativePath of relativePaths) {
|
|
167
|
+
const resolved = resolveModuleFile(roots, imps, relativePath)
|
|
168
|
+
if (resolved) return resolved
|
|
169
|
+
}
|
|
170
|
+
return null
|
|
171
|
+
}
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
|
|
21
21
|
const CACHE_TTL_ENV_VAR = 'OM_INTEGRATION_BUILD_CACHE_TTL_SECONDS'
|
|
22
22
|
const APP_READY_TIMEOUT_ENV_VAR = 'OM_INTEGRATION_APP_READY_TIMEOUT_SECONDS'
|
|
23
|
+
const CHECKOUT_TEST_INJECTION_FLAG = 'NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED'
|
|
23
24
|
const resolver = createResolver()
|
|
24
25
|
const projectRootDirectory = resolver.getRootDir()
|
|
25
26
|
|
|
@@ -39,6 +40,7 @@ describe('integration cache and options', () => {
|
|
|
39
40
|
const ephemeralLegacyEnvFilePath = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-env.md')
|
|
40
41
|
const originalCacheTtl = process.env[CACHE_TTL_ENV_VAR]
|
|
41
42
|
const originalAppReadyTimeout = process.env[APP_READY_TIMEOUT_ENV_VAR]
|
|
43
|
+
const originalCheckoutTestInjectionFlag = process.env[CHECKOUT_TEST_INJECTION_FLAG]
|
|
42
44
|
let originalEphemeralEnvState: string | null = null
|
|
43
45
|
let originalEphemeralLegacyEnvState: string | null = null
|
|
44
46
|
|
|
@@ -69,11 +71,17 @@ describe('integration cache and options', () => {
|
|
|
69
71
|
} else {
|
|
70
72
|
process.env[APP_READY_TIMEOUT_ENV_VAR] = originalAppReadyTimeout
|
|
71
73
|
}
|
|
74
|
+
if (originalCheckoutTestInjectionFlag === undefined) {
|
|
75
|
+
delete process.env[CHECKOUT_TEST_INJECTION_FLAG]
|
|
76
|
+
} else {
|
|
77
|
+
process.env[CHECKOUT_TEST_INJECTION_FLAG] = originalCheckoutTestInjectionFlag
|
|
78
|
+
}
|
|
72
79
|
await restoreEphemeralStateFiles(originalEphemeralEnvState, originalEphemeralLegacyEnvState)
|
|
73
80
|
})
|
|
74
81
|
|
|
75
82
|
it('reuses an existing reachable ephemeral environment state', async () => {
|
|
76
83
|
const baseUrl = 'http://127.0.0.1:5001'
|
|
84
|
+
delete process.env[CHECKOUT_TEST_INJECTION_FLAG]
|
|
77
85
|
const fetchSpy = jest.spyOn(global, 'fetch').mockImplementation(async (input) => {
|
|
78
86
|
const url = typeof input === 'string' ? input : String(input)
|
|
79
87
|
if (url.endsWith('/api/auth/login')) {
|
|
@@ -116,6 +124,49 @@ describe('integration cache and options', () => {
|
|
|
116
124
|
ownedByCurrentProcess: false,
|
|
117
125
|
})
|
|
118
126
|
expect(environment?.commandEnvironment.PW_CAPTURE_SCREENSHOTS).toBe('1')
|
|
127
|
+
expect(environment?.commandEnvironment.NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED).toBeUndefined()
|
|
128
|
+
} finally {
|
|
129
|
+
fetchSpy.mockRestore()
|
|
130
|
+
}
|
|
131
|
+
}, 20000)
|
|
132
|
+
|
|
133
|
+
it('reuses an existing environment with checkout wrapper injections only when explicitly enabled', async () => {
|
|
134
|
+
const baseUrl = 'http://127.0.0.1:5001'
|
|
135
|
+
process.env[CHECKOUT_TEST_INJECTION_FLAG] = 'true'
|
|
136
|
+
const fetchSpy = jest.spyOn(global, 'fetch').mockImplementation(async (input) => {
|
|
137
|
+
const url = typeof input === 'string' ? input : String(input)
|
|
138
|
+
if (url.endsWith('/api/auth/login')) {
|
|
139
|
+
return { status: 401, text: async () => '' } as unknown as Response
|
|
140
|
+
}
|
|
141
|
+
if (url.endsWith('/login')) {
|
|
142
|
+
return {
|
|
143
|
+
status: 200,
|
|
144
|
+
text: async () => '<!doctype html><script src="/_next/static/chunks/app-healthcheck.js"></script>',
|
|
145
|
+
} as unknown as Response
|
|
146
|
+
}
|
|
147
|
+
if (url.includes('/_next/static/chunks/app-healthcheck.js')) {
|
|
148
|
+
return { status: 200, text: async () => '' } as unknown as Response
|
|
149
|
+
}
|
|
150
|
+
return { status: 200, text: async () => '' } as unknown as Response
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await writeEphemeralEnvironmentState({
|
|
155
|
+
baseUrl,
|
|
156
|
+
port: 5001,
|
|
157
|
+
logPrefix: 'integration',
|
|
158
|
+
captureScreenshots: true,
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const environment = await tryReuseExistingEnvironment({
|
|
162
|
+
verbose: false,
|
|
163
|
+
captureScreenshots: true,
|
|
164
|
+
logPrefix: 'integration',
|
|
165
|
+
forceRebuild: false,
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
expect(environment).not.toBeNull()
|
|
169
|
+
expect(environment?.commandEnvironment.NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED).toBe('true')
|
|
119
170
|
} finally {
|
|
120
171
|
fetchSpy.mockRestore()
|
|
121
172
|
}
|
|
@@ -1357,6 +1357,8 @@ async function clearStaleEphemeralEnvironmentLock(logPrefix: string): Promise<bo
|
|
|
1357
1357
|
function buildReusableEnvironment(baseUrl: string, captureScreenshots: boolean): NodeJS.ProcessEnv {
|
|
1358
1358
|
return buildEnvironment({
|
|
1359
1359
|
BASE_URL: baseUrl,
|
|
1360
|
+
APP_URL: baseUrl,
|
|
1361
|
+
NEXT_PUBLIC_APP_URL: baseUrl,
|
|
1360
1362
|
NODE_ENV: 'production',
|
|
1361
1363
|
JWT_SECRET: process.env.JWT_SECRET ?? 'om-ephemeral-integration-jwt-secret',
|
|
1362
1364
|
OM_SECURITY_MFA_SETUP_SECRET: process.env.OM_SECURITY_MFA_SETUP_SECRET ?? 'om-ephemeral-integration-mfa-setup-secret',
|
|
@@ -2572,6 +2574,8 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
2572
2574
|
const commandEnvironment = buildEnvironment({
|
|
2573
2575
|
DATABASE_URL: databaseUrl,
|
|
2574
2576
|
BASE_URL: applicationBaseUrl,
|
|
2577
|
+
APP_URL: applicationBaseUrl,
|
|
2578
|
+
NEXT_PUBLIC_APP_URL: applicationBaseUrl,
|
|
2575
2579
|
JWT_SECRET: process.env.JWT_SECRET ?? 'om-ephemeral-integration-jwt-secret',
|
|
2576
2580
|
OM_SECURITY_MFA_SETUP_SECRET: process.env.OM_SECURITY_MFA_SETUP_SECRET ?? 'om-ephemeral-integration-mfa-setup-secret',
|
|
2577
2581
|
NODE_ENV: 'production',
|