@open-mercato/cli 0.6.7-develop.6597.1.b8f069b7fe → 0.6.7-develop.6603.1.78e5b7a65d

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 (60) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/agentic/guides/module-facts.json +53 -53
  3. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  4. package/dist/agentic/guides/modules/api_docs.md +1 -1
  5. package/dist/agentic/guides/modules/api_keys.md +1 -1
  6. package/dist/agentic/guides/modules/attachments.md +1 -1
  7. package/dist/agentic/guides/modules/audit_logs.md +1 -1
  8. package/dist/agentic/guides/modules/auth.md +1 -1
  9. package/dist/agentic/guides/modules/business_rules.md +1 -1
  10. package/dist/agentic/guides/modules/catalog.md +1 -1
  11. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  12. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  13. package/dist/agentic/guides/modules/checkout.md +1 -1
  14. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  15. package/dist/agentic/guides/modules/configs.md +1 -1
  16. package/dist/agentic/guides/modules/content.md +1 -1
  17. package/dist/agentic/guides/modules/currencies.md +1 -1
  18. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  19. package/dist/agentic/guides/modules/customers.md +1 -1
  20. package/dist/agentic/guides/modules/dashboards.md +1 -1
  21. package/dist/agentic/guides/modules/data_sync.md +1 -1
  22. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  23. package/dist/agentic/guides/modules/directory.md +1 -1
  24. package/dist/agentic/guides/modules/entities.md +1 -1
  25. package/dist/agentic/guides/modules/events.md +1 -1
  26. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  27. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  28. package/dist/agentic/guides/modules/generators.md +1 -1
  29. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  30. package/dist/agentic/guides/modules/integrations.md +1 -1
  31. package/dist/agentic/guides/modules/messages.md +1 -1
  32. package/dist/agentic/guides/modules/notifications.md +1 -1
  33. package/dist/agentic/guides/modules/onboarding.md +1 -1
  34. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  35. package/dist/agentic/guides/modules/perspectives.md +1 -1
  36. package/dist/agentic/guides/modules/planner.md +1 -1
  37. package/dist/agentic/guides/modules/portal.md +1 -1
  38. package/dist/agentic/guides/modules/progress.md +1 -1
  39. package/dist/agentic/guides/modules/query_index.md +1 -1
  40. package/dist/agentic/guides/modules/record_locks.md +1 -1
  41. package/dist/agentic/guides/modules/resources.md +1 -1
  42. package/dist/agentic/guides/modules/sales.md +1 -1
  43. package/dist/agentic/guides/modules/scheduler.md +1 -1
  44. package/dist/agentic/guides/modules/search.md +1 -1
  45. package/dist/agentic/guides/modules/security.md +1 -1
  46. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  47. package/dist/agentic/guides/modules/sso.md +1 -1
  48. package/dist/agentic/guides/modules/staff.md +1 -1
  49. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  50. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  51. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  52. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  53. package/dist/agentic/guides/modules/translations.md +1 -1
  54. package/dist/agentic/guides/modules/webhooks.md +1 -1
  55. package/dist/agentic/guides/modules/workflows.md +1 -1
  56. package/dist/lib/eject.js +17 -2
  57. package/dist/lib/eject.js.map +2 -2
  58. package/package.json +5 -5
  59. package/src/lib/__tests__/eject.test.ts +85 -0
  60. package/src/lib/eject.ts +24 -2
@@ -1,5 +1,5 @@
1
1
  # entities — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # events — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # feature_toggles — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # gateway_stripe — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # generators — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # inbox_ops — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # integrations — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # messages — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # notifications — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # onboarding — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # payment_gateways — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # perspectives — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # planner — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # portal — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # progress — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # query_index — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # record_locks — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # resources — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sales — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # scheduler — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # search — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # security — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # shipping_carriers — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sso — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # staff — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # storage_s3 — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sync_akeneo — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # sync_excel — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # system_status_overlays — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # translations — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # webhooks — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
@@ -1,5 +1,5 @@
1
1
  # workflows — module facts (generated, do not edit)
2
- <!-- generated from @open-mercato/core 0.6.7-develop.6597.1.b8f069b7fe — R1 staleness stamp -->
2
+ <!-- generated from @open-mercato/core 0.6.7-develop.6603.1.78e5b7a65d — R1 staleness stamp -->
3
3
 
4
4
  ## Entities
5
5
 
package/dist/lib/eject.js CHANGED
@@ -132,9 +132,24 @@ function copyDirRecursive(src, dest) {
132
132
  function updateModulesTs(modulesPath, moduleId) {
133
133
  setModuleRegistrationSource(modulesPath, moduleId, "@app");
134
134
  }
135
- function resolveModuleSource(resolver, entry) {
135
+ function resolveModuleSourceBase(resolver, entry) {
136
136
  const { pkgBase } = resolver.getModulePaths(entry);
137
- const fallbackMetadata = parseModuleMetadata(path.join(pkgBase, "index.ts"));
137
+ const from = entry.from || "@open-mercato/core";
138
+ if (from === "@app") return pkgBase;
139
+ const sourceBase = path.join(resolver.getPackageRoot(from), "src", "modules", entry.id);
140
+ if (path.resolve(sourceBase) !== path.resolve(pkgBase) && fs.existsSync(sourceBase)) {
141
+ return sourceBase;
142
+ }
143
+ return pkgBase;
144
+ }
145
+ function readModuleMetadata(moduleDir) {
146
+ const tsIndex = path.join(moduleDir, "index.ts");
147
+ if (fs.existsSync(tsIndex)) return parseModuleMetadata(tsIndex);
148
+ return parseModuleMetadata(path.join(moduleDir, "index.js"));
149
+ }
150
+ function resolveModuleSource(resolver, entry) {
151
+ const pkgBase = resolveModuleSourceBase(resolver, entry);
152
+ const fallbackMetadata = readModuleMetadata(pkgBase);
138
153
  const from = entry.from || "@open-mercato/core";
139
154
  if (from === "@app" || from === "@open-mercato/core") {
140
155
  return { pkgBase, metadata: fallbackMetadata };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/eject.ts"],
4
- "sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport { setModuleRegistrationSource } from './modules-config'\nimport type { PackageResolver, ModuleEntry } from './resolver'\nimport { resolveInstalledOfficialModulePackage } from './module-package'\n\ntype ModuleMetadata = {\n ejectable?: boolean\n title?: string\n description?: string\n}\n\nconst SKIP_DIRS = new Set(['__tests__', '__mocks__', 'node_modules'])\nconst SOURCE_FILE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']\n\nfunction shouldSkipEntryName(name: string): boolean {\n return SKIP_DIRS.has(name) || name === '.DS_Store' || name.startsWith('._')\n}\n\nfunction collectSourceFiles(dir: string): string[] {\n const files: string[] = []\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n for (const entry of entries) {\n if (shouldSkipEntryName(entry.name)) continue\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n files.push(...collectSourceFiles(fullPath))\n continue\n }\n const ext = path.extname(entry.name)\n if (!SOURCE_FILE_EXTENSIONS.includes(ext)) continue\n files.push(fullPath)\n }\n return files\n}\n\nfunction resolveRelativeImportTarget(sourceFile: string, importPath: string): string | null {\n if (!importPath.startsWith('.')) return null\n\n const basePath = path.resolve(path.dirname(sourceFile), importPath)\n const candidates = [basePath]\n\n for (const ext of SOURCE_FILE_EXTENSIONS) {\n candidates.push(`${basePath}${ext}`)\n candidates.push(path.join(basePath, `index${ext}`))\n }\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate\n }\n }\n\n return null\n}\n\nfunction rewriteRelativeSpecifier(\n sourceFile: string,\n specifier: string,\n modulesRoot: string,\n moduleId: string,\n packageName: string,\n): string {\n const resolvedTarget = resolveRelativeImportTarget(sourceFile, specifier)\n if (!resolvedTarget) return specifier\n\n const modulesRootPrefix = `${modulesRoot}${path.sep}`\n if (!resolvedTarget.startsWith(modulesRootPrefix)) return specifier\n\n const relativeFromModules = path.relative(modulesRoot, resolvedTarget)\n let normalizedRelative = relativeFromModules.split(path.sep).join('/')\n const matchedExt = SOURCE_FILE_EXTENSIONS.find((ext) => normalizedRelative.endsWith(ext))\n if (matchedExt) {\n normalizedRelative = normalizedRelative.slice(0, -matchedExt.length)\n }\n if (normalizedRelative.endsWith('/index')) {\n normalizedRelative = normalizedRelative.slice(0, -'/index'.length)\n }\n const segments = normalizedRelative.split('/')\n const targetModuleId = segments[0]\n\n if (!targetModuleId || targetModuleId === moduleId) return specifier\n\n return `${packageName}/modules/${normalizedRelative}`\n}\n\nexport function rewriteCrossModuleImports(\n pkgBase: string,\n appBase: string,\n moduleId: string,\n packageName: string,\n): void {\n const modulesRoot = path.resolve(pkgBase, '..')\n const appFiles = collectSourceFiles(appBase)\n\n for (const appFile of appFiles) {\n const relativePath = path.relative(appBase, appFile)\n const sourceFile = path.join(pkgBase, relativePath)\n\n if (!fs.existsSync(sourceFile)) continue\n\n const content = fs.readFileSync(appFile, 'utf8')\n let updated = content\n\n updated = updated.replace(\n /(\\bfrom\\s*['\"])([^'\"]+)(['\"])/g,\n (_match, prefix: string, specifier: string, suffix: string) => {\n const rewritten = rewriteRelativeSpecifier(\n sourceFile,\n specifier,\n modulesRoot,\n moduleId,\n packageName,\n )\n return `${prefix}${rewritten}${suffix}`\n },\n )\n\n updated = updated.replace(\n /(\\bimport\\s*\\(\\s*['\"])([^'\"]+)(['\"]\\s*\\))/g,\n (_match, prefix: string, specifier: string, suffix: string) => {\n const rewritten = rewriteRelativeSpecifier(\n sourceFile,\n specifier,\n modulesRoot,\n moduleId,\n packageName,\n )\n return `${prefix}${rewritten}${suffix}`\n },\n )\n\n if (updated !== content) {\n fs.writeFileSync(appFile, updated)\n }\n }\n}\n\nexport function parseModuleMetadata(indexPath: string): ModuleMetadata {\n if (!fs.existsSync(indexPath)) return {}\n\n const source = fs.readFileSync(indexPath, 'utf8')\n const result: ModuleMetadata = {}\n\n const ejectableMatch = source.match(/ejectable\\s*:\\s*(true|false)/)\n if (ejectableMatch) {\n result.ejectable = ejectableMatch[1] === 'true'\n }\n\n const titleMatch = source.match(/title\\s*:\\s*['\"]([^'\"]+)['\"]/)\n if (titleMatch) {\n result.title = titleMatch[1]\n }\n\n const descMatch = source.match(/description\\s*:\\s*['\"]([^'\"]+)['\"]/)\n if (descMatch) {\n result.description = descMatch[1]\n }\n\n return result\n}\n\nexport function copyDirRecursive(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true })\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n for (const entry of entries) {\n if (shouldSkipEntryName(entry.name)) continue\n\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n copyDirRecursive(srcPath, destPath)\n } else {\n fs.copyFileSync(srcPath, destPath)\n }\n }\n}\n\nexport function updateModulesTs(modulesPath: string, moduleId: string): void {\n setModuleRegistrationSource(modulesPath, moduleId, '@app')\n}\n\nexport type EjectableModule = {\n id: string\n title?: string\n description?: string\n from: string\n}\n\ntype ResolvedModuleSource = {\n pkgBase: string\n metadata: ModuleMetadata\n}\n\nfunction resolveModuleSource(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): ResolvedModuleSource {\n const { pkgBase } = resolver.getModulePaths(entry)\n const fallbackMetadata = parseModuleMetadata(path.join(pkgBase, 'index.ts'))\n const from = entry.from || '@open-mercato/core'\n\n if (from === '@app' || from === '@open-mercato/core') {\n return { pkgBase, metadata: fallbackMetadata }\n }\n\n try {\n const modulePackage = resolveInstalledOfficialModulePackage(resolver, from, entry.id)\n\n return {\n pkgBase: modulePackage.sourceModuleDir,\n metadata: {\n ejectable: modulePackage.metadata.ejectable,\n title: modulePackage.moduleInfo.title ?? modulePackage.metadata.moduleId,\n description: modulePackage.moduleInfo.description,\n },\n }\n } catch {\n return { pkgBase, metadata: fallbackMetadata }\n }\n}\n\nexport function listEjectableModules(resolver: PackageResolver): EjectableModule[] {\n const modules = resolver.loadEnabledModules()\n const ejectable: EjectableModule[] = []\n\n for (const entry of modules) {\n if (entry.from === '@app') continue\n\n const { metadata } = resolveModuleSource(resolver, entry)\n\n if (metadata.ejectable) {\n ejectable.push({\n id: entry.id,\n title: metadata.title,\n description: metadata.description,\n from: entry.from || '@open-mercato/core',\n })\n }\n }\n\n return ejectable\n}\n\nexport function ejectModule(resolver: PackageResolver, moduleId: string): void {\n const modules = resolver.loadEnabledModules()\n const entry = modules.find((m: ModuleEntry) => m.id === moduleId)\n\n if (!entry) {\n throw new Error(\n `Module \"${moduleId}\" is not listed in src/modules.ts. ` +\n `Available modules: ${modules.map((m: ModuleEntry) => m.id).join(', ')}`,\n )\n }\n\n if (entry.from === '@app') {\n throw new Error(\n `Module \"${moduleId}\" is already local (from: '@app'). Nothing to eject.`,\n )\n }\n\n const { appBase } = resolver.getModulePaths(entry)\n const { pkgBase, metadata } = resolveModuleSource(resolver, entry)\n\n if (!fs.existsSync(pkgBase)) {\n throw new Error(\n `Package source directory not found: ${pkgBase}. ` +\n `Make sure the package is installed.`,\n )\n }\n\n if (!metadata.ejectable) {\n throw new Error(\n `Module \"${moduleId}\" is not marked as ejectable. Only modules with \\`ejectable: true\\` in their metadata can be ejected.`,\n )\n }\n\n if (fs.existsSync(appBase)) {\n throw new Error(\n `Destination directory already exists: ${appBase}. ` +\n `Remove it first or resolve the conflict manually.`,\n )\n }\n\n copyDirRecursive(pkgBase, appBase)\n rewriteCrossModuleImports(pkgBase, appBase, moduleId, entry.from || '@open-mercato/core')\n\n const modulesPath = resolver.getModulesConfigPath()\n updateModulesTs(modulesPath, moduleId)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport { setModuleRegistrationSource } from './modules-config'\nimport type { PackageResolver, ModuleEntry } from './resolver'\nimport { resolveInstalledOfficialModulePackage } from './module-package'\n\ntype ModuleMetadata = {\n ejectable?: boolean\n title?: string\n description?: string\n}\n\nconst SKIP_DIRS = new Set(['__tests__', '__mocks__', 'node_modules'])\nconst SOURCE_FILE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']\n\nfunction shouldSkipEntryName(name: string): boolean {\n return SKIP_DIRS.has(name) || name === '.DS_Store' || name.startsWith('._')\n}\n\nfunction collectSourceFiles(dir: string): string[] {\n const files: string[] = []\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n for (const entry of entries) {\n if (shouldSkipEntryName(entry.name)) continue\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n files.push(...collectSourceFiles(fullPath))\n continue\n }\n const ext = path.extname(entry.name)\n if (!SOURCE_FILE_EXTENSIONS.includes(ext)) continue\n files.push(fullPath)\n }\n return files\n}\n\nfunction resolveRelativeImportTarget(sourceFile: string, importPath: string): string | null {\n if (!importPath.startsWith('.')) return null\n\n const basePath = path.resolve(path.dirname(sourceFile), importPath)\n const candidates = [basePath]\n\n for (const ext of SOURCE_FILE_EXTENSIONS) {\n candidates.push(`${basePath}${ext}`)\n candidates.push(path.join(basePath, `index${ext}`))\n }\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate\n }\n }\n\n return null\n}\n\nfunction rewriteRelativeSpecifier(\n sourceFile: string,\n specifier: string,\n modulesRoot: string,\n moduleId: string,\n packageName: string,\n): string {\n const resolvedTarget = resolveRelativeImportTarget(sourceFile, specifier)\n if (!resolvedTarget) return specifier\n\n const modulesRootPrefix = `${modulesRoot}${path.sep}`\n if (!resolvedTarget.startsWith(modulesRootPrefix)) return specifier\n\n const relativeFromModules = path.relative(modulesRoot, resolvedTarget)\n let normalizedRelative = relativeFromModules.split(path.sep).join('/')\n const matchedExt = SOURCE_FILE_EXTENSIONS.find((ext) => normalizedRelative.endsWith(ext))\n if (matchedExt) {\n normalizedRelative = normalizedRelative.slice(0, -matchedExt.length)\n }\n if (normalizedRelative.endsWith('/index')) {\n normalizedRelative = normalizedRelative.slice(0, -'/index'.length)\n }\n const segments = normalizedRelative.split('/')\n const targetModuleId = segments[0]\n\n if (!targetModuleId || targetModuleId === moduleId) return specifier\n\n return `${packageName}/modules/${normalizedRelative}`\n}\n\nexport function rewriteCrossModuleImports(\n pkgBase: string,\n appBase: string,\n moduleId: string,\n packageName: string,\n): void {\n const modulesRoot = path.resolve(pkgBase, '..')\n const appFiles = collectSourceFiles(appBase)\n\n for (const appFile of appFiles) {\n const relativePath = path.relative(appBase, appFile)\n const sourceFile = path.join(pkgBase, relativePath)\n\n if (!fs.existsSync(sourceFile)) continue\n\n const content = fs.readFileSync(appFile, 'utf8')\n let updated = content\n\n updated = updated.replace(\n /(\\bfrom\\s*['\"])([^'\"]+)(['\"])/g,\n (_match, prefix: string, specifier: string, suffix: string) => {\n const rewritten = rewriteRelativeSpecifier(\n sourceFile,\n specifier,\n modulesRoot,\n moduleId,\n packageName,\n )\n return `${prefix}${rewritten}${suffix}`\n },\n )\n\n updated = updated.replace(\n /(\\bimport\\s*\\(\\s*['\"])([^'\"]+)(['\"]\\s*\\))/g,\n (_match, prefix: string, specifier: string, suffix: string) => {\n const rewritten = rewriteRelativeSpecifier(\n sourceFile,\n specifier,\n modulesRoot,\n moduleId,\n packageName,\n )\n return `${prefix}${rewritten}${suffix}`\n },\n )\n\n if (updated !== content) {\n fs.writeFileSync(appFile, updated)\n }\n }\n}\n\nexport function parseModuleMetadata(indexPath: string): ModuleMetadata {\n if (!fs.existsSync(indexPath)) return {}\n\n const source = fs.readFileSync(indexPath, 'utf8')\n const result: ModuleMetadata = {}\n\n const ejectableMatch = source.match(/ejectable\\s*:\\s*(true|false)/)\n if (ejectableMatch) {\n result.ejectable = ejectableMatch[1] === 'true'\n }\n\n const titleMatch = source.match(/title\\s*:\\s*['\"]([^'\"]+)['\"]/)\n if (titleMatch) {\n result.title = titleMatch[1]\n }\n\n const descMatch = source.match(/description\\s*:\\s*['\"]([^'\"]+)['\"]/)\n if (descMatch) {\n result.description = descMatch[1]\n }\n\n return result\n}\n\nexport function copyDirRecursive(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true })\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n for (const entry of entries) {\n if (shouldSkipEntryName(entry.name)) continue\n\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n copyDirRecursive(srcPath, destPath)\n } else {\n fs.copyFileSync(srcPath, destPath)\n }\n }\n}\n\nexport function updateModulesTs(modulesPath: string, moduleId: string): void {\n setModuleRegistrationSource(modulesPath, moduleId, '@app')\n}\n\nexport type EjectableModule = {\n id: string\n title?: string\n description?: string\n from: string\n}\n\ntype ResolvedModuleSource = {\n pkgBase: string\n metadata: ModuleMetadata\n}\n\n// Standalone installs resolve getModulePaths' pkgBase to the package's\n// dist/modules tree when it exists (compiled JS, no index.ts), which made every\n// ejectable module read as \"not ejectable\" and eject copies of compiled output\n// (#4272). Prefer the shipped TypeScript sources under src/modules; fall back\n// to the resolved base for packages that ship dist only.\nfunction resolveModuleSourceBase(resolver: PackageResolver, entry: ModuleEntry): string {\n const { pkgBase } = resolver.getModulePaths(entry)\n const from = entry.from || '@open-mercato/core'\n if (from === '@app') return pkgBase\n const sourceBase = path.join(resolver.getPackageRoot(from), 'src', 'modules', entry.id)\n if (path.resolve(sourceBase) !== path.resolve(pkgBase) && fs.existsSync(sourceBase)) {\n return sourceBase\n }\n return pkgBase\n}\n\nfunction readModuleMetadata(moduleDir: string): ModuleMetadata {\n const tsIndex = path.join(moduleDir, 'index.ts')\n if (fs.existsSync(tsIndex)) return parseModuleMetadata(tsIndex)\n return parseModuleMetadata(path.join(moduleDir, 'index.js'))\n}\n\nfunction resolveModuleSource(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): ResolvedModuleSource {\n const pkgBase = resolveModuleSourceBase(resolver, entry)\n const fallbackMetadata = readModuleMetadata(pkgBase)\n const from = entry.from || '@open-mercato/core'\n\n if (from === '@app' || from === '@open-mercato/core') {\n return { pkgBase, metadata: fallbackMetadata }\n }\n\n try {\n const modulePackage = resolveInstalledOfficialModulePackage(resolver, from, entry.id)\n\n return {\n pkgBase: modulePackage.sourceModuleDir,\n metadata: {\n ejectable: modulePackage.metadata.ejectable,\n title: modulePackage.moduleInfo.title ?? modulePackage.metadata.moduleId,\n description: modulePackage.moduleInfo.description,\n },\n }\n } catch {\n return { pkgBase, metadata: fallbackMetadata }\n }\n}\n\nexport function listEjectableModules(resolver: PackageResolver): EjectableModule[] {\n const modules = resolver.loadEnabledModules()\n const ejectable: EjectableModule[] = []\n\n for (const entry of modules) {\n if (entry.from === '@app') continue\n\n const { metadata } = resolveModuleSource(resolver, entry)\n\n if (metadata.ejectable) {\n ejectable.push({\n id: entry.id,\n title: metadata.title,\n description: metadata.description,\n from: entry.from || '@open-mercato/core',\n })\n }\n }\n\n return ejectable\n}\n\nexport function ejectModule(resolver: PackageResolver, moduleId: string): void {\n const modules = resolver.loadEnabledModules()\n const entry = modules.find((m: ModuleEntry) => m.id === moduleId)\n\n if (!entry) {\n throw new Error(\n `Module \"${moduleId}\" is not listed in src/modules.ts. ` +\n `Available modules: ${modules.map((m: ModuleEntry) => m.id).join(', ')}`,\n )\n }\n\n if (entry.from === '@app') {\n throw new Error(\n `Module \"${moduleId}\" is already local (from: '@app'). Nothing to eject.`,\n )\n }\n\n const { appBase } = resolver.getModulePaths(entry)\n const { pkgBase, metadata } = resolveModuleSource(resolver, entry)\n\n if (!fs.existsSync(pkgBase)) {\n throw new Error(\n `Package source directory not found: ${pkgBase}. ` +\n `Make sure the package is installed.`,\n )\n }\n\n if (!metadata.ejectable) {\n throw new Error(\n `Module \"${moduleId}\" is not marked as ejectable. Only modules with \\`ejectable: true\\` in their metadata can be ejected.`,\n )\n }\n\n if (fs.existsSync(appBase)) {\n throw new Error(\n `Destination directory already exists: ${appBase}. ` +\n `Remove it first or resolve the conflict manually.`,\n )\n }\n\n copyDirRecursive(pkgBase, appBase)\n rewriteCrossModuleImports(pkgBase, appBase, moduleId, entry.from || '@open-mercato/core')\n\n const modulesPath = resolver.getModulesConfigPath()\n updateModulesTs(modulesPath, moduleId)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.6.7-develop.6597.1.b8f069b7fe",
3
+ "version": "0.6.7-develop.6603.1.78e5b7a65d",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,8 +60,8 @@
60
60
  "@mikro-orm/decorators": "^7.1.5",
61
61
  "@mikro-orm/migrations": "^7.1.5",
62
62
  "@mikro-orm/postgresql": "^7.1.5",
63
- "@open-mercato/queue": "0.6.7-develop.6597.1.b8f069b7fe",
64
- "@open-mercato/shared": "0.6.7-develop.6597.1.b8f069b7fe",
63
+ "@open-mercato/queue": "0.6.7-develop.6603.1.78e5b7a65d",
64
+ "@open-mercato/shared": "0.6.7-develop.6603.1.78e5b7a65d",
65
65
  "cross-spawn": "^7.0.6",
66
66
  "pg": "8.22.0",
67
67
  "semver": "^7.8.5",
@@ -72,10 +72,10 @@
72
72
  "typescript-js": "npm:typescript@6.0.3"
73
73
  },
74
74
  "peerDependencies": {
75
- "@open-mercato/shared": "0.6.7-develop.6597.1.b8f069b7fe"
75
+ "@open-mercato/shared": "0.6.7-develop.6603.1.78e5b7a65d"
76
76
  },
77
77
  "devDependencies": {
78
- "@open-mercato/shared": "0.6.7-develop.6597.1.b8f069b7fe",
78
+ "@open-mercato/shared": "0.6.7-develop.6603.1.78e5b7a65d",
79
79
  "@types/jest": "^30.0.0",
80
80
  "jest": "^30.4.2",
81
81
  "ts-jest": "^29.4.11"
@@ -362,4 +362,89 @@ describe('eject', () => {
362
362
  )
363
363
  })
364
364
  })
365
+
366
+ // Regression guards for #4272: standalone installs resolve getModulePaths'
367
+ // pkgBase to node_modules/<pkg>/dist/modules (compiled JS, no index.ts), so
368
+ // eject reported every module as "not marked as ejectable" and --list came up
369
+ // (nearly) empty. Ejection must prefer the shipped src/modules TypeScript.
370
+ describe('standalone installs (#4272)', () => {
371
+ function createStandaloneResolver(baseDir: string, options: { shipSrc: boolean }): PackageResolver {
372
+ const appDir = path.join(baseDir, 'app')
373
+ const modulesTsPath = path.join(appDir, 'src', 'modules.ts')
374
+ const packageRoot = path.join(baseDir, 'node_modules', '@open-mercato', 'core')
375
+ const distModuleDir = path.join(packageRoot, 'dist', 'modules', 'customers')
376
+ const srcModuleDir = path.join(packageRoot, 'src', 'modules', 'customers')
377
+
378
+ fs.mkdirSync(path.join(appDir, 'src'), { recursive: true })
379
+ fs.mkdirSync(distModuleDir, { recursive: true })
380
+ fs.writeFileSync(
381
+ path.join(appDir, 'src', 'modules.ts'),
382
+ "export const enabledModules = [{ id: 'customers', from: '@open-mercato/core' }]\n",
383
+ )
384
+ fs.writeFileSync(
385
+ path.join(distModuleDir, 'index.js'),
386
+ 'var metadata = { title: "Customers", description: "Compiled", ejectable: true };\nexport { metadata };\n',
387
+ )
388
+ fs.writeFileSync(path.join(distModuleDir, 'index.js.map'), '{}\n')
389
+
390
+ if (options.shipSrc) {
391
+ fs.mkdirSync(srcModuleDir, { recursive: true })
392
+ fs.writeFileSync(
393
+ path.join(srcModuleDir, 'index.ts'),
394
+ "export const metadata = { title: 'Customers', description: 'Source', ejectable: true }\n",
395
+ )
396
+ fs.writeFileSync(path.join(srcModuleDir, 'acl.ts'), 'export const features = []\n')
397
+ }
398
+
399
+ return {
400
+ getAppDir: () => appDir,
401
+ getModulesConfigPath: () => modulesTsPath,
402
+ loadEnabledModules: () => [{ id: 'customers', from: '@open-mercato/core' }],
403
+ getModulePaths: () => ({
404
+ appBase: path.join(appDir, 'src', 'modules', 'customers'),
405
+ pkgBase: distModuleDir,
406
+ }),
407
+ getPackageRoot: () => packageRoot,
408
+ } as unknown as PackageResolver
409
+ }
410
+
411
+ it('lists core modules as ejectable when pkgBase points at dist/modules', () => {
412
+ const resolver = createStandaloneResolver(tmpDir, { shipSrc: true })
413
+
414
+ expect(listEjectableModules(resolver)).toEqual([
415
+ {
416
+ id: 'customers',
417
+ title: 'Customers',
418
+ description: 'Source',
419
+ from: '@open-mercato/core',
420
+ },
421
+ ])
422
+ })
423
+
424
+ it('ejects the shipped TypeScript sources, not the compiled dist output', () => {
425
+ const resolver = createStandaloneResolver(tmpDir, { shipSrc: true })
426
+ const appModuleDir = path.join(tmpDir, 'app', 'src', 'modules', 'customers')
427
+ const modulesTsPath = path.join(tmpDir, 'app', 'src', 'modules.ts')
428
+
429
+ ejectModule(resolver, 'customers')
430
+
431
+ expect(fs.existsSync(path.join(appModuleDir, 'index.ts'))).toBe(true)
432
+ expect(fs.existsSync(path.join(appModuleDir, 'acl.ts'))).toBe(true)
433
+ expect(fs.existsSync(path.join(appModuleDir, 'index.js'))).toBe(false)
434
+ expect(fs.readFileSync(modulesTsPath, 'utf8')).toContain("{ id: 'customers', from: '@app' }")
435
+ })
436
+
437
+ it('falls back to compiled index.js metadata for dist-only packages', () => {
438
+ const resolver = createStandaloneResolver(tmpDir, { shipSrc: false })
439
+
440
+ expect(listEjectableModules(resolver)).toEqual([
441
+ {
442
+ id: 'customers',
443
+ title: 'Customers',
444
+ description: 'Compiled',
445
+ from: '@open-mercato/core',
446
+ },
447
+ ])
448
+ })
449
+ })
365
450
  })
package/src/lib/eject.ts CHANGED
@@ -194,12 +194,34 @@ type ResolvedModuleSource = {
194
194
  metadata: ModuleMetadata
195
195
  }
196
196
 
197
+ // Standalone installs resolve getModulePaths' pkgBase to the package's
198
+ // dist/modules tree when it exists (compiled JS, no index.ts), which made every
199
+ // ejectable module read as "not ejectable" and eject copies of compiled output
200
+ // (#4272). Prefer the shipped TypeScript sources under src/modules; fall back
201
+ // to the resolved base for packages that ship dist only.
202
+ function resolveModuleSourceBase(resolver: PackageResolver, entry: ModuleEntry): string {
203
+ const { pkgBase } = resolver.getModulePaths(entry)
204
+ const from = entry.from || '@open-mercato/core'
205
+ if (from === '@app') return pkgBase
206
+ const sourceBase = path.join(resolver.getPackageRoot(from), 'src', 'modules', entry.id)
207
+ if (path.resolve(sourceBase) !== path.resolve(pkgBase) && fs.existsSync(sourceBase)) {
208
+ return sourceBase
209
+ }
210
+ return pkgBase
211
+ }
212
+
213
+ function readModuleMetadata(moduleDir: string): ModuleMetadata {
214
+ const tsIndex = path.join(moduleDir, 'index.ts')
215
+ if (fs.existsSync(tsIndex)) return parseModuleMetadata(tsIndex)
216
+ return parseModuleMetadata(path.join(moduleDir, 'index.js'))
217
+ }
218
+
197
219
  function resolveModuleSource(
198
220
  resolver: PackageResolver,
199
221
  entry: ModuleEntry,
200
222
  ): ResolvedModuleSource {
201
- const { pkgBase } = resolver.getModulePaths(entry)
202
- const fallbackMetadata = parseModuleMetadata(path.join(pkgBase, 'index.ts'))
223
+ const pkgBase = resolveModuleSourceBase(resolver, entry)
224
+ const fallbackMetadata = readModuleMetadata(pkgBase)
203
225
  const from = entry.from || '@open-mercato/core'
204
226
 
205
227
  if (from === '@app' || from === '@open-mercato/core') {