@open-mercato/cli 0.10.1-develop.7983.1.fd91207efe → 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/__integration__/TC-INT-007.spec.ts"],
|
|
4
|
-
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliBin = path.join(repoRoot, 'packages', 'cli', 'dist', 'bin.js')\nconst fixtureModulePackage = path.join(\n repoRoot,\n 'packages',\n 'cli',\n 'src',\n 'lib',\n '__fixtures__',\n 'official-module-package',\n)\n\nfunction yarnBinary(): string {\n return process.platform === 'win32' ? 'yarn.cmd' : 'yarn'\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): string {\n const yarnCacheFolder = path.join(cwd, '.yarn', 'cache')\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n YARN_CACHE_FOLDER: yarnCacheFolder,\n YARN_ENABLE_GLOBAL_CACHE: '0',\n YARN_ENABLE_IMMUTABLE_INSTALLS: '0',\n YARN_NODE_LINKER: 'node-modules',\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction createCoreWorkspacePackage(rootDir: string, relativeDir: string): string {\n const coreDir = path.join(rootDir, relativeDir)\n writeFile(\n path.join(coreDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/core',\n version: '0.4.7',\n type: 'module',\n },\n null,\n 2,\n ),\n )\n return coreDir\n}\n\nconst commentedModulesSource = [\n '// Central place to enable modules.',\n 'export const enabledModules = [',\n ' // customer_groups stays disabled by default.',\n \" // { id: 'customer_groups', from: '@open-mercato/core' },\",\n '',\n ' /* Block comment kept by module add. */',\n ']',\n '',\n].join('\\n')\n\nfunction createMonorepoFixture(rootDir: string): string {\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-monorepo-fixture',\n private: true,\n workspaces: ['apps/*', 'packages/*'],\n },\n null,\n 2,\n ),\n )\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('packages', 'core'))\n\n const appDir = path.join(rootDir, 'apps', 'mercato')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/app',\n version: '0.0.0',\n private: true,\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(appDir, 'src', 'modules.ts'), commentedModulesSource)\n return appDir\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('vendor', 'core'))\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-standalone-fixture',\n private: true,\n dependencies: {\n '@open-mercato/core': 'file:./vendor/core',\n },\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(rootDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n return rootDir\n}\n\nfunction readFile(filePath: string): string {\n return fs.readFileSync(filePath, 'utf8')\n}\n\ntest.describe('TC-INT-007: CLI official module install and eject flows', () => {\n test('module add installs and registers a package-backed module in a monorepo app', () => {\n const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-monorepo-'))\n\n try {\n const appDir = createMonorepoFixture(rootDir)\n runCommand(yarnBinary(), ['install'], rootDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n ],\n rootDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n const appPackageJson = JSON.parse(readFile(path.join(appDir, 'package.json'))) as {\n dependencies?: Record<string, string>\n }\n\n expect(modulesSource).toBe(\n commentedModulesSource.replace(\n ' /* Block comment kept by module add. */\\n',\n \" /* Block comment kept by module add. */\\n { id: 'test_package', from: '@open-mercato/test-package' },\\n\",\n ),\n )\n expect(cssSource).toContain('node_modules/@open-mercato/test-package/src/**/*.{ts,tsx}')\n expect(appPackageJson.dependencies?.['@open-mercato/test-package']).toBeTruthy()\n } finally {\n fs.rmSync(rootDir, { recursive: true, force: true })\n }\n })\n\n test('module add --eject copies module source and omits package CSS entries', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-source-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n '--eject',\n ],\n appDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n\n expect(modulesSource).toContain(\"{ id: 'test_package', from: '@app' }\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(cssSource).toBe('')\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module enable supports package-backed and ejected flows plus both eject entrypoints', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-eject-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n runCommand(\n yarnBinary(),\n ['add', `@open-mercato/test-package@file:${fixtureModulePackage}`],\n appDir,\n )\n\n runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\n \"{ id: 'test_package', from: '@open-mercato/test-package' }\",\n )\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'enable', '@open-mercato/test-package', '--eject'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))).toBe('')\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module add and module enable exit 0 without changes when the module is already enabled', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-rerun-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n const packageSpec = `@open-mercato/test-package@file:${fixtureModulePackage}`\n\n runMercato(['module', 'add', packageSpec], appDir)\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n\n const addOutput = runMercato(['module', 'add', packageSpec], appDir)\n const enableOutput = runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)\n\n expect(addOutput).toContain('is already enabled in modules.ts. Nothing to change.')\n expect(enableOutput).toContain('is already enabled in modules.ts. Nothing to change.')\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliBin = path.join(repoRoot, 'packages', 'cli', 'dist', 'bin.js')\nconst fixtureModulePackage = path.join(\n repoRoot,\n 'packages',\n 'cli',\n 'src',\n 'lib',\n '__fixtures__',\n 'official-module-package',\n)\n\nfunction yarnBinary(): string {\n return process.platform === 'win32' ? 'yarn.cmd' : 'yarn'\n}\n\nfunction runCommand(command: string, args: string[], cwd: string, environment: NodeJS.ProcessEnv = {}): string {\n const yarnCacheFolder = path.join(cwd, '.yarn', 'cache')\n try {\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n YARN_CACHE_FOLDER: yarnCacheFolder,\n YARN_ENABLE_GLOBAL_CACHE: '0',\n YARN_ENABLE_IMMUTABLE_INSTALLS: '0',\n YARN_NODE_LINKER: 'node-modules',\n ...environment,\n },\n })\n } catch (error) {\n if (!error || typeof error !== 'object') throw error\n const errorRecord = error as Record<string, unknown>\n const outputs = ['stdout', 'stderr'].flatMap((streamName) => {\n const output = errorRecord[streamName]\n return typeof output === 'string' || Buffer.isBuffer(output) ? [output.toString().trim()] : []\n }).filter(Boolean)\n const message = error instanceof Error ? error.message : String(error)\n throw new Error(outputs.length > 0 ? `${message}\\n${outputs.join('\\n')}` : message)\n }\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction createCoreWorkspacePackage(rootDir: string, relativeDir: string): string {\n const coreDir = path.join(rootDir, relativeDir)\n writeFile(\n path.join(coreDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/core',\n version: '0.4.7',\n type: 'module',\n },\n null,\n 2,\n ),\n )\n return coreDir\n}\n\nconst commentedModulesSource = [\n '// Central place to enable modules.',\n 'export const enabledModules = [',\n ' // customer_groups stays disabled by default.',\n \" // { id: 'customer_groups', from: '@open-mercato/core' },\",\n '',\n ' /* Block comment kept by module add. */',\n ']',\n '',\n].join('\\n')\n\nfunction createMonorepoFixture(rootDir: string): string {\n writeFile(path.join(rootDir, 'yarn.lock'), '')\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-monorepo-fixture',\n private: true,\n workspaces: ['apps/*', 'packages/*'],\n },\n null,\n 2,\n ),\n )\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('packages', 'core'))\n\n const appDir = path.join(rootDir, 'apps', 'mercato')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/app',\n version: '0.0.0',\n private: true,\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(appDir, 'src', 'modules.ts'), commentedModulesSource)\n return appDir\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n writeFile(path.join(rootDir, 'yarn.lock'), '')\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('vendor', 'core'))\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-standalone-fixture',\n private: true,\n dependencies: {\n '@open-mercato/core': 'file:./vendor/core',\n },\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(rootDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n return rootDir\n}\n\nfunction readFile(filePath: string): string {\n return fs.readFileSync(filePath, 'utf8')\n}\n\ntest.describe('TC-INT-007: CLI official module install and eject flows', () => {\n test('module add installs and registers a package-backed module in a monorepo app', () => {\n const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-monorepo-'))\n\n try {\n const appDir = createMonorepoFixture(rootDir)\n runCommand(yarnBinary(), ['install'], rootDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n ],\n rootDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n const appPackageJson = JSON.parse(readFile(path.join(appDir, 'package.json'))) as {\n dependencies?: Record<string, string>\n }\n\n expect(modulesSource).toBe(\n commentedModulesSource.replace(\n ' /* Block comment kept by module add. */\\n',\n \" /* Block comment kept by module add. */\\n { id: 'test_package', from: '@open-mercato/test-package' },\\n\",\n ),\n )\n expect(cssSource).toContain('node_modules/@open-mercato/test-package/src/**/*.{ts,tsx}')\n expect(appPackageJson.dependencies?.['@open-mercato/test-package']).toBeTruthy()\n } finally {\n fs.rmSync(rootDir, { recursive: true, force: true })\n }\n })\n\n test('module add --eject copies module source and omits package CSS entries', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-source-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n '--eject',\n ],\n appDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n\n expect(modulesSource).toMatch(/id: 'test_package', from: '@app'/)\n expect(modulesSource).not.toContain('locator:')\n expect(modulesSource).toContain(\"packageName: '@open-mercato/test-package'\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(readFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(readFile(path.join(fixtureModulePackage, 'src', 'modules', 'test_package', 'index.ts')))\n expect(cssSource).toBe('')\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module add reports dependencies that must be enabled before registration', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-dependencies-'))\n\n try {\n createStandaloneFixture(appDir)\n const packageDir = path.join(appDir, 'fixture-module-package')\n fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })\n writeFile(\n path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),\n \"export const metadata = { id: 'test_package', requires: ['customers'], ejectable: true }\\n\",\n )\n runCommand(yarnBinary(), ['install'], appDir)\n\n expect(() => runMercato(\n ['module', 'add', '@open-mercato/test-package@file:./fixture-module-package'],\n appDir,\n )).toThrow(/requires module\\(s\\) that are not enabled: customers/)\n\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe('export const enabledModules = []\\n')\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module add resolves canonical requirements from retained ejected origins', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-canonical-requires-'))\n\n try {\n createStandaloneFixture(appDir)\n const packageDir = path.join(appDir, 'fixture-module-package')\n fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })\n const requirements = [\n '@pkarw/marketing_consents@preview',\n 'npm:@pkarw/marketing_consents@1.0.0',\n 'github:pkarw/marketing-consents',\n 'npm:consent-helper@next',\n 'github:pkarw/consent-tools#main',\n 'pkarw/consent-tools',\n 'https://github.com/pkarw/consent-tools.git#release',\n 'ssh://git@github.com/pkarw/consent-tools.git#main',\n 'git@github.com:pkarw/consent-tools.git',\n 'github:pkarw/installed-tools',\n 'npm:@open-mercato/core@preview',\n ]\n writeFile(\n path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),\n `export const metadata = { id: 'test_package', requires: ${JSON.stringify(requirements)}, ejectable: true }\\n`,\n )\n const entries = [\n { id: 'marketing_consents', from: '@app', locator: 'github:pkarw/marketing-consents', packageName: '@pkarw/marketing_consents' },\n { id: 'npm_consents', from: '@app', locator: 'npm:@pkarw/marketing_consents', packageName: '@pkarw/marketing_consents' },\n { id: 'npm_core', from: '@app', locator: 'npm:@open-mercato/core', packageName: '@open-mercato/core' },\n { id: 'consent_helper', from: '@app', locator: 'npm:consent-helper' },\n { id: 'consent_tools', from: '@app', locator: 'github:pkarw/consent-tools' },\n ]\n for (const entry of entries) {\n writeFile(\n path.join(appDir, 'src', 'modules', entry.id, 'index.ts'),\n `export const metadata = { id: '${entry.id}' }\\n`,\n )\n }\n const corePackageDir = path.join(appDir, 'vendor', 'core')\n writeFile(\n path.join(corePackageDir, 'package.json'),\n JSON.stringify({ name: '@open-mercato/core', version: '0.4.7', type: 'module', repository: { type: 'git', url: 'https://github.com/pkarw/installed-tools.git' } }),\n )\n writeFile(\n path.join(corePackageDir, 'src', 'modules', 'repository_tools', 'index.ts'),\n \"export const metadata = { id: 'repository_tools' }\\n\",\n )\n writeFile(\n path.join(corePackageDir, 'dist', 'modules', 'repository_tools', 'index.js'),\n \"export const metadata = { id: 'repository_tools' }\\n\",\n )\n const enabledEntries = [...entries, { id: 'repository_tools', from: '@open-mercato/core', locator: 'github:pkarw/installed-tools' }]\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = ${JSON.stringify(enabledEntries)}\\n`)\n runCommand(yarnBinary(), ['install'], appDir)\n\n runMercato(['module', 'add', 'npm:@open-mercato/test-package@file:./fixture-module-package'], appDir)\n\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"id: 'test_package'\")\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('same-name modules from different origins do not satisfy canonical requirements', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-wrong-origin-'))\n\n try {\n createStandaloneFixture(appDir)\n const packageDir = path.join(appDir, 'fixture-module-package')\n fs.cpSync(fixtureModulePackage, packageDir, { recursive: true })\n writeFile(\n path.join(packageDir, 'src', 'modules', 'test_package', 'index.ts'),\n \"export const metadata = { id: 'test_package', requires: ['@pkarw/marketing_consents', 'github:pkarw/consent-tools'], ejectable: true }\\n\",\n )\n const modulesSource = `export const enabledModules = [\n { id: 'marketing_consents', from: '@app', locator: 'npm:@open-mercato/marketing_consents' },\n { id: 'consent_tools', from: '@app', locator: 'github:another-owner/consent-tools' },\n ]\\n`\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n runCommand(yarnBinary(), ['install'], appDir)\n\n expect(() => runMercato(\n ['module', 'add', '@open-mercato/test-package@file:./fixture-module-package', '--eject'],\n appDir,\n )).toThrow(/@pkarw\\/marketing_consents[\\s\\S]*github:pkarw\\/consent-tools[\\s\\S]*npx create-mercato-module install/)\n\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package'))).toBe(false)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module add rejects a same-ID source collision before ejecting', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-module-collision-'))\n\n try {\n createStandaloneFixture(appDir)\n const modulesSource = \"export const enabledModules = [{ id: 'test_package', from: '@app', locator: 'github:another-owner/test-package' }]\\n\"\n const localSource = \"export const metadata = { id: 'test_package', locator: 'github:another-owner/test-package' }\\n\"\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n writeFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'), localSource)\n runCommand(yarnBinary(), ['install'], appDir)\n\n expect(() => runMercato(\n ['module', 'add', `@open-mercato/test-package@file:${fixtureModulePackage}`, '--eject'],\n appDir,\n )).toThrow(/(?=[\\s\\S]*test_package)(?=[\\s\\S]*(?:collision|already|conflict))(?=[\\s\\S]*another-owner)(?=[\\s\\S]*@open-mercato\\/test-package)/i)\n\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)\n expect(readFile(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(localSource)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('GitHub locators detect a runtime ID collision before invoking Yarn', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-github-collision-'))\n try {\n createStandaloneFixture(appDir)\n const modulesSource = \"export const enabledModules = [{ id: 'test_package', from: '@app', locator: 'github:other/test-package' }]\\n\"\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n const originalManifest = readFile(path.join(appDir, 'package.json'))\n const executableDir = path.join(appDir, 'bin')\n const packageManifest = Buffer.from(JSON.stringify({ name: '@pkarw/test-package' })).toString('base64')\n const ghPath = path.join(executableDir, 'gh')\n writeFile(ghPath, `#!/usr/bin/env node\nconst endpoint = process.argv[3]\nconst sha = 'a'.repeat(40)\nconst value = endpoint === 'user' ? { login: 'pkarw' }\n : endpoint.includes('/commits/') ? { sha }\n : endpoint.includes('/contents/') ? { encoding: 'base64', content: ${JSON.stringify(packageManifest)} }\n : endpoint.includes('/git/trees/') ? { tree: [{ path: 'src/modules/test_package/index.ts' }] }\n : { default_branch: 'main' }\nprocess.stdout.write(JSON.stringify(value))\n`)\n const yarnPath = path.join(executableDir, 'yarn')\n const marker = path.join(appDir, 'yarn-invoked')\n writeFile(yarnPath, \"#!/usr/bin/env node\\nrequire('node:fs').writeFileSync(process.env.COLLISION_YARN_MARKER, 'invoked')\\nprocess.exit(1)\\n\")\n fs.chmodSync(ghPath, 0o755)\n fs.chmodSync(yarnPath, 0o755)\n 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']) {\n expect(() => runCommand(process.execPath, [cliBin, 'module', 'add', locator, '--allow-third-party'], appDir, {\n PATH: executableDir + path.delimiter + process.env.PATH,\n COLLISION_YARN_MARKER: marker,\n })).toThrow(/Module name collision[\\s\\S]*test_package[\\s\\S]*github:other\\/test-package[\\s\\S]*github:pkarw\\/test-package/)\n }\n expect(fs.existsSync(marker)).toBe(false)\n expect(readFile(path.join(appDir, 'package.json'))).toBe(originalManifest)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package'))).toBe(false)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module enable supports package-backed and ejected flows plus both eject entrypoints', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-eject-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n runCommand(\n yarnBinary(),\n ['add', `@open-mercato/test-package@file:${fixtureModulePackage}`],\n appDir,\n )\n\n runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\n \"id: 'test_package', from: '@open-mercato/test-package'\",\n )\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'enable', '@open-mercato/test-package', '--eject'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"id: 'test_package', from: '@app'\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))).toBe('')\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"packageName: '@open-mercato/test-package'\")\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).not.toContain(\"locator: 'npm:@open-mercato/test-package'\")\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"id: 'test_package', from: '@app'\")\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"packageName: '@open-mercato/test-package'\")\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).not.toContain(\"locator: 'npm:@open-mercato/test-package'\")\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"id: 'test_package', from: '@app'\")\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module add and module enable exit 0 without changes when the module is already enabled', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-rerun-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n const packageSpec = `@open-mercato/test-package@file:${fixtureModulePackage}`\n\n runMercato(['module', 'add', packageSpec], appDir)\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n\n const addOutput = runMercato(['module', 'add', packageSpec], appDir)\n const enableOutput = runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)\n\n expect(addOutput).toContain('is already enabled in modules.ts. Nothing to change.')\n expect(enableOutput).toContain('is already enabled in modules.ts. Nothing to change.')\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toBe(modulesSource)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..", "..");
|
|
8
|
+
const cliBin = path.join(repoRoot, "packages", "cli", "dist", "bin.js");
|
|
9
|
+
function writeFile(filePath, content) {
|
|
10
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
11
|
+
fs.writeFileSync(filePath, content);
|
|
12
|
+
}
|
|
13
|
+
function createPackage(packageRoot, packageName, moduleIds) {
|
|
14
|
+
writeFile(path.join(packageRoot, "package.json"), JSON.stringify({ name: packageName, version: "0.4.7", type: "module" }));
|
|
15
|
+
for (const moduleId of moduleIds) {
|
|
16
|
+
writeFile(path.join(packageRoot, "src", "modules", moduleId, "index.ts"), `export const metadata = { id: '${moduleId}', title: '${moduleId}', ejectable: true }
|
|
17
|
+
`);
|
|
18
|
+
writeFile(path.join(packageRoot, "dist", "modules", moduleId, "index.js"), `export const metadata = { id: '${moduleId}', title: '${moduleId}', ejectable: true }
|
|
19
|
+
`);
|
|
20
|
+
writeFile(path.join(packageRoot, "src", "modules", moduleId, "di.ts"), "export function register() {}\n");
|
|
21
|
+
writeFile(path.join(packageRoot, "dist", "modules", moduleId, "di.js"), "export function register() {}\n");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function createApp(appDir, dependencies = {}) {
|
|
25
|
+
writeFile(path.join(appDir, "package.json"), JSON.stringify({ name: "module-collision-integration", private: true, dependencies: { "@open-mercato/core": "0.4.7", ...dependencies } }));
|
|
26
|
+
writeFile(path.join(appDir, "yarn.lock"), "");
|
|
27
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = []\n");
|
|
28
|
+
createPackage(path.join(appDir, "node_modules", "@open-mercato", "core"), "@open-mercato/core", []);
|
|
29
|
+
}
|
|
30
|
+
function runMercato(args, appDir, environment = {}) {
|
|
31
|
+
const result = spawnSync(process.execPath, [cliBin, ...args], {
|
|
32
|
+
cwd: appDir,
|
|
33
|
+
encoding: "utf8",
|
|
34
|
+
env: { ...process.env, FORCE_COLOR: "0", NODE_NO_WARNINGS: "1", ...environment }
|
|
35
|
+
});
|
|
36
|
+
if (result.error) throw result.error;
|
|
37
|
+
return { status: result.status, output: `${result.stdout}
|
|
38
|
+
${result.stderr}` };
|
|
39
|
+
}
|
|
40
|
+
function installCommandStubs(appDir, candidateName, candidateModuleId) {
|
|
41
|
+
const executableDir = path.join(appDir, "bin");
|
|
42
|
+
const marker = path.join(appDir, "yarn-invoked");
|
|
43
|
+
const yarnPath = path.join(executableDir, process.platform === "win32" ? "yarn.cmd" : "yarn");
|
|
44
|
+
const yarnScript = `require('node:fs').writeFileSync(${JSON.stringify(marker)}, 'invoked'); process.exit(1)
|
|
45
|
+
`;
|
|
46
|
+
writeFile(yarnPath, process.platform === "win32" ? `@"${process.execPath}" "%~dp0yarn-stub.cjs" %*\r
|
|
47
|
+
` : `#!${process.execPath}
|
|
48
|
+
${yarnScript}`);
|
|
49
|
+
writeFile(path.join(executableDir, "yarn-stub.cjs"), yarnScript);
|
|
50
|
+
fs.chmodSync(yarnPath, 493);
|
|
51
|
+
if (candidateName && candidateModuleId) {
|
|
52
|
+
const manifest = Buffer.from(JSON.stringify({ name: candidateName })).toString("base64");
|
|
53
|
+
const ghScript = `const endpoint = process.argv[3] || ''
|
|
54
|
+
const value = endpoint === 'user' ? { login: 'candidate' }
|
|
55
|
+
: endpoint.includes('/commits/') ? { sha: 'a'.repeat(40) }
|
|
56
|
+
: endpoint.includes('/contents/') ? { encoding: 'base64', content: ${JSON.stringify(manifest)} }
|
|
57
|
+
: endpoint.includes('/git/trees/') ? { tree: [{ path: 'src/modules/${candidateModuleId}/index.ts' }, { path: 'dist/modules/${candidateModuleId}/index.js' }] }
|
|
58
|
+
: { default_branch: 'main' }
|
|
59
|
+
process.stdout.write(JSON.stringify(value))
|
|
60
|
+
`;
|
|
61
|
+
const ghPath = path.join(executableDir, process.platform === "win32" ? "gh.cmd" : "gh");
|
|
62
|
+
writeFile(ghPath, process.platform === "win32" ? `@"${process.execPath}" "%~dp0gh-stub.cjs" %*\r
|
|
63
|
+
` : `#!${process.execPath}
|
|
64
|
+
${ghScript}`);
|
|
65
|
+
writeFile(path.join(executableDir, "gh-stub.cjs"), ghScript);
|
|
66
|
+
fs.chmodSync(ghPath, 493);
|
|
67
|
+
}
|
|
68
|
+
return { PATH: executableDir + path.delimiter + process.env.PATH };
|
|
69
|
+
}
|
|
70
|
+
function snapshotDirectory(directory) {
|
|
71
|
+
if (!fs.existsSync(directory)) return {};
|
|
72
|
+
const files = {};
|
|
73
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
74
|
+
const fullPath = path.join(directory, entry.name);
|
|
75
|
+
if (entry.isDirectory()) {
|
|
76
|
+
for (const [relativePath, content] of Object.entries(snapshotDirectory(fullPath))) files[path.join(entry.name, relativePath)] = content;
|
|
77
|
+
} else {
|
|
78
|
+
files[entry.name] = fs.readFileSync(fullPath).toString("base64");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return files;
|
|
82
|
+
}
|
|
83
|
+
test.describe("TC-INT-009: CLI source collision lifecycle safeguards", () => {
|
|
84
|
+
for (const kind of ["directory", "archive"]) {
|
|
85
|
+
test(`rejects a local ${kind} with unknown provenance before replacing an active npm binding`, () => {
|
|
86
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-file-origin-"));
|
|
87
|
+
const appDir = path.join(root, "app");
|
|
88
|
+
try {
|
|
89
|
+
const binding = "@publisher/consents";
|
|
90
|
+
createApp(appDir, { [binding]: "0.4.7" });
|
|
91
|
+
createPackage(path.join(appDir, "node_modules", binding), binding, ["consents"]);
|
|
92
|
+
const packageRoot = path.join(root, "package");
|
|
93
|
+
createPackage(packageRoot, binding, ["consents"]);
|
|
94
|
+
if (kind === "archive") execFileSync("tar", ["-czf", path.join(root, "candidate.tgz"), "-C", root, "package"]);
|
|
95
|
+
const modulesSource = `export const enabledModules = [{ id: 'consents', from: '${binding}', locator: 'npm:${binding}' }]
|
|
96
|
+
`;
|
|
97
|
+
writeFile(path.join(appDir, "src", "modules.ts"), modulesSource);
|
|
98
|
+
const manifestBefore = fs.readFileSync(path.join(appDir, "package.json"), "utf8");
|
|
99
|
+
const installedBefore = snapshotDirectory(path.join(appDir, "node_modules"));
|
|
100
|
+
const environment = installCommandStubs(appDir);
|
|
101
|
+
const locator = kind === "archive" ? "file:../candidate.tgz" : "file:../package";
|
|
102
|
+
const result = runMercato(["module", "add", `${binding}@${locator}`, "--eject", "--allow-third-party"], appDir, environment);
|
|
103
|
+
expect(result.status, result.output).not.toBe(0);
|
|
104
|
+
expect(result.output).toContain("Package binding collision");
|
|
105
|
+
expect(result.output).toContain("unknown origin");
|
|
106
|
+
expect(result.output).toContain("consents");
|
|
107
|
+
expect(fs.existsSync(path.join(appDir, "yarn-invoked"))).toBe(false);
|
|
108
|
+
expect(fs.readFileSync(path.join(appDir, "src", "modules.ts"), "utf8")).toBe(modulesSource);
|
|
109
|
+
expect(fs.readFileSync(path.join(appDir, "package.json"), "utf8")).toBe(manifestBefore);
|
|
110
|
+
expect(snapshotDirectory(path.join(appDir, "node_modules"))).toEqual(installedBefore);
|
|
111
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "consents"))).toBe(false);
|
|
112
|
+
expect(fs.existsSync(path.join(appDir, ".mercato", "generated"))).toBe(false);
|
|
113
|
+
} finally {
|
|
114
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
test("rejects a GitHub replacement of an active binding even when the selected module ID differs", () => {
|
|
119
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-binding-collision-"));
|
|
120
|
+
try {
|
|
121
|
+
const binding = "@publisher/shared-package";
|
|
122
|
+
createApp(appDir, { [binding]: "github:existing/provider#main" });
|
|
123
|
+
createPackage(path.join(appDir, "node_modules", binding), binding, ["active_module"]);
|
|
124
|
+
const modulesSource = `export const enabledModules = [{ id: 'active_module', from: '${binding}', locator: 'github:existing/provider', packageName: '${binding}' }]
|
|
125
|
+
`;
|
|
126
|
+
writeFile(path.join(appDir, "src", "modules.ts"), modulesSource);
|
|
127
|
+
const manifestBefore = fs.readFileSync(path.join(appDir, "package.json"), "utf8");
|
|
128
|
+
const environment = installCommandStubs(appDir, binding, "candidate_module");
|
|
129
|
+
const result = runMercato(["module", "add", "github:candidate/provider", "--allow-third-party"], appDir, environment);
|
|
130
|
+
expect(result.status, result.output).not.toBe(0);
|
|
131
|
+
expect(result.output).toContain("active_module");
|
|
132
|
+
expect(result.output).toContain(binding);
|
|
133
|
+
expect(result.output).toContain("github:existing/provider");
|
|
134
|
+
expect(result.output).toContain("github:candidate/provider");
|
|
135
|
+
expect(fs.existsSync(path.join(appDir, "yarn-invoked"))).toBe(false);
|
|
136
|
+
expect(fs.readFileSync(path.join(appDir, "src", "modules.ts"), "utf8")).toBe(modulesSource);
|
|
137
|
+
expect(fs.readFileSync(path.join(appDir, "package.json"), "utf8")).toBe(manifestBefore);
|
|
138
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "candidate_module"))).toBe(false);
|
|
139
|
+
} finally {
|
|
140
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
test("rejects an npm file package runtime ID collision before invoking Yarn or copying sources", () => {
|
|
144
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-file-collision-"));
|
|
145
|
+
try {
|
|
146
|
+
createApp(appDir);
|
|
147
|
+
const candidateDir = path.join(appDir, "candidate");
|
|
148
|
+
createPackage(candidateDir, "@publisher/candidate", ["consents"]);
|
|
149
|
+
const modulesSource = "export const enabledModules = [{ id: 'consents', from: '@app', locator: 'github:existing/consents' }]\n";
|
|
150
|
+
writeFile(path.join(appDir, "src", "modules.ts"), modulesSource);
|
|
151
|
+
writeFile(path.join(appDir, "src", "modules", "consents", "index.ts"), "export const metadata = { ejectable: true }\n");
|
|
152
|
+
const sourceBefore = snapshotDirectory(path.join(appDir, "src"));
|
|
153
|
+
const manifestBefore = fs.readFileSync(path.join(appDir, "package.json"), "utf8");
|
|
154
|
+
const result = runMercato(["module", "add", "@publisher/candidate@file:./candidate", "--allow-third-party", "--eject"], appDir, installCommandStubs(appDir));
|
|
155
|
+
expect(result.status, result.output).not.toBe(0);
|
|
156
|
+
expect(result.output).toContain("consents");
|
|
157
|
+
expect(result.output).toMatch(/collision|already registered|conflict/i);
|
|
158
|
+
expect(fs.existsSync(path.join(appDir, "yarn-invoked"))).toBe(false);
|
|
159
|
+
expect(snapshotDirectory(path.join(appDir, "src"))).toEqual(sourceBefore);
|
|
160
|
+
expect(fs.readFileSync(path.join(appDir, "package.json"), "utf8")).toBe(manifestBefore);
|
|
161
|
+
} finally {
|
|
162
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
test("every generate command rejects duplicate effective registrations before changing existing output", () => {
|
|
166
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-generate-duplicates-"));
|
|
167
|
+
try {
|
|
168
|
+
createApp(appDir);
|
|
169
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = [{ id: 'consents', from: '@app' }]\nif (process.env.COLLISION_DUPLICATE_ENABLED === 'true') enabledModules.push({ id: 'consents', from: '@app' })\n");
|
|
170
|
+
writeFile(path.join(appDir, "src", "modules", "consents", "index.ts"), "export const metadata = {}\n");
|
|
171
|
+
const outputDir = path.join(appDir, ".mercato", "generated");
|
|
172
|
+
for (const file of ["entities.ids.generated.ts", "modules.generated.ts", "entities.generated.ts", "di.generated.ts", "module-package-sources.css"]) writeFile(path.join(outputDir, file), "preserved output\n");
|
|
173
|
+
const before = snapshotDirectory(outputDir);
|
|
174
|
+
for (const command of ["all", "entity-ids", "registry", "entities", "di"]) {
|
|
175
|
+
const result = runMercato(["generate", command, "--quiet"], appDir, { COLLISION_DUPLICATE_ENABLED: "true" });
|
|
176
|
+
expect(result.status, `${command}: ${result.output}`).not.toBe(0);
|
|
177
|
+
expect(result.output).toContain("Duplicate enabled module ID 'consents'");
|
|
178
|
+
expect(snapshotDirectory(outputDir), command).toEqual(before);
|
|
179
|
+
}
|
|
180
|
+
const singleProvider = runMercato(["generate", "all", "--quiet"], appDir, { COLLISION_DUPLICATE_ENABLED: "false" });
|
|
181
|
+
expect(singleProvider.status, singleProvider.output).toBe(0);
|
|
182
|
+
} finally {
|
|
183
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
test("an installed alias generates binding imports, ejects with canonical provenance, and disables cleanly", () => {
|
|
187
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-alias-lifecycle-"));
|
|
188
|
+
try {
|
|
189
|
+
const binding = "consents_candidate";
|
|
190
|
+
const canonicalName = "@publisher/consents";
|
|
191
|
+
createApp(appDir, { [binding]: `npm:${canonicalName}@0.4.7` });
|
|
192
|
+
const packageRoot = path.join(appDir, "node_modules", binding);
|
|
193
|
+
createPackage(packageRoot, canonicalName, ["consents", "sibling"]);
|
|
194
|
+
writeFile(path.join(packageRoot, "src", "modules", "consents", "sibling.ts"), "export { metadata } from '../sibling'\n");
|
|
195
|
+
const enabled = runMercato(["module", "enable", binding, "--module", "consents", "--allow-third-party"], appDir);
|
|
196
|
+
expect(enabled.status, enabled.output).toBe(0);
|
|
197
|
+
const outputDir = path.join(appDir, ".mercato", "generated");
|
|
198
|
+
const modulesSource = fs.readFileSync(path.join(appDir, "src", "modules.ts"), "utf8");
|
|
199
|
+
expect(modulesSource).toContain(`from: '${binding}'`);
|
|
200
|
+
expect(modulesSource).toContain(`packageName: '${canonicalName}'`);
|
|
201
|
+
expect(fs.readFileSync(path.join(outputDir, "di.generated.ts"), "utf8")).toContain(`${binding}/modules/consents/di`);
|
|
202
|
+
expect(fs.readFileSync(path.join(outputDir, "module-package-sources.css"), "utf8")).toContain(`node_modules/${binding}/src/`);
|
|
203
|
+
const ejected = runMercato(["module", "eject", "consents"], appDir);
|
|
204
|
+
expect(ejected.status, ejected.output).toBe(0);
|
|
205
|
+
const ejectedSource = fs.readFileSync(path.join(appDir, "src", "modules.ts"), "utf8");
|
|
206
|
+
expect(ejectedSource).toContain("from: '@app'");
|
|
207
|
+
expect(ejectedSource).toContain(`packageName: '${canonicalName}'`);
|
|
208
|
+
expect(ejectedSource).toContain(`locator: 'npm:${canonicalName}'`);
|
|
209
|
+
expect(fs.readFileSync(path.join(appDir, "src", "modules", "consents", "sibling.ts"), "utf8")).toContain(`${binding}/modules/sibling`);
|
|
210
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = []\n");
|
|
211
|
+
const disabled = runMercato(["generate", "all", "--quiet"], appDir);
|
|
212
|
+
expect(disabled.status, disabled.output).toBe(0);
|
|
213
|
+
expect(fs.readFileSync(path.join(outputDir, "di.generated.ts"), "utf8")).not.toContain("consents");
|
|
214
|
+
expect(fs.readFileSync(path.join(outputDir, "module-package-sources.css"), "utf8")).toBe("");
|
|
215
|
+
expect(fs.existsSync(path.join(packageRoot, "package.json"))).toBe(true);
|
|
216
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "consents", "index.ts"))).toBe(true);
|
|
217
|
+
} finally {
|
|
218
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
test("missing alias exports fail enable and direct eject before source or config changes", () => {
|
|
222
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-alias-exports-"));
|
|
223
|
+
try {
|
|
224
|
+
const binding = "consents_candidate";
|
|
225
|
+
createApp(appDir, { [binding]: "npm:@publisher/consents@0.4.7" });
|
|
226
|
+
const packageRoot = path.join(appDir, "node_modules", binding);
|
|
227
|
+
createPackage(packageRoot, "@publisher/consents", ["consents"]);
|
|
228
|
+
writeFile(path.join(packageRoot, "package.json"), JSON.stringify({ name: "@publisher/consents", exports: { ".": "./dist/modules/consents/index.js" } }));
|
|
229
|
+
const configPath = path.join(appDir, "src", "modules.ts");
|
|
230
|
+
const emptyConfig = fs.readFileSync(configPath, "utf8");
|
|
231
|
+
const enabled = runMercato(["module", "enable", binding, "--module", "consents", "--eject", "--allow-third-party"], appDir);
|
|
232
|
+
expect(enabled.status, enabled.output).not.toBe(0);
|
|
233
|
+
expect(enabled.output).toContain(`${binding}/modules/consents/`);
|
|
234
|
+
expect(fs.readFileSync(configPath, "utf8")).toBe(emptyConfig);
|
|
235
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "consents"))).toBe(false);
|
|
236
|
+
const registeredConfig = `export const enabledModules = [{ id: 'consents', from: '${binding}' }]
|
|
237
|
+
`;
|
|
238
|
+
writeFile(configPath, registeredConfig);
|
|
239
|
+
const ejected = runMercato(["module", "eject", "consents"], appDir);
|
|
240
|
+
expect(ejected.status, ejected.output).not.toBe(0);
|
|
241
|
+
expect(ejected.output).toContain(`${binding}/modules/consents/`);
|
|
242
|
+
expect(fs.readFileSync(configPath, "utf8")).toBe(registeredConfig);
|
|
243
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "consents"))).toBe(false);
|
|
244
|
+
} finally {
|
|
245
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
test("a single package registration with a local overlay remains valid", () => {
|
|
249
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-single-overlay-"));
|
|
250
|
+
try {
|
|
251
|
+
const binding = "@publisher/consents";
|
|
252
|
+
createApp(appDir, { [binding]: "0.4.7" });
|
|
253
|
+
createPackage(path.join(appDir, "node_modules", binding), binding, ["consents"]);
|
|
254
|
+
writeFile(path.join(appDir, "src", "modules.ts"), `export const enabledModules = [{ id: 'consents', from: '${binding}' }]
|
|
255
|
+
`);
|
|
256
|
+
writeFile(path.join(appDir, "src", "modules", "consents", "index.ts"), "export const metadata = { title: 'Local overlay' }\n");
|
|
257
|
+
const before = snapshotDirectory(path.join(appDir, "src"));
|
|
258
|
+
const result = runMercato(["generate", "all", "--quiet"], appDir);
|
|
259
|
+
expect(result.status, result.output).toBe(0);
|
|
260
|
+
expect(snapshotDirectory(path.join(appDir, "src"))).toEqual(before);
|
|
261
|
+
expect(fs.readFileSync(path.join(appDir, ".mercato", "generated", "di.generated.ts"), "utf8")).toContain(`${binding}/modules/consents/di`);
|
|
262
|
+
} finally {
|
|
263
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
//# sourceMappingURL=TC-INT-009.spec.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/__integration__/TC-INT-009.spec.ts"],
|
|
4
|
+
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync, spawnSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..', '..')\nconst cliBin = path.join(repoRoot, 'packages', 'cli', 'dist', 'bin.js')\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction createPackage(packageRoot: string, packageName: string, moduleIds: string[]): void {\n writeFile(path.join(packageRoot, 'package.json'), JSON.stringify({ name: packageName, version: '0.4.7', type: 'module' }))\n for (const moduleId of moduleIds) {\n writeFile(path.join(packageRoot, 'src', 'modules', moduleId, 'index.ts'), `export const metadata = { id: '${moduleId}', title: '${moduleId}', ejectable: true }\\n`)\n writeFile(path.join(packageRoot, 'dist', 'modules', moduleId, 'index.js'), `export const metadata = { id: '${moduleId}', title: '${moduleId}', ejectable: true }\\n`)\n writeFile(path.join(packageRoot, 'src', 'modules', moduleId, 'di.ts'), 'export function register() {}\\n')\n writeFile(path.join(packageRoot, 'dist', 'modules', moduleId, 'di.js'), 'export function register() {}\\n')\n }\n}\n\nfunction createApp(appDir: string, dependencies: Record<string, string> = {}): void {\n writeFile(path.join(appDir, 'package.json'), JSON.stringify({ name: 'module-collision-integration', private: true, dependencies: { '@open-mercato/core': '0.4.7', ...dependencies } }))\n writeFile(path.join(appDir, 'yarn.lock'), '')\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n createPackage(path.join(appDir, 'node_modules', '@open-mercato', 'core'), '@open-mercato/core', [])\n}\n\nfunction runMercato(args: string[], appDir: string, environment: NodeJS.ProcessEnv = {}): { status: number | null; output: string } {\n const result = spawnSync(process.execPath, [cliBin, ...args], {\n cwd: appDir,\n encoding: 'utf8',\n env: { ...process.env, FORCE_COLOR: '0', NODE_NO_WARNINGS: '1', ...environment },\n })\n if (result.error) throw result.error\n return { status: result.status, output: `${result.stdout}\\n${result.stderr}` }\n}\n\nfunction installCommandStubs(appDir: string, candidateName?: string, candidateModuleId?: string): NodeJS.ProcessEnv {\n const executableDir = path.join(appDir, 'bin')\n const marker = path.join(appDir, 'yarn-invoked')\n const yarnPath = path.join(executableDir, process.platform === 'win32' ? 'yarn.cmd' : 'yarn')\n const yarnScript = `require('node:fs').writeFileSync(${JSON.stringify(marker)}, 'invoked'); process.exit(1)\\n`\n writeFile(yarnPath, process.platform === 'win32'\n ? `@\"${process.execPath}\" \"%~dp0yarn-stub.cjs\" %*\\r\\n`\n : `#!${process.execPath}\\n${yarnScript}`)\n writeFile(path.join(executableDir, 'yarn-stub.cjs'), yarnScript)\n fs.chmodSync(yarnPath, 0o755)\n if (candidateName && candidateModuleId) {\n const manifest = Buffer.from(JSON.stringify({ name: candidateName })).toString('base64')\n const ghScript = `const endpoint = process.argv[3] || ''\nconst value = endpoint === 'user' ? { login: 'candidate' }\n : endpoint.includes('/commits/') ? { sha: 'a'.repeat(40) }\n : endpoint.includes('/contents/') ? { encoding: 'base64', content: ${JSON.stringify(manifest)} }\n : endpoint.includes('/git/trees/') ? { tree: [{ path: 'src/modules/${candidateModuleId}/index.ts' }, { path: 'dist/modules/${candidateModuleId}/index.js' }] }\n : { default_branch: 'main' }\nprocess.stdout.write(JSON.stringify(value))\\n`\n const ghPath = path.join(executableDir, process.platform === 'win32' ? 'gh.cmd' : 'gh')\n writeFile(ghPath, process.platform === 'win32'\n ? `@\"${process.execPath}\" \"%~dp0gh-stub.cjs\" %*\\r\\n`\n : `#!${process.execPath}\\n${ghScript}`)\n writeFile(path.join(executableDir, 'gh-stub.cjs'), ghScript)\n fs.chmodSync(ghPath, 0o755)\n }\n return { PATH: executableDir + path.delimiter + process.env.PATH }\n}\n\nfunction snapshotDirectory(directory: string): Record<string, string> {\n if (!fs.existsSync(directory)) return {}\n const files: Record<string, string> = {}\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n const fullPath = path.join(directory, entry.name)\n if (entry.isDirectory()) {\n for (const [relativePath, content] of Object.entries(snapshotDirectory(fullPath))) files[path.join(entry.name, relativePath)] = content\n } else {\n files[entry.name] = fs.readFileSync(fullPath).toString('base64')\n }\n }\n return files\n}\n\ntest.describe('TC-INT-009: CLI source collision lifecycle safeguards', () => {\n for (const kind of ['directory', 'archive']) {\n test(`rejects a local ${kind} with unknown provenance before replacing an active npm binding`, () => {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-file-origin-'))\n const appDir = path.join(root, 'app')\n try {\n const binding = '@publisher/consents'\n createApp(appDir, { [binding]: '0.4.7' })\n createPackage(path.join(appDir, 'node_modules', binding), binding, ['consents'])\n const packageRoot = path.join(root, 'package')\n createPackage(packageRoot, binding, ['consents'])\n if (kind === 'archive') execFileSync('tar', ['-czf', path.join(root, 'candidate.tgz'), '-C', root, 'package'])\n const modulesSource = `export const enabledModules = [{ id: 'consents', from: '${binding}', locator: 'npm:${binding}' }]\\n`\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n const manifestBefore = fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')\n const installedBefore = snapshotDirectory(path.join(appDir, 'node_modules'))\n const environment = installCommandStubs(appDir)\n const locator = kind === 'archive' ? 'file:../candidate.tgz' : 'file:../package'\n const result = runMercato(['module', 'add', `${binding}@${locator}`, '--eject', '--allow-third-party'], appDir, environment)\n\n expect(result.status, result.output).not.toBe(0)\n expect(result.output).toContain('Package binding collision')\n expect(result.output).toContain('unknown origin')\n expect(result.output).toContain('consents')\n expect(fs.existsSync(path.join(appDir, 'yarn-invoked'))).toBe(false)\n expect(fs.readFileSync(path.join(appDir, 'src', 'modules.ts'), 'utf8')).toBe(modulesSource)\n expect(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')).toBe(manifestBefore)\n expect(snapshotDirectory(path.join(appDir, 'node_modules'))).toEqual(installedBefore)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'consents'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, '.mercato', 'generated'))).toBe(false)\n } finally { fs.rmSync(root, { recursive: true, force: true }) }\n })\n }\n\n test('rejects a GitHub replacement of an active binding even when the selected module ID differs', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-binding-collision-'))\n try {\n const binding = '@publisher/shared-package'\n createApp(appDir, { [binding]: 'github:existing/provider#main' })\n createPackage(path.join(appDir, 'node_modules', binding), binding, ['active_module'])\n const modulesSource = `export const enabledModules = [{ id: 'active_module', from: '${binding}', locator: 'github:existing/provider', packageName: '${binding}' }]\\n`\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n const manifestBefore = fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')\n const environment = installCommandStubs(appDir, binding, 'candidate_module')\n const result = runMercato(['module', 'add', 'github:candidate/provider', '--allow-third-party'], appDir, environment)\n\n expect(result.status, result.output).not.toBe(0)\n expect(result.output).toContain('active_module')\n expect(result.output).toContain(binding)\n expect(result.output).toContain('github:existing/provider')\n expect(result.output).toContain('github:candidate/provider')\n expect(fs.existsSync(path.join(appDir, 'yarn-invoked'))).toBe(false)\n expect(fs.readFileSync(path.join(appDir, 'src', 'modules.ts'), 'utf8')).toBe(modulesSource)\n expect(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')).toBe(manifestBefore)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'candidate_module'))).toBe(false)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('rejects an npm file package runtime ID collision before invoking Yarn or copying sources', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-file-collision-'))\n try {\n createApp(appDir)\n const candidateDir = path.join(appDir, 'candidate')\n createPackage(candidateDir, '@publisher/candidate', ['consents'])\n const modulesSource = \"export const enabledModules = [{ id: 'consents', from: '@app', locator: 'github:existing/consents' }]\\n\"\n writeFile(path.join(appDir, 'src', 'modules.ts'), modulesSource)\n writeFile(path.join(appDir, 'src', 'modules', 'consents', 'index.ts'), 'export const metadata = { ejectable: true }\\n')\n const sourceBefore = snapshotDirectory(path.join(appDir, 'src'))\n const manifestBefore = fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')\n const result = runMercato(['module', 'add', '@publisher/candidate@file:./candidate', '--allow-third-party', '--eject'], appDir, installCommandStubs(appDir))\n\n expect(result.status, result.output).not.toBe(0)\n expect(result.output).toContain('consents')\n expect(result.output).toMatch(/collision|already registered|conflict/i)\n expect(fs.existsSync(path.join(appDir, 'yarn-invoked'))).toBe(false)\n expect(snapshotDirectory(path.join(appDir, 'src'))).toEqual(sourceBefore)\n expect(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')).toBe(manifestBefore)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('every generate command rejects duplicate effective registrations before changing existing output', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-generate-duplicates-'))\n try {\n createApp(appDir)\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'consents', from: '@app' }]\\nif (process.env.COLLISION_DUPLICATE_ENABLED === 'true') enabledModules.push({ id: 'consents', from: '@app' })\\n\")\n writeFile(path.join(appDir, 'src', 'modules', 'consents', 'index.ts'), 'export const metadata = {}\\n')\n const outputDir = path.join(appDir, '.mercato', 'generated')\n for (const file of ['entities.ids.generated.ts', 'modules.generated.ts', 'entities.generated.ts', 'di.generated.ts', 'module-package-sources.css']) writeFile(path.join(outputDir, file), 'preserved output\\n')\n const before = snapshotDirectory(outputDir)\n\n for (const command of ['all', 'entity-ids', 'registry', 'entities', 'di']) {\n const result = runMercato(['generate', command, '--quiet'], appDir, { COLLISION_DUPLICATE_ENABLED: 'true' })\n expect(result.status, `${command}: ${result.output}`).not.toBe(0)\n expect(result.output).toContain(\"Duplicate enabled module ID 'consents'\")\n expect(snapshotDirectory(outputDir), command).toEqual(before)\n }\n const singleProvider = runMercato(['generate', 'all', '--quiet'], appDir, { COLLISION_DUPLICATE_ENABLED: 'false' })\n expect(singleProvider.status, singleProvider.output).toBe(0)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('an installed alias generates binding imports, ejects with canonical provenance, and disables cleanly', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-alias-lifecycle-'))\n try {\n const binding = 'consents_candidate'\n const canonicalName = '@publisher/consents'\n createApp(appDir, { [binding]: `npm:${canonicalName}@0.4.7` })\n const packageRoot = path.join(appDir, 'node_modules', binding)\n createPackage(packageRoot, canonicalName, ['consents', 'sibling'])\n writeFile(path.join(packageRoot, 'src', 'modules', 'consents', 'sibling.ts'), \"export { metadata } from '../sibling'\\n\")\n const enabled = runMercato(['module', 'enable', binding, '--module', 'consents', '--allow-third-party'], appDir)\n expect(enabled.status, enabled.output).toBe(0)\n const outputDir = path.join(appDir, '.mercato', 'generated')\n const modulesSource = fs.readFileSync(path.join(appDir, 'src', 'modules.ts'), 'utf8')\n expect(modulesSource).toContain(`from: '${binding}'`)\n expect(modulesSource).toContain(`packageName: '${canonicalName}'`)\n expect(fs.readFileSync(path.join(outputDir, 'di.generated.ts'), 'utf8')).toContain(`${binding}/modules/consents/di`)\n expect(fs.readFileSync(path.join(outputDir, 'module-package-sources.css'), 'utf8')).toContain(`node_modules/${binding}/src/`)\n\n const ejected = runMercato(['module', 'eject', 'consents'], appDir)\n expect(ejected.status, ejected.output).toBe(0)\n const ejectedSource = fs.readFileSync(path.join(appDir, 'src', 'modules.ts'), 'utf8')\n expect(ejectedSource).toContain(\"from: '@app'\")\n expect(ejectedSource).toContain(`packageName: '${canonicalName}'`)\n expect(ejectedSource).toContain(`locator: 'npm:${canonicalName}'`)\n expect(fs.readFileSync(path.join(appDir, 'src', 'modules', 'consents', 'sibling.ts'), 'utf8')).toContain(`${binding}/modules/sibling`)\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n const disabled = runMercato(['generate', 'all', '--quiet'], appDir)\n expect(disabled.status, disabled.output).toBe(0)\n expect(fs.readFileSync(path.join(outputDir, 'di.generated.ts'), 'utf8')).not.toContain('consents')\n expect(fs.readFileSync(path.join(outputDir, 'module-package-sources.css'), 'utf8')).toBe('')\n expect(fs.existsSync(path.join(packageRoot, 'package.json'))).toBe(true)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'consents', 'index.ts'))).toBe(true)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('missing alias exports fail enable and direct eject before source or config changes', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-alias-exports-'))\n try {\n const binding = 'consents_candidate'\n createApp(appDir, { [binding]: 'npm:@publisher/consents@0.4.7' })\n const packageRoot = path.join(appDir, 'node_modules', binding)\n createPackage(packageRoot, '@publisher/consents', ['consents'])\n writeFile(path.join(packageRoot, 'package.json'), JSON.stringify({ name: '@publisher/consents', exports: { '.': './dist/modules/consents/index.js' } }))\n const configPath = path.join(appDir, 'src', 'modules.ts')\n const emptyConfig = fs.readFileSync(configPath, 'utf8')\n\n const enabled = runMercato(['module', 'enable', binding, '--module', 'consents', '--eject', '--allow-third-party'], appDir)\n expect(enabled.status, enabled.output).not.toBe(0)\n expect(enabled.output).toContain(`${binding}/modules/consents/`)\n expect(fs.readFileSync(configPath, 'utf8')).toBe(emptyConfig)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'consents'))).toBe(false)\n\n const registeredConfig = `export const enabledModules = [{ id: 'consents', from: '${binding}' }]\\n`\n writeFile(configPath, registeredConfig)\n const ejected = runMercato(['module', 'eject', 'consents'], appDir)\n expect(ejected.status, ejected.output).not.toBe(0)\n expect(ejected.output).toContain(`${binding}/modules/consents/`)\n expect(fs.readFileSync(configPath, 'utf8')).toBe(registeredConfig)\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'consents'))).toBe(false)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('a single package registration with a local overlay remains valid', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-single-overlay-'))\n try {\n const binding = '@publisher/consents'\n createApp(appDir, { [binding]: '0.4.7' })\n createPackage(path.join(appDir, 'node_modules', binding), binding, ['consents'])\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [{ id: 'consents', from: '${binding}' }]\\n`)\n writeFile(path.join(appDir, 'src', 'modules', 'consents', 'index.ts'), \"export const metadata = { title: 'Local overlay' }\\n\")\n const before = snapshotDirectory(path.join(appDir, 'src'))\n\n const result = runMercato(['generate', 'all', '--quiet'], appDir)\n\n expect(result.status, result.output).toBe(0)\n expect(snapshotDirectory(path.join(appDir, 'src'))).toEqual(before)\n expect(fs.readFileSync(path.join(appDir, '.mercato', 'generated', 'di.generated.ts'), 'utf8')).toContain(`${binding}/modules/consents/di`)\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/lib/eject.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
-
import { setModuleRegistrationSource } from "./modules-config.js";
|
|
4
|
-
import { resolveInstalledOfficialModulePackage } from "./module-package.js";
|
|
3
|
+
import { prepareModuleRegistrationSource, setModuleRegistrationSource } from "./modules-config.js";
|
|
4
|
+
import { isModulePackageExportError, resolveInstalledOfficialModulePackage, resolveInstalledPackageRoot } from "./module-package.js";
|
|
5
|
+
import { normalizeModuleLocator } from "@open-mercato/shared/modules/module-locators";
|
|
6
|
+
import { getEnabledModuleIdentities } from "./module-identity.js";
|
|
5
7
|
const SKIP_DIRS = /* @__PURE__ */ new Set(["__tests__", "__mocks__", "node_modules"]);
|
|
6
8
|
const SOURCE_FILE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
7
9
|
function shouldSkipEntryName(name) {
|
|
@@ -129,8 +131,8 @@ function copyDirRecursive(src, dest) {
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
|
-
function updateModulesTs(modulesPath, moduleId) {
|
|
133
|
-
setModuleRegistrationSource(modulesPath, moduleId, "@app");
|
|
134
|
+
function updateModulesTs(modulesPath, moduleId, provenance) {
|
|
135
|
+
setModuleRegistrationSource(modulesPath, moduleId, "@app", provenance);
|
|
134
136
|
}
|
|
135
137
|
function resolveModuleSourceBase(resolver, entry) {
|
|
136
138
|
const { pkgBase } = resolver.getModulePaths(entry);
|
|
@@ -164,7 +166,8 @@ function resolveModuleSource(resolver, entry) {
|
|
|
164
166
|
description: modulePackage.moduleInfo.description
|
|
165
167
|
}
|
|
166
168
|
};
|
|
167
|
-
} catch {
|
|
169
|
+
} catch (error) {
|
|
170
|
+
if (isModulePackageExportError(error)) throw error;
|
|
168
171
|
return { pkgBase, metadata: fallbackMetadata };
|
|
169
172
|
}
|
|
170
173
|
}
|
|
@@ -187,7 +190,9 @@ function listEjectableModules(resolver) {
|
|
|
187
190
|
}
|
|
188
191
|
function ejectModule(resolver, moduleId) {
|
|
189
192
|
const modules = resolver.loadEnabledModules();
|
|
190
|
-
const
|
|
193
|
+
const identities = getEnabledModuleIdentities(resolver, modules);
|
|
194
|
+
const matches = modules.filter((module) => module.id === moduleId);
|
|
195
|
+
const entry = matches[0];
|
|
191
196
|
if (!entry) {
|
|
192
197
|
throw new Error(
|
|
193
198
|
`Module "${moduleId}" is not listed in src/modules.ts. Available modules: ${modules.map((m) => m.id).join(", ")}`
|
|
@@ -212,13 +217,24 @@ function ejectModule(resolver, moduleId) {
|
|
|
212
217
|
}
|
|
213
218
|
if (fs.existsSync(appBase)) {
|
|
214
219
|
throw new Error(
|
|
215
|
-
`Destination directory already exists: ${appBase}.
|
|
220
|
+
`Destination directory already exists: ${appBase}. Keep the existing local source and review the destination conflict before ejecting.`
|
|
216
221
|
);
|
|
217
222
|
}
|
|
223
|
+
const locators = identities.find((identity) => identity.id === moduleId)?.locators ?? [];
|
|
224
|
+
const packageRoot = resolveInstalledPackageRoot(resolver, entry.from || "@open-mercato/core");
|
|
225
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
|
|
226
|
+
const packageName = manifest && typeof manifest === "object" && "name" in manifest && typeof manifest.name === "string" ? manifest.name : void 0;
|
|
227
|
+
if (!packageName || normalizeModuleLocator(`npm:${packageName}`) !== `npm:${packageName}`) {
|
|
228
|
+
throw new Error(`Cannot retain source provenance for module "${moduleId}": the installed package manifest has no valid name.`);
|
|
229
|
+
}
|
|
230
|
+
const locator = locators.find((identity) => identity.startsWith("github:")) ?? locators.find((identity) => identity.startsWith("npm:"));
|
|
231
|
+
const provenance = { ...packageName ? { packageName } : {}, ...locator ? { locator } : {} };
|
|
232
|
+
const modulesPath = resolver.getModulesConfigPath();
|
|
233
|
+
const originalConfig = fs.readFileSync(modulesPath, "utf8");
|
|
234
|
+
const updatedConfig = prepareModuleRegistrationSource(originalConfig, moduleId, "@app", provenance);
|
|
218
235
|
copyDirRecursive(pkgBase, appBase);
|
|
219
236
|
rewriteCrossModuleImports(pkgBase, appBase, moduleId, entry.from || "@open-mercato/core");
|
|
220
|
-
|
|
221
|
-
updateModulesTs(modulesPath, moduleId);
|
|
237
|
+
fs.writeFileSync(modulesPath, updatedConfig);
|
|
222
238
|
}
|
|
223
239
|
export {
|
|
224
240
|
copyDirRecursive,
|