@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.
Files changed (162) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/agentic/guides/module-facts.json +162 -162
  3. package/dist/agentic/guides/module-facts.v2.json +162 -162
  4. package/dist/agentic/guides/module-tool.md +21 -0
  5. package/dist/agentic/guides/modules/agent_orchestrator/index.md +1 -1
  6. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  7. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  8. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  9. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  10. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  11. package/dist/agentic/guides/modules/auth/index.md +1 -1
  12. package/dist/agentic/guides/modules/availability/index.md +1 -1
  13. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  14. package/dist/agentic/guides/modules/carrier_inpost/index.md +1 -1
  15. package/dist/agentic/guides/modules/cart/index.md +1 -1
  16. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  17. package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
  18. package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
  19. package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
  20. package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
  21. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  22. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  23. package/dist/agentic/guides/modules/channel_resend/index.md +1 -1
  24. package/dist/agentic/guides/modules/channel_ses/index.md +1 -1
  25. package/dist/agentic/guides/modules/channel_smtp/index.md +1 -1
  26. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  27. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  28. package/dist/agentic/guides/modules/configs/index.md +1 -1
  29. package/dist/agentic/guides/modules/content/index.md +1 -1
  30. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  31. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  32. package/dist/agentic/guides/modules/customer_groups/index.md +1 -1
  33. package/dist/agentic/guides/modules/customers/index.md +1 -1
  34. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  35. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  36. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  37. package/dist/agentic/guides/modules/devices/index.md +1 -1
  38. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  39. package/dist/agentic/guides/modules/directory/index.md +1 -1
  40. package/dist/agentic/guides/modules/documents/index.md +1 -1
  41. package/dist/agentic/guides/modules/ecommerce/index.md +1 -1
  42. package/dist/agentic/guides/modules/entities/index.md +1 -1
  43. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  44. package/dist/agentic/guides/modules/events/index.md +1 -1
  45. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  46. package/dist/agentic/guides/modules/forms/index.md +1 -1
  47. package/dist/agentic/guides/modules/gateway_autopay/index.md +1 -1
  48. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  49. package/dist/agentic/guides/modules/gateway_tpay/index.md +1 -1
  50. package/dist/agentic/guides/modules/generators/index.md +1 -1
  51. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  52. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  53. package/dist/agentic/guides/modules/messages/index.md +1 -1
  54. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  55. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  56. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  57. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  58. package/dist/agentic/guides/modules/phone_calls/index.md +1 -1
  59. package/dist/agentic/guides/modules/planner/index.md +1 -1
  60. package/dist/agentic/guides/modules/portal/index.md +1 -1
  61. package/dist/agentic/guides/modules/progress/index.md +1 -1
  62. package/dist/agentic/guides/modules/promotions/index.md +1 -1
  63. package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
  64. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  65. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  66. package/dist/agentic/guides/modules/resources/index.md +1 -1
  67. package/dist/agentic/guides/modules/sales/index.md +1 -1
  68. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  69. package/dist/agentic/guides/modules/search/index.md +1 -1
  70. package/dist/agentic/guides/modules/security/index.md +1 -1
  71. package/dist/agentic/guides/modules/seeds/index.md +1 -1
  72. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  73. package/dist/agentic/guides/modules/sso/index.md +1 -1
  74. package/dist/agentic/guides/modules/staff/index.md +1 -1
  75. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  76. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  77. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  78. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  79. package/dist/agentic/guides/modules/telemetry/index.md +1 -1
  80. package/dist/agentic/guides/modules/tillio/index.md +1 -1
  81. package/dist/agentic/guides/modules/translations/index.md +1 -1
  82. package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
  83. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  84. package/dist/agentic/guides/modules/wms/index.md +1 -1
  85. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  86. package/dist/agentic/guides/reference-module-facts.json +1 -1
  87. package/dist/agentic/guides/upstream/manifest.json +1 -1
  88. package/dist/agentic/shared/ai/harness/cases.json +23 -9
  89. package/dist/agentic/shared/ai/harness/source-link-inventory.json +90 -4
  90. package/dist/lib/__integration__/TC-INT-007.spec.js +207 -19
  91. package/dist/lib/__integration__/TC-INT-007.spec.js.map +2 -2
  92. package/dist/lib/__integration__/TC-INT-009.spec.js +267 -0
  93. package/dist/lib/__integration__/TC-INT-009.spec.js.map +7 -0
  94. package/dist/lib/eject.js +25 -9
  95. package/dist/lib/eject.js.map +2 -2
  96. package/dist/lib/generators/entity-ids.js +2 -0
  97. package/dist/lib/generators/entity-ids.js.map +2 -2
  98. package/dist/lib/generators/module-di.js +2 -0
  99. package/dist/lib/generators/module-di.js.map +2 -2
  100. package/dist/lib/generators/module-entities.js +2 -0
  101. package/dist/lib/generators/module-entities.js.map +2 -2
  102. package/dist/lib/generators/module-package-sources.js +6 -4
  103. package/dist/lib/generators/module-package-sources.js.map +2 -2
  104. package/dist/lib/generators/module-registry.js +32 -86
  105. package/dist/lib/generators/module-registry.js.map +2 -2
  106. package/dist/lib/generators/openapi.js +2 -0
  107. package/dist/lib/generators/openapi.js.map +2 -2
  108. package/dist/lib/generators/source-exports.js +73 -0
  109. package/dist/lib/generators/source-exports.js.map +7 -0
  110. package/dist/lib/init-summary.js +44 -0
  111. package/dist/lib/init-summary.js.map +7 -0
  112. package/dist/lib/module-github.js +98 -0
  113. package/dist/lib/module-github.js.map +7 -0
  114. package/dist/lib/module-identity.js +131 -0
  115. package/dist/lib/module-identity.js.map +7 -0
  116. package/dist/lib/module-inspection.js +124 -0
  117. package/dist/lib/module-inspection.js.map +7 -0
  118. package/dist/lib/module-install.js +150 -21
  119. package/dist/lib/module-install.js.map +3 -3
  120. package/dist/lib/module-package.js +205 -15
  121. package/dist/lib/module-package.js.map +2 -2
  122. package/dist/lib/modules-config.js +69 -30
  123. package/dist/lib/modules-config.js.map +2 -2
  124. package/dist/lib/resolver.js +33 -34
  125. package/dist/lib/resolver.js.map +2 -2
  126. package/dist/mercato.js +14 -23
  127. package/dist/mercato.js.map +2 -2
  128. package/package.json +7 -7
  129. package/src/__tests__/mercato.test.ts +14 -4
  130. package/src/lib/__fixtures__/official-module-package/dist/modules/test_package/widgets/injection/test/widget.js +1 -0
  131. package/src/lib/__integration__/TC-INT-007.spec.ts +219 -19
  132. package/src/lib/__integration__/TC-INT-009.spec.ts +279 -0
  133. package/src/lib/__tests__/eject.test.ts +98 -4
  134. package/src/lib/__tests__/init-summary.test.ts +50 -0
  135. package/src/lib/__tests__/module-github.test.ts +108 -0
  136. package/src/lib/__tests__/module-identity.test.ts +144 -0
  137. package/src/lib/__tests__/module-inspection.test.ts +195 -0
  138. package/src/lib/__tests__/module-install.test.ts +399 -10
  139. package/src/lib/__tests__/module-package.test.ts +154 -0
  140. package/src/lib/__tests__/modules-config.test.ts +55 -0
  141. package/src/lib/__tests__/resolver.packages.test.ts +29 -0
  142. package/src/lib/eject.ts +28 -10
  143. package/src/lib/generators/__tests__/module-id-collisions.test.ts +146 -0
  144. package/src/lib/generators/__tests__/module-package-sources.test.ts +19 -2
  145. package/src/lib/generators/__tests__/module-requirements.test.ts +56 -0
  146. package/src/lib/generators/entity-ids.ts +2 -0
  147. package/src/lib/generators/module-di.ts +2 -0
  148. package/src/lib/generators/module-entities.ts +2 -0
  149. package/src/lib/generators/module-package-sources.ts +7 -5
  150. package/src/lib/generators/module-registry.ts +33 -115
  151. package/src/lib/generators/openapi.ts +3 -0
  152. package/src/lib/generators/source-exports.ts +93 -0
  153. package/src/lib/init-summary.ts +54 -0
  154. package/src/lib/module-github.ts +109 -0
  155. package/src/lib/module-identity.ts +145 -0
  156. package/src/lib/module-inspection.ts +133 -0
  157. package/src/lib/module-install.ts +170 -22
  158. package/src/lib/module-package.ts +243 -16
  159. package/src/lib/modules-config.ts +80 -32
  160. package/src/lib/resolver.ts +35 -39
  161. package/src/mercato.ts +14 -24
  162. 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 entry = modules.find((m) => m.id === moduleId);
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}. Remove it first or resolve the conflict manually.`
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
- const modulesPath = resolver.getModulesConfigPath();
221
- updateModulesTs(modulesPath, moduleId);
237
+ fs.writeFileSync(modulesPath, updatedConfig);
222
238
  }
223
239
  export {
224
240
  copyDirRecursive,