@open-mercato/cli 0.10.1-develop.7990.1.82d0a183c5 → 0.10.1-develop.7994.1.c9f31972aa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/agentic/guides/module-facts.json +162 -162
- package/dist/agentic/guides/module-facts.v2.json +162 -162
- package/dist/agentic/guides/module-tool.md +21 -0
- package/dist/agentic/guides/modules/agent_orchestrator/index.md +1 -1
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/availability/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/carrier_inpost/index.md +1 -1
- package/dist/agentic/guides/modules/cart/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/channel_resend/index.md +1 -1
- package/dist/agentic/guides/modules/channel_ses/index.md +1 -1
- package/dist/agentic/guides/modules/channel_smtp/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customer_groups/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/documents/index.md +1 -1
- package/dist/agentic/guides/modules/ecommerce/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/forms/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_autopay/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_tpay/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/phone_calls/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/promotions/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/seeds/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/telemetry/index.md +1 -1
- package/dist/agentic/guides/modules/tillio/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/agentic/shared/ai/harness/cases.json +23 -9
- package/dist/agentic/shared/ai/harness/source-link-inventory.json +90 -4
- package/dist/lib/__integration__/TC-INT-007.spec.js +207 -19
- package/dist/lib/__integration__/TC-INT-007.spec.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-009.spec.js +267 -0
- package/dist/lib/__integration__/TC-INT-009.spec.js.map +7 -0
- package/dist/lib/eject.js +25 -9
- package/dist/lib/eject.js.map +2 -2
- package/dist/lib/generators/entity-ids.js +2 -0
- package/dist/lib/generators/entity-ids.js.map +2 -2
- package/dist/lib/generators/module-di.js +2 -0
- package/dist/lib/generators/module-di.js.map +2 -2
- package/dist/lib/generators/module-entities.js +2 -0
- package/dist/lib/generators/module-entities.js.map +2 -2
- package/dist/lib/generators/module-package-sources.js +6 -4
- package/dist/lib/generators/module-package-sources.js.map +2 -2
- package/dist/lib/generators/module-registry.js +32 -86
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/openapi.js +2 -0
- package/dist/lib/generators/openapi.js.map +2 -2
- package/dist/lib/generators/source-exports.js +73 -0
- package/dist/lib/generators/source-exports.js.map +7 -0
- package/dist/lib/init-summary.js +44 -0
- package/dist/lib/init-summary.js.map +7 -0
- package/dist/lib/module-github.js +98 -0
- package/dist/lib/module-github.js.map +7 -0
- package/dist/lib/module-identity.js +131 -0
- package/dist/lib/module-identity.js.map +7 -0
- package/dist/lib/module-inspection.js +124 -0
- package/dist/lib/module-inspection.js.map +7 -0
- package/dist/lib/module-install.js +150 -21
- package/dist/lib/module-install.js.map +3 -3
- package/dist/lib/module-package.js +205 -15
- package/dist/lib/module-package.js.map +2 -2
- package/dist/lib/modules-config.js +69 -30
- package/dist/lib/modules-config.js.map +2 -2
- package/dist/lib/resolver.js +33 -34
- package/dist/lib/resolver.js.map +2 -2
- package/dist/mercato.js +14 -23
- package/dist/mercato.js.map +2 -2
- package/package.json +7 -7
- package/src/__tests__/mercato.test.ts +14 -4
- package/src/lib/__fixtures__/official-module-package/dist/modules/test_package/widgets/injection/test/widget.js +1 -0
- package/src/lib/__integration__/TC-INT-007.spec.ts +219 -19
- package/src/lib/__integration__/TC-INT-009.spec.ts +279 -0
- package/src/lib/__tests__/eject.test.ts +98 -4
- package/src/lib/__tests__/init-summary.test.ts +50 -0
- package/src/lib/__tests__/module-github.test.ts +108 -0
- package/src/lib/__tests__/module-identity.test.ts +144 -0
- package/src/lib/__tests__/module-inspection.test.ts +195 -0
- package/src/lib/__tests__/module-install.test.ts +399 -10
- package/src/lib/__tests__/module-package.test.ts +154 -0
- package/src/lib/__tests__/modules-config.test.ts +55 -0
- package/src/lib/__tests__/resolver.packages.test.ts +29 -0
- package/src/lib/eject.ts +28 -10
- package/src/lib/generators/__tests__/module-id-collisions.test.ts +146 -0
- package/src/lib/generators/__tests__/module-package-sources.test.ts +19 -2
- package/src/lib/generators/__tests__/module-requirements.test.ts +56 -0
- package/src/lib/generators/entity-ids.ts +2 -0
- package/src/lib/generators/module-di.ts +2 -0
- package/src/lib/generators/module-entities.ts +2 -0
- package/src/lib/generators/module-package-sources.ts +7 -5
- package/src/lib/generators/module-registry.ts +33 -115
- package/src/lib/generators/openapi.ts +3 -0
- package/src/lib/generators/source-exports.ts +93 -0
- package/src/lib/init-summary.ts +54 -0
- package/src/lib/module-github.ts +109 -0
- package/src/lib/module-identity.ts +145 -0
- package/src/lib/module-inspection.ts +133 -0
- package/src/lib/module-install.ts +170 -22
- package/src/lib/module-package.ts +243 -16
- package/src/lib/modules-config.ts +80 -32
- package/src/lib/resolver.ts +35 -39
- package/src/mercato.ts +14 -24
- package/src/types/cross-spawn.d.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.10.1-develop.
|
|
3
|
+
"version": "0.10.1-develop.7994.1.c9f31972aa",
|
|
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.
|
|
64
|
-
"@open-mercato/queue": "0.10.1-develop.
|
|
65
|
-
"@open-mercato/shared": "0.10.1-develop.
|
|
66
|
-
"@open-mercato/telemetry": "0.10.1-develop.
|
|
63
|
+
"@open-mercato/events": "0.10.1-develop.7994.1.c9f31972aa",
|
|
64
|
+
"@open-mercato/queue": "0.10.1-develop.7994.1.c9f31972aa",
|
|
65
|
+
"@open-mercato/shared": "0.10.1-develop.7994.1.c9f31972aa",
|
|
66
|
+
"@open-mercato/telemetry": "0.10.1-develop.7994.1.c9f31972aa",
|
|
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.
|
|
78
|
+
"@open-mercato/shared": "0.10.1-develop.7994.1.c9f31972aa"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@open-mercato/shared": "0.10.1-develop.
|
|
81
|
+
"@open-mercato/shared": "0.10.1-develop.7994.1.c9f31972aa",
|
|
82
82
|
"@types/jest": "^30.0.0",
|
|
83
83
|
"jest": "^30.4.2",
|
|
84
84
|
"ts-jest": "^29.4.12"
|
|
@@ -1125,8 +1125,8 @@ describe('init command failure output', () => {
|
|
|
1125
1125
|
expect(authSetup).toHaveBeenCalledWith(expect.arrayContaining(['--include-demo-users']))
|
|
1126
1126
|
expect(consoleLogSpy).toHaveBeenCalledWith('👤 Demo accounts (admin@/employee@): enabled')
|
|
1127
1127
|
const loggedLines = consoleLogSpy.mock.calls.map((args) => args.join(' '))
|
|
1128
|
-
expect(loggedLines.some((line) => line.includes('🧰 Admin
|
|
1129
|
-
expect(loggedLines.some((line) => line.includes('👷 Employee
|
|
1128
|
+
expect(loggedLines.some((line) => line.includes('🧰 Admin'))).toBe(true)
|
|
1129
|
+
expect(loggedLines.some((line) => line.includes('👷 Employee'))).toBe(true)
|
|
1130
1130
|
|
|
1131
1131
|
consoleErrorSpy.mockRestore()
|
|
1132
1132
|
consoleLogSpy.mockRestore()
|
|
@@ -1148,8 +1148,8 @@ describe('init command failure output', () => {
|
|
|
1148
1148
|
'👤 Demo accounts (admin@/employee@): skipped (--no-demo-users)',
|
|
1149
1149
|
)
|
|
1150
1150
|
const loggedLines = consoleLogSpy.mock.calls.map((args) => args.join(' '))
|
|
1151
|
-
expect(loggedLines.some((line) => line.includes('🧰 Admin
|
|
1152
|
-
expect(loggedLines.some((line) => line.includes('👷 Employee
|
|
1151
|
+
expect(loggedLines.some((line) => line.includes('🧰 Admin'))).toBe(false)
|
|
1152
|
+
expect(loggedLines.some((line) => line.includes('👷 Employee'))).toBe(false)
|
|
1153
1153
|
|
|
1154
1154
|
consoleErrorSpy.mockRestore()
|
|
1155
1155
|
consoleLogSpy.mockRestore()
|
|
@@ -1735,6 +1735,11 @@ describe('server dev managed process exits', () => {
|
|
|
1735
1735
|
expect(exitCode).toBe(0)
|
|
1736
1736
|
expect(consoleErrorSpy).not.toHaveBeenCalled()
|
|
1737
1737
|
expect(consoleLogSpy).toHaveBeenCalledWith('[server] Skipping scheduler auto-start — module not enabled')
|
|
1738
|
+
const { spawn } = await import('child_process')
|
|
1739
|
+
const nextSpawn = (spawn as jest.Mock).mock.calls.find((call) =>
|
|
1740
|
+
pathIncludes(call[1]?.[0] ?? '', 'next/dist/bin/next') && call[1]?.includes('dev'),
|
|
1741
|
+
)
|
|
1742
|
+
expect(nextSpawn?.[2]?.env.NODE_ENV).toBe('development')
|
|
1738
1743
|
|
|
1739
1744
|
consoleErrorSpy.mockRestore()
|
|
1740
1745
|
consoleLogSpy.mockRestore()
|
|
@@ -2477,6 +2482,11 @@ describe('server start managed process exits', () => {
|
|
|
2477
2482
|
expect(exitCode).toBe(0)
|
|
2478
2483
|
expect(consoleErrorSpy).not.toHaveBeenCalled()
|
|
2479
2484
|
expect(consoleLogSpy).toHaveBeenCalledWith('[server] Skipping scheduler auto-start — module not enabled')
|
|
2485
|
+
const { spawn } = await import('child_process')
|
|
2486
|
+
const nextSpawn = (spawn as jest.Mock).mock.calls.find((call) =>
|
|
2487
|
+
pathIncludes(call[1]?.[0] ?? '', 'next/dist/bin/next') && call[1]?.includes('start'),
|
|
2488
|
+
)
|
|
2489
|
+
expect(nextSpawn?.[2]?.env.NODE_ENV).toBe('production')
|
|
2480
2490
|
|
|
2481
2491
|
consoleErrorSpy.mockRestore()
|
|
2482
2492
|
consoleLogSpy.mockRestore()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function widget() {}
|
|
@@ -22,21 +22,33 @@ function yarnBinary(): string {
|
|
|
22
22
|
return process.platform === 'win32' ? 'yarn.cmd' : 'yarn'
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function runCommand(command: string, args: string[], cwd: string): string {
|
|
25
|
+
function runCommand(command: string, args: string[], cwd: string, environment: NodeJS.ProcessEnv = {}): string {
|
|
26
26
|
const yarnCacheFolder = path.join(cwd, '.yarn', 'cache')
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
try {
|
|
28
|
+
return execFileSync(command, args, {
|
|
29
|
+
cwd,
|
|
30
|
+
encoding: 'utf8',
|
|
31
|
+
env: {
|
|
32
|
+
...process.env,
|
|
33
|
+
FORCE_COLOR: '0',
|
|
34
|
+
NODE_NO_WARNINGS: '1',
|
|
35
|
+
YARN_CACHE_FOLDER: yarnCacheFolder,
|
|
36
|
+
YARN_ENABLE_GLOBAL_CACHE: '0',
|
|
37
|
+
YARN_ENABLE_IMMUTABLE_INSTALLS: '0',
|
|
38
|
+
YARN_NODE_LINKER: 'node-modules',
|
|
39
|
+
...environment,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (!error || typeof error !== 'object') throw error
|
|
44
|
+
const errorRecord = error as Record<string, unknown>
|
|
45
|
+
const outputs = ['stdout', 'stderr'].flatMap((streamName) => {
|
|
46
|
+
const output = errorRecord[streamName]
|
|
47
|
+
return typeof output === 'string' || Buffer.isBuffer(output) ? [output.toString().trim()] : []
|
|
48
|
+
}).filter(Boolean)
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
50
|
+
throw new Error(outputs.length > 0 ? `${message}\n${outputs.join('\n')}` : message)
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
function runMercato(args: string[], cwd: string): string {
|
|
@@ -77,6 +89,7 @@ const commentedModulesSource = [
|
|
|
77
89
|
].join('\n')
|
|
78
90
|
|
|
79
91
|
function createMonorepoFixture(rootDir: string): string {
|
|
92
|
+
writeFile(path.join(rootDir, 'yarn.lock'), '')
|
|
80
93
|
writeFile(
|
|
81
94
|
path.join(rootDir, 'package.json'),
|
|
82
95
|
JSON.stringify(
|
|
@@ -113,6 +126,7 @@ function createMonorepoFixture(rootDir: string): string {
|
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
function createStandaloneFixture(rootDir: string): string {
|
|
129
|
+
writeFile(path.join(rootDir, 'yarn.lock'), '')
|
|
116
130
|
writeFile(
|
|
117
131
|
path.join(rootDir, '.yarnrc.yml'),
|
|
118
132
|
['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\n'),
|
|
@@ -196,14 +210,196 @@ test.describe('TC-INT-007: CLI official module install and eject flows', () => {
|
|
|
196
210
|
const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))
|
|
197
211
|
const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))
|
|
198
212
|
|
|
199
|
-
expect(modulesSource).
|
|
213
|
+
expect(modulesSource).toMatch(/id: 'test_package', from: '@app'/)
|
|
214
|
+
expect(modulesSource).not.toContain('locator:')
|
|
215
|
+
expect(modulesSource).toContain("packageName: '@open-mercato/test-package'")
|
|
200
216
|
expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)
|
|
217
|
+
expect(readFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(readFile(path.join(fixtureModulePackage, 'src', 'modules', 'test_package', 'index.ts')))
|
|
201
218
|
expect(cssSource).toBe('')
|
|
202
219
|
} finally {
|
|
203
220
|
fs.rmSync(appDir, { recursive: true, force: true })
|
|
204
221
|
}
|
|
205
222
|
})
|
|
206
223
|
|
|
224
|
+
test('module add reports dependencies that must be enabled before registration', () => {
|
|
225
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-dependencies-'))
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
createStandaloneFixture(appDir)
|
|
229
|
+
const packageDir = path.join(appDir, 'fixture-module-package')
|
|
230
|
+
fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })
|
|
231
|
+
writeFile(
|
|
232
|
+
path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),
|
|
233
|
+
"export const metadata = { id: 'test_package', requires: ['customers'], ejectable: true }\n",
|
|
234
|
+
)
|
|
235
|
+
runCommand(yarnBinary(), ['install'], appDir)
|
|
236
|
+
|
|
237
|
+
expect(() => runMercato(
|
|
238
|
+
['module', 'add', '@open-mercato/test-package@file:./fixture-module-package'],
|
|
239
|
+
appDir,
|
|
240
|
+
)).toThrow(/requires module\(s\) that are not enabled: customers/)
|
|
241
|
+
|
|
242
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe('export const enabledModules = []\n')
|
|
243
|
+
} finally {
|
|
244
|
+
fs.rmSync(appDir, { recursive: true, force: true })
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('module add resolves canonical requirements from retained ejected origins', () => {
|
|
249
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-canonical-requires-'))
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
createStandaloneFixture(appDir)
|
|
253
|
+
const packageDir = path.join(appDir, 'fixture-module-package')
|
|
254
|
+
fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })
|
|
255
|
+
const requirements = [
|
|
256
|
+
'@pkarw/marketing_consents@preview',
|
|
257
|
+
'npm:@pkarw/marketing_consents@1.0.0',
|
|
258
|
+
'github:pkarw/marketing-consents',
|
|
259
|
+
'npm:consent-helper@next',
|
|
260
|
+
'github:pkarw/consent-tools#main',
|
|
261
|
+
'pkarw/consent-tools',
|
|
262
|
+
'https://github.com/pkarw/consent-tools.git#release',
|
|
263
|
+
'ssh://git@github.com/pkarw/consent-tools.git#main',
|
|
264
|
+
'git@github.com:pkarw/consent-tools.git',
|
|
265
|
+
'github:pkarw/installed-tools',
|
|
266
|
+
'npm:@open-mercato/core@preview',
|
|
267
|
+
]
|
|
268
|
+
writeFile(
|
|
269
|
+
path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),
|
|
270
|
+
`export const metadata = { id: 'test_package', requires: ${JSON.stringify(requirements)}, ejectable: true }\n`,
|
|
271
|
+
)
|
|
272
|
+
const entries = [
|
|
273
|
+
{ id: 'marketing_consents', from: '@app', locator: 'github:pkarw/marketing-consents', packageName: '@pkarw/marketing_consents' },
|
|
274
|
+
{ id: 'npm_consents', from: '@app', locator: 'npm:@pkarw/marketing_consents', packageName: '@pkarw/marketing_consents' },
|
|
275
|
+
{ id: 'npm_core', from: '@app', locator: 'npm:@open-mercato/core', packageName: '@open-mercato/core' },
|
|
276
|
+
{ id: 'consent_helper', from: '@app', locator: 'npm:consent-helper' },
|
|
277
|
+
{ id: 'consent_tools', from: '@app', locator: 'github:pkarw/consent-tools' },
|
|
278
|
+
]
|
|
279
|
+
for (const entry of entries) {
|
|
280
|
+
writeFile(
|
|
281
|
+
path.join(appDir, 'src', 'modules', entry.id, 'index.ts'),
|
|
282
|
+
`export const metadata = { id: '${entry.id}' }\n`,
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
const corePackageDir = path.join(appDir, 'vendor', 'core')
|
|
286
|
+
writeFile(
|
|
287
|
+
path.join(corePackageDir, 'package.json'),
|
|
288
|
+
JSON.stringify({ name: '@open-mercato/core', version: '0.4.7', type: 'module', repository: { type: 'git', url: 'https://github.com/pkarw/installed-tools.git' } }),
|
|
289
|
+
)
|
|
290
|
+
writeFile(
|
|
291
|
+
path.join(corePackageDir, 'src', 'modules', 'repository_tools', 'index.ts'),
|
|
292
|
+
"export const metadata = { id: 'repository_tools' }\n",
|
|
293
|
+
)
|
|
294
|
+
writeFile(
|
|
295
|
+
path.join(corePackageDir, 'dist', 'modules', 'repository_tools', 'index.js'),
|
|
296
|
+
"export const metadata = { id: 'repository_tools' }\n",
|
|
297
|
+
)
|
|
298
|
+
const enabledEntries = [...entries, { id: 'repository_tools', from: '@open-mercato/core', locator: 'github:pkarw/installed-tools' }]
|
|
299
|
+
writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = ${JSON.stringify(enabledEntries)}\n`)
|
|
300
|
+
runCommand(yarnBinary(), ['install'], appDir)
|
|
301
|
+
|
|
302
|
+
runMercato(['module', 'add', 'npm:@open-mercato/test-package@file:./fixture-module-package'], appDir)
|
|
303
|
+
|
|
304
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("id: 'test_package'")
|
|
305
|
+
} finally {
|
|
306
|
+
fs.rmSync(appDir, { recursive: true, force: true })
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
test('same-name modules from different origins do not satisfy canonical requirements', () => {
|
|
311
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-wrong-origin-'))
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
createStandaloneFixture(appDir)
|
|
315
|
+
const packageDir = path.join(appDir, 'fixture-module-package')
|
|
316
|
+
fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })
|
|
317
|
+
writeFile(
|
|
318
|
+
path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),
|
|
319
|
+
"export const metadata = { id: 'test_package', requires: ['@pkarw/marketing_consents', 'github:pkarw/consent-tools'], ejectable: true }\n",
|
|
320
|
+
)
|
|
321
|
+
const modulesSource = `export const enabledModules = [
|
|
322
|
+
{ id: 'marketing_consents', from: '@app', locator: 'npm:@open-mercato/marketing_consents' },
|
|
323
|
+
{ id: 'consent_tools', from: '@app', locator: 'github:another-owner/consent-tools' },
|
|
324
|
+
]\n`
|
|
325
|
+
writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)
|
|
326
|
+
runCommand(yarnBinary(), ['install'], appDir)
|
|
327
|
+
|
|
328
|
+
expect(() => runMercato(
|
|
329
|
+
['module', 'add', '@open-mercato/test-package@file:./fixture-module-package', '--eject'],
|
|
330
|
+
appDir,
|
|
331
|
+
)).toThrow(/@pkarw\/marketing_consents[\s\S]*github:pkarw\/consent-tools[\s\S]*npx create-mercato-module install/)
|
|
332
|
+
|
|
333
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)
|
|
334
|
+
expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package'))).toBe(false)
|
|
335
|
+
} finally {
|
|
336
|
+
fs.rmSync(appDir, { recursive: true, force: true })
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
test('module add rejects a same-ID source collision before ejecting', () => {
|
|
341
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-module-collision-'))
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
createStandaloneFixture(appDir)
|
|
345
|
+
const modulesSource = "export const enabledModules = [{ id: 'test_package', from: '@app', locator: 'github:another-owner/test-package' }]\n"
|
|
346
|
+
const localSource = "export const metadata = { id: 'test_package', locator: 'github:another-owner/test-package' }\n"
|
|
347
|
+
writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)
|
|
348
|
+
writeFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'), localSource)
|
|
349
|
+
runCommand(yarnBinary(), ['install'], appDir)
|
|
350
|
+
|
|
351
|
+
expect(() => runMercato(
|
|
352
|
+
['module', 'add', `@open-mercato/test-package@file:${fixtureModulePackage}`, '--eject'],
|
|
353
|
+
appDir,
|
|
354
|
+
)).toThrow(/(?=[\s\S]*test_package)(?=[\s\S]*(?:collision|already|conflict))(?=[\s\S]*another-owner)(?=[\s\S]*@open-mercato\/test-package)/i)
|
|
355
|
+
|
|
356
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)
|
|
357
|
+
expect(readFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(localSource)
|
|
358
|
+
} finally {
|
|
359
|
+
fs.rmSync(appDir, { recursive: true, force: true })
|
|
360
|
+
}
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
test('GitHub locators detect a runtime ID collision before invoking Yarn', () => {
|
|
364
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-github-collision-'))
|
|
365
|
+
try {
|
|
366
|
+
createStandaloneFixture(appDir)
|
|
367
|
+
const modulesSource = "export const enabledModules = [{ id: 'test_package', from: '@app', locator: 'github:other/test-package' }]\n"
|
|
368
|
+
writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)
|
|
369
|
+
const originalManifest = readFile(path.join(appDir, 'package.json'))
|
|
370
|
+
const executableDir = path.join(appDir, 'bin')
|
|
371
|
+
const packageManifest = Buffer.from(JSON.stringify({ name: '@pkarw/test-package' })).toString('base64')
|
|
372
|
+
const ghPath = path.join(executableDir, 'gh')
|
|
373
|
+
writeFile(ghPath, `#!/usr/bin/env node
|
|
374
|
+
const endpoint = process.argv[3]
|
|
375
|
+
const sha = 'a'.repeat(40)
|
|
376
|
+
const value = endpoint === 'user' ? { login: 'pkarw' }
|
|
377
|
+
: endpoint.includes('/commits/') ? { sha }
|
|
378
|
+
: endpoint.includes('/contents/') ? { encoding: 'base64', content: ${JSON.stringify(packageManifest)} }
|
|
379
|
+
: endpoint.includes('/git/trees/') ? { tree: [{ path: 'src/modules/test_package/index.ts' }] }
|
|
380
|
+
: { default_branch: 'main' }
|
|
381
|
+
process.stdout.write(JSON.stringify(value))
|
|
382
|
+
`)
|
|
383
|
+
const yarnPath = path.join(executableDir, 'yarn')
|
|
384
|
+
const marker = path.join(appDir, 'yarn-invoked')
|
|
385
|
+
writeFile(yarnPath, "#!/usr/bin/env node\nrequire('node:fs').writeFileSync(process.env.COLLISION_YARN_MARKER, 'invoked')\nprocess.exit(1)\n")
|
|
386
|
+
fs.chmodSync(ghPath, 0o755)
|
|
387
|
+
fs.chmodSync(yarnPath, 0o755)
|
|
388
|
+
for (const locator of ['github:pkarw/test-package', 'https://github.com/pkarw/test-package.git', 'git@github.com:pkarw/test-package.git', 'github:test-package']) {
|
|
389
|
+
expect(() => runCommand(process.execPath, [cliBin, 'module', 'add', locator, '--allow-third-party'], appDir, {
|
|
390
|
+
PATH: executableDir + path.delimiter + process.env.PATH,
|
|
391
|
+
COLLISION_YARN_MARKER: marker,
|
|
392
|
+
})).toThrow(/Module name collision[\s\S]*test_package[\s\S]*github:other\/test-package[\s\S]*github:pkarw\/test-package/)
|
|
393
|
+
}
|
|
394
|
+
expect(fs.existsSync(marker)).toBe(false)
|
|
395
|
+
expect(readFile(path.join(appDir, 'package.json'))).toBe(originalManifest)
|
|
396
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)
|
|
397
|
+
expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package'))).toBe(false)
|
|
398
|
+
} finally {
|
|
399
|
+
fs.rmSync(appDir, { recursive: true, force: true })
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
|
|
207
403
|
test('module enable supports package-backed and ejected flows plus both eject entrypoints', () => {
|
|
208
404
|
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-eject-'))
|
|
209
405
|
|
|
@@ -218,25 +414,29 @@ test.describe('TC-INT-007: CLI official module install and eject flows', () => {
|
|
|
218
414
|
|
|
219
415
|
runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)
|
|
220
416
|
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(
|
|
221
|
-
"
|
|
417
|
+
"id: 'test_package', from: '@open-mercato/test-package'",
|
|
222
418
|
)
|
|
223
419
|
|
|
224
420
|
writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\n')
|
|
225
421
|
fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })
|
|
226
422
|
runMercato(['module', 'enable', '@open-mercato/test-package', '--eject'], appDir)
|
|
227
|
-
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("
|
|
423
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("id: 'test_package', from: '@app'")
|
|
228
424
|
expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)
|
|
229
425
|
expect(readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))).toBe('')
|
|
230
426
|
|
|
231
427
|
writeFile(path.join(appDir, 'src', 'modules.ts'), "export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\n")
|
|
232
428
|
fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })
|
|
233
429
|
runMercato(['module', 'eject', 'test_package'], appDir)
|
|
234
|
-
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("
|
|
430
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("packageName: '@open-mercato/test-package'")
|
|
431
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).not.toContain("locator: 'npm:@open-mercato/test-package'")
|
|
432
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("id: 'test_package', from: '@app'")
|
|
235
433
|
|
|
236
434
|
writeFile(path.join(appDir, 'src', 'modules.ts'), "export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\n")
|
|
237
435
|
fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })
|
|
238
436
|
runMercato(['eject', 'test_package'], appDir)
|
|
239
|
-
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("
|
|
437
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("packageName: '@open-mercato/test-package'")
|
|
438
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).not.toContain("locator: 'npm:@open-mercato/test-package'")
|
|
439
|
+
expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain("id: 'test_package', from: '@app'")
|
|
240
440
|
} finally {
|
|
241
441
|
fs.rmSync(appDir, { recursive: true, force: true })
|
|
242
442
|
}
|