@open-mercato/cli 0.8.1-develop.7241.1.fad7b2ce2a → 0.8.1-develop.7261.1.5d42353f61

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 (92) hide show
  1. package/dist/agentic/guides/module-facts.json +158 -152
  2. package/dist/agentic/guides/module-facts.v2.json +158 -152
  3. package/dist/agentic/guides/modules/agent_orchestrator/index.md +1 -1
  4. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  5. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  6. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  7. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  8. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  9. package/dist/agentic/guides/modules/auth/di-registrations-rich.md +2 -2
  10. package/dist/agentic/guides/modules/auth/index.md +1 -1
  11. package/dist/agentic/guides/modules/availability/index.md +1 -1
  12. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  13. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  14. package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
  15. package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
  16. package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
  17. package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
  18. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  19. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  20. package/dist/agentic/guides/modules/channel_resend/index.md +1 -1
  21. package/dist/agentic/guides/modules/channel_ses/index.md +1 -1
  22. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  23. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  24. package/dist/agentic/guides/modules/configs/index.md +1 -1
  25. package/dist/agentic/guides/modules/content/index.md +1 -1
  26. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  27. package/dist/agentic/guides/modules/customer_accounts/di-registrations-rich.md +1 -1
  28. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  29. package/dist/agentic/guides/modules/customers/index.md +1 -1
  30. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  31. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  32. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  33. package/dist/agentic/guides/modules/devices/index.md +1 -1
  34. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  35. package/dist/agentic/guides/modules/directory/index.md +1 -1
  36. package/dist/agentic/guides/modules/documents/index.md +1 -1
  37. package/dist/agentic/guides/modules/entities/index.md +1 -1
  38. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  39. package/dist/agentic/guides/modules/events/index.md +1 -1
  40. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  41. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  42. package/dist/agentic/guides/modules/generators/index.md +1 -1
  43. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  44. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  45. package/dist/agentic/guides/modules/messages/index.md +1 -1
  46. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  47. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  48. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  49. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  50. package/dist/agentic/guides/modules/phone_calls/index.md +1 -1
  51. package/dist/agentic/guides/modules/planner/index.md +1 -1
  52. package/dist/agentic/guides/modules/portal/index.md +1 -1
  53. package/dist/agentic/guides/modules/progress/index.md +1 -1
  54. package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
  55. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  56. package/dist/agentic/guides/modules/record_locks/di-registrations-rich.md +3 -3
  57. package/dist/agentic/guides/modules/record_locks/di-service-tokens.md +2 -2
  58. package/dist/agentic/guides/modules/record_locks/exact-override-targets.md +2 -2
  59. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  60. package/dist/agentic/guides/modules/resources/index.md +1 -1
  61. package/dist/agentic/guides/modules/sales/index.md +1 -1
  62. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  63. package/dist/agentic/guides/modules/search/index.md +1 -1
  64. package/dist/agentic/guides/modules/security/index.md +1 -1
  65. package/dist/agentic/guides/modules/seeds/index.md +1 -1
  66. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  67. package/dist/agentic/guides/modules/sso/index.md +1 -1
  68. package/dist/agentic/guides/modules/staff/index.md +1 -1
  69. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  70. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  71. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  72. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  73. package/dist/agentic/guides/modules/tillio/index.md +1 -1
  74. package/dist/agentic/guides/modules/translations/index.md +1 -1
  75. package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
  76. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  77. package/dist/agentic/guides/modules/wms/index.md +1 -1
  78. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  79. package/dist/agentic/guides/reference-module-facts.json +1 -1
  80. package/dist/agentic/guides/upstream/manifest.json +1 -1
  81. package/dist/lib/generate-watch-events.js +19 -1
  82. package/dist/lib/generate-watch-events.js.map +2 -2
  83. package/dist/lib/generators/module-package-sources.js +17 -4
  84. package/dist/lib/generators/module-package-sources.js.map +2 -2
  85. package/dist/mercato.js +11 -16
  86. package/dist/mercato.js.map +2 -2
  87. package/package.json +6 -6
  88. package/src/lib/__tests__/generate-watch-events.test.ts +137 -0
  89. package/src/lib/generate-watch-events.ts +31 -0
  90. package/src/lib/generators/__tests__/module-package-sources.test.ts +89 -6
  91. package/src/lib/generators/module-package-sources.ts +17 -5
  92. package/src/mercato.ts +16 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.8.1-develop.7241.1.fad7b2ce2a",
3
+ "version": "0.8.1-develop.7261.1.5d42353f61",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,9 +60,9 @@
60
60
  "@mikro-orm/decorators": "^7.1.14",
61
61
  "@mikro-orm/migrations": "^7.1.14",
62
62
  "@mikro-orm/postgresql": "^7.1.14",
63
- "@open-mercato/queue": "0.8.1-develop.7241.1.fad7b2ce2a",
64
- "@open-mercato/shared": "0.8.1-develop.7241.1.fad7b2ce2a",
65
- "@open-mercato/telemetry": "0.8.1-develop.7241.1.fad7b2ce2a",
63
+ "@open-mercato/queue": "0.8.1-develop.7261.1.5d42353f61",
64
+ "@open-mercato/shared": "0.8.1-develop.7261.1.5d42353f61",
65
+ "@open-mercato/telemetry": "0.8.1-develop.7261.1.5d42353f61",
66
66
  "cross-spawn": "^7.0.6",
67
67
  "pg": "8.23.0",
68
68
  "semver": "^7.8.5",
@@ -73,10 +73,10 @@
73
73
  "typescript-js": "npm:typescript@6.0.3"
74
74
  },
75
75
  "peerDependencies": {
76
- "@open-mercato/shared": "0.8.1-develop.7241.1.fad7b2ce2a"
76
+ "@open-mercato/shared": "0.8.1-develop.7261.1.5d42353f61"
77
77
  },
78
78
  "devDependencies": {
79
- "@open-mercato/shared": "0.8.1-develop.7241.1.fad7b2ce2a",
79
+ "@open-mercato/shared": "0.8.1-develop.7261.1.5d42353f61",
80
80
  "@types/jest": "^30.0.0",
81
81
  "jest": "^30.4.2",
82
82
  "ts-jest": "^29.4.12"
@@ -3,6 +3,7 @@ import os from 'node:os'
3
3
  import path from 'node:path'
4
4
  import {
5
5
  createGenerateWatchChangeSignal,
6
+ resolveGenerateWatchTargets,
6
7
  type GenerateWatchTarget,
7
8
  } from '../generate-watch-events'
8
9
 
@@ -40,6 +41,142 @@ function createWatchHarness(initialTargets: GenerateWatchTarget[]) {
40
41
  }
41
42
 
42
43
  describe('createGenerateWatchChangeSignal', () => {
44
+ it('keeps app-module watches idle without inventing a node_modules/@app target', async () => {
45
+ const projectRoot = path.resolve('/virtual/standalone-app')
46
+ const modulesFile = path.join(projectRoot, 'src', 'modules.ts')
47
+ const appBase = path.join(projectRoot, 'src', 'modules', 'custom_module')
48
+ const impossiblePackageBase = path.join(
49
+ projectRoot,
50
+ 'node_modules',
51
+ '@app',
52
+ 'src',
53
+ 'modules',
54
+ 'custom_module',
55
+ )
56
+ const resolveSourceMirrorBase = jest.fn(() => null)
57
+ const targets = resolveGenerateWatchTargets({
58
+ modulesFile,
59
+ moduleRoots: [{
60
+ appBase,
61
+ pkgBase: impossiblePackageBase,
62
+ watchPackageBase: false,
63
+ }],
64
+ resolveSourceMirrorBase,
65
+ })
66
+
67
+ expect(targets).toEqual([
68
+ {
69
+ directory: path.dirname(modulesFile),
70
+ recursive: false,
71
+ fileName: path.basename(modulesFile),
72
+ },
73
+ {
74
+ directory: path.dirname(appBase),
75
+ recursive: true,
76
+ },
77
+ ])
78
+ expect(resolveSourceMirrorBase).not.toHaveBeenCalled()
79
+
80
+ const signal = createGenerateWatchChangeSignal({
81
+ getWatchTargets: () => targets,
82
+ directoryExists: () => true,
83
+ watchDirectory: () => ({ close: jest.fn() }),
84
+ })
85
+ await signal.refresh()
86
+ expect(signal.hasSkippedTargets?.()).toBe(false)
87
+ await signal.close()
88
+ })
89
+
90
+ it('retains the real package fallback target for app modules in monorepo mode', () => {
91
+ const projectRoot = path.resolve('/virtual/monorepo')
92
+ const modulesFile = path.join(projectRoot, 'apps', 'mercato', 'src', 'modules.ts')
93
+ const appBase = path.join(
94
+ projectRoot,
95
+ 'apps',
96
+ 'mercato',
97
+ 'src',
98
+ 'modules',
99
+ 'custom_module',
100
+ )
101
+ const packageBase = path.join(
102
+ projectRoot,
103
+ 'packages',
104
+ 'core',
105
+ 'src',
106
+ 'modules',
107
+ 'custom_module',
108
+ )
109
+ const resolveSourceMirrorBase = jest.fn(() => null)
110
+
111
+ const targets = resolveGenerateWatchTargets({
112
+ modulesFile,
113
+ moduleRoots: [{
114
+ appBase,
115
+ pkgBase: packageBase,
116
+ watchPackageBase: true,
117
+ }],
118
+ resolveSourceMirrorBase,
119
+ })
120
+
121
+ expect(targets).toContainEqual({
122
+ directory: path.dirname(appBase),
123
+ recursive: true,
124
+ })
125
+ expect(targets).toContainEqual({
126
+ directory: path.dirname(packageBase),
127
+ recursive: true,
128
+ })
129
+ expect(resolveSourceMirrorBase).toHaveBeenCalledWith(packageBase)
130
+ })
131
+
132
+ it('retains missing package-module targets so idle refresh discovers them later', async () => {
133
+ const projectRoot = path.resolve('/virtual/standalone-app')
134
+ const modulesFile = path.join(projectRoot, 'src', 'modules.ts')
135
+ const appBase = path.join(projectRoot, 'src', 'modules', 'official_module')
136
+ const packageBase = path.join(
137
+ projectRoot,
138
+ 'node_modules',
139
+ '@open-mercato',
140
+ 'official-package',
141
+ 'dist',
142
+ 'modules',
143
+ 'official_module',
144
+ )
145
+ const packageModulesDir = path.dirname(packageBase)
146
+ const targets = resolveGenerateWatchTargets({
147
+ modulesFile,
148
+ moduleRoots: [{
149
+ appBase,
150
+ pkgBase: packageBase,
151
+ watchPackageBase: true,
152
+ }],
153
+ resolveSourceMirrorBase: () => null,
154
+ })
155
+ const existing = new Set([
156
+ path.dirname(modulesFile),
157
+ path.dirname(appBase),
158
+ ])
159
+ const registered: string[] = []
160
+ const signal = createGenerateWatchChangeSignal({
161
+ getWatchTargets: () => targets,
162
+ directoryExists: (directory) => existing.has(directory),
163
+ watchDirectory: (target) => {
164
+ registered.push(target.directory)
165
+ return { close: jest.fn() }
166
+ },
167
+ })
168
+
169
+ await signal.refresh()
170
+ expect(signal.hasSkippedTargets?.()).toBe(true)
171
+ expect(registered).not.toContain(packageModulesDir)
172
+
173
+ existing.add(packageModulesDir)
174
+ await signal.refresh()
175
+ expect(signal.hasSkippedTargets?.()).toBe(false)
176
+ expect(registered).toContain(packageModulesDir)
177
+ await signal.close()
178
+ })
179
+
43
180
  it('skips missing directories without falling back and retries them on refresh', async () => {
44
181
  const present = path.resolve('./modules-present')
45
182
  const delayed = path.resolve('./modules-delayed')
@@ -25,6 +25,37 @@ export type GenerateWatchChangeSignalOptions = {
25
25
  onSkippedDirectory?: (directory: string) => void
26
26
  }
27
27
 
28
+ export type GenerateWatchModuleTarget = {
29
+ appBase: string
30
+ pkgBase: string
31
+ watchPackageBase: boolean
32
+ }
33
+
34
+ export function resolveGenerateWatchTargets(options: {
35
+ modulesFile: string
36
+ moduleRoots: GenerateWatchModuleTarget[]
37
+ resolveSourceMirrorBase: (packageBase: string) => string | null
38
+ }): GenerateWatchTarget[] {
39
+ const targets: GenerateWatchTarget[] = [{
40
+ directory: path.dirname(options.modulesFile),
41
+ recursive: false,
42
+ fileName: path.basename(options.modulesFile),
43
+ }]
44
+
45
+ for (const roots of options.moduleRoots) {
46
+ targets.push({ directory: path.dirname(roots.appBase), recursive: true })
47
+ if (!roots.watchPackageBase) continue
48
+
49
+ targets.push({ directory: path.dirname(roots.pkgBase), recursive: true })
50
+ const sourceMirror = options.resolveSourceMirrorBase(roots.pkgBase)
51
+ if (sourceMirror) {
52
+ targets.push({ directory: path.dirname(sourceMirror), recursive: true })
53
+ }
54
+ }
55
+
56
+ return targets
57
+ }
58
+
28
59
  function targetKey(target: GenerateWatchTarget): string {
29
60
  return JSON.stringify([
30
61
  path.resolve(target.directory),
@@ -3,6 +3,7 @@ import os from 'node:os'
3
3
  import path from 'node:path'
4
4
  import { generateModulePackageSources } from '../module-package-sources'
5
5
  import type { PackageResolver } from '../../resolver'
6
+ import { readChecksumRecord } from '../../utils'
6
7
 
7
8
  const fixturePackageRoot = path.resolve(
8
9
  __dirname,
@@ -25,7 +26,7 @@ function copyDir(src: string, dest: string): void {
25
26
  }
26
27
  }
27
28
 
28
- function createResolver(tmpDir: string, packageRoot: string, from: string): PackageResolver {
29
+ function createResolver(tmpDir: string, packageRoot: string, from: string, moduleId = 'test_package'): PackageResolver {
29
30
  const appDir = path.join(tmpDir, 'app')
30
31
  const outputDir = path.join(appDir, '.mercato', 'generated')
31
32
  fs.mkdirSync(outputDir, { recursive: true })
@@ -37,14 +38,14 @@ function createResolver(tmpDir: string, packageRoot: string, from: string): Pack
37
38
  getOutputDir: () => outputDir,
38
39
  getModulesConfigPath: () => path.join(appDir, 'src', 'modules.ts'),
39
40
  discoverPackages: () => [],
40
- loadEnabledModules: () => [{ id: 'test_package', from }],
41
+ loadEnabledModules: () => [{ id: moduleId, from }],
41
42
  getModulePaths: () => ({
42
- appBase: path.join(appDir, 'src', 'modules', 'test_package'),
43
- pkgBase: path.join(packageRoot, 'src', 'modules', 'test_package'),
43
+ appBase: path.join(appDir, 'src', 'modules', moduleId),
44
+ pkgBase: path.join(packageRoot, 'src', 'modules', moduleId),
44
45
  }),
45
46
  getModuleImportBase: () => ({
46
- appBase: '@/modules/test_package',
47
- pkgBase: `${from}/modules/test_package`,
47
+ appBase: `@/modules/${moduleId}`,
48
+ pkgBase: `${from}/modules/${moduleId}`,
48
49
  }),
49
50
  getPackageOutputDir: () => outputDir,
50
51
  getPackageRoot: () => packageRoot,
@@ -75,6 +76,88 @@ describe('generateModulePackageSources', () => {
75
76
  expect(output).toContain('node_modules/@open-mercato/test-package/src/**/*.{ts,tsx}')
76
77
  })
77
78
 
79
+ it('does not checksum unrelated files below the installed package root', async () => {
80
+ const packageRoot = path.join(tmpDir, 'node_modules', '@open-mercato', 'test-package')
81
+ copyDir(fixturePackageRoot, packageRoot)
82
+ const resolver = createResolver(tmpDir, packageRoot, '@open-mercato/test-package')
83
+ const outFile = path.join(resolver.getOutputDir(), 'module-package-sources.css')
84
+ const checksumFile = path.join(resolver.getOutputDir(), 'module-package-sources.checksum')
85
+
86
+ await generateModulePackageSources({ resolver, quiet: true })
87
+ const outputBefore = fs.readFileSync(outFile, 'utf8')
88
+ const checksumBefore = readChecksumRecord(checksumFile)
89
+ const pinnedTime = new Date(Date.now() - 60_000)
90
+ fs.utimesSync(outFile, pinnedTime, pinnedTime)
91
+ fs.utimesSync(checksumFile, pinnedTime, pinnedTime)
92
+
93
+ fs.writeFileSync(path.join(packageRoot, 'src', 'unrelated-runtime.ts'), 'export const unrelated = true\n')
94
+ const result = await generateModulePackageSources({ resolver, quiet: true })
95
+
96
+ expect(result.filesWritten).toEqual([])
97
+ expect(result.filesUnchanged).toEqual([outFile])
98
+ expect(fs.readFileSync(outFile, 'utf8')).toBe(outputBefore)
99
+ expect(fs.statSync(outFile).mtimeMs).toBe(pinnedTime.getTime())
100
+ expect(fs.statSync(checksumFile).mtimeMs).toBe(pinnedTime.getTime())
101
+ expect(readChecksumRecord(checksumFile)).toEqual(checksumBefore)
102
+ })
103
+
104
+ it('tracks enabled module and package manifest inputs without touching byte-identical output', async () => {
105
+ const packageRoot = path.join(tmpDir, 'node_modules', '@open-mercato', 'test-package')
106
+ copyDir(fixturePackageRoot, packageRoot)
107
+ copyDir(
108
+ path.join(packageRoot, 'src', 'modules', 'test_package'),
109
+ path.join(packageRoot, 'src', 'modules', 'alternate_module'),
110
+ )
111
+ copyDir(
112
+ path.join(packageRoot, 'dist', 'modules', 'test_package'),
113
+ path.join(packageRoot, 'dist', 'modules', 'alternate_module'),
114
+ )
115
+ const packageName = '@open-mercato/test-package'
116
+ const initialResolver = createResolver(tmpDir, packageRoot, packageName)
117
+ const alternateResolver = createResolver(tmpDir, packageRoot, packageName, 'alternate_module')
118
+ const outFile = path.join(initialResolver.getOutputDir(), 'module-package-sources.css')
119
+ const checksumFile = path.join(initialResolver.getOutputDir(), 'module-package-sources.checksum')
120
+
121
+ await generateModulePackageSources({ resolver: initialResolver, quiet: true })
122
+ const outputBefore = fs.readFileSync(outFile, 'utf8')
123
+ const initialStructure = readChecksumRecord(checksumFile)?.structure
124
+ const pinnedTime = new Date(Date.now() - 60_000)
125
+ fs.utimesSync(outFile, pinnedTime, pinnedTime)
126
+
127
+ await generateModulePackageSources({ resolver: alternateResolver, quiet: true })
128
+ const alternateStructure = readChecksumRecord(checksumFile)?.structure
129
+ expect(alternateStructure).not.toBe(initialStructure)
130
+ expect(fs.readFileSync(outFile, 'utf8')).toBe(outputBefore)
131
+ expect(fs.statSync(outFile).mtimeMs).toBe(pinnedTime.getTime())
132
+
133
+ const packageJsonPath = path.join(packageRoot, 'package.json')
134
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as Record<string, unknown>
135
+ packageJson.version = '0.2.0'
136
+ fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`)
137
+ const result = await generateModulePackageSources({ resolver: alternateResolver, quiet: true })
138
+
139
+ expect(readChecksumRecord(checksumFile)?.structure).not.toBe(alternateStructure)
140
+ expect(result.filesWritten).toEqual([])
141
+ expect(result.filesUnchanged).toEqual([outFile])
142
+ expect(fs.readFileSync(outFile, 'utf8')).toBe(outputBefore)
143
+ expect(fs.statSync(outFile).mtimeMs).toBe(pinnedTime.getTime())
144
+ })
145
+
146
+ it('keeps official package validation as the source inclusion gate', async () => {
147
+ const packageRoot = path.join(tmpDir, 'node_modules', '@open-mercato', 'test-package')
148
+ copyDir(fixturePackageRoot, packageRoot)
149
+ const packageJsonPath = path.join(packageRoot, 'package.json')
150
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as Record<string, unknown>
151
+ packageJson.name = '@open-mercato/different-package'
152
+ fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`)
153
+ const resolver = createResolver(tmpDir, packageRoot, '@open-mercato/test-package')
154
+
155
+ await generateModulePackageSources({ resolver, quiet: true })
156
+
157
+ const output = fs.readFileSync(path.join(resolver.getOutputDir(), 'module-package-sources.css'), 'utf8')
158
+ expect(output).toBe('')
159
+ })
160
+
78
161
  it('skips app-backed modules', async () => {
79
162
  const packageRoot = path.join(tmpDir, 'node_modules', '@open-mercato', 'test-package')
80
163
  copyDir(fixturePackageRoot, packageRoot)
@@ -1,8 +1,7 @@
1
- import fs from 'node:fs'
2
1
  import path from 'node:path'
3
2
  import { readOfficialModulePackageFromRoot, resolveInstalledPackageRoot } from '../module-package'
4
3
  import type { PackageResolver } from '../resolver'
5
- import { calculateStructureChecksum, createGeneratorResult, type GeneratorResult, writeGeneratedFile } from '../utils'
4
+ import { calculateChecksum, createGeneratorResult, type GeneratorResult, writeGeneratedFile } from '../utils'
6
5
 
7
6
  export interface ModulePackageSourcesOptions {
8
7
  resolver: PackageResolver
@@ -23,13 +22,12 @@ export async function generateModulePackageSources(
23
22
  const outFile = path.join(outputDir, 'module-package-sources.css')
24
23
  const checksumFile = path.join(outputDir, 'module-package-sources.checksum')
25
24
  const sourcePaths = new Set<string>()
26
- const checksumTargets: string[] = []
25
+ const checksumInputs = new Set<string>()
27
26
 
28
27
  for (const entry of resolver.loadEnabledModules()) {
29
28
  if (!entry.from || entry.from === '@app' || entry.from === '@open-mercato/core') continue
30
29
 
31
30
  const packageRoot = resolveInstalledPackageRoot(resolver, entry.from)
32
- checksumTargets.push(packageRoot)
33
31
 
34
32
  let modulePackage
35
33
  try {
@@ -39,12 +37,26 @@ export async function generateModulePackageSources(
39
37
  }
40
38
 
41
39
  const packageSourceRoot = path.join(modulePackage.packageRoot, 'src')
40
+ checksumInputs.add(JSON.stringify({
41
+ entry: {
42
+ from: entry.from,
43
+ id: entry.id,
44
+ },
45
+ packageName: modulePackage.packageName,
46
+ packageRoot: path.resolve(modulePackage.packageRoot),
47
+ packageJson: modulePackage.packageJson,
48
+ packageSourceRoot,
49
+ sourceModuleDir: path.resolve(modulePackage.sourceModuleDir),
50
+ distModuleDir: path.resolve(modulePackage.distModuleDir),
51
+ }))
42
52
  const relativeSourcePath = normalizeCssSourcePath(path.relative(path.dirname(outFile), packageSourceRoot))
43
53
  sourcePaths.add(`@source "${relativeSourcePath}/**/*.{ts,tsx}";`)
44
54
  }
45
55
 
46
56
  const content = `${Array.from(sourcePaths).sort((left, right) => left.localeCompare(right)).join('\n')}${sourcePaths.size > 0 ? '\n' : ''}`
47
- const structureChecksum = calculateStructureChecksum(checksumTargets)
57
+ const structureChecksum = calculateChecksum(
58
+ Array.from(checksumInputs).sort((left, right) => left.localeCompare(right)).join('\n'),
59
+ )
48
60
 
49
61
  writeGeneratedFile({
50
62
  outFile,
package/src/mercato.ts CHANGED
@@ -825,7 +825,7 @@ async function createGenerateWatchRuntime(quiet = false) {
825
825
  const [
826
826
  { createResolver },
827
827
  { calculateGenerateWatchStructureChecksum },
828
- { createGenerateWatchChangeSignal },
828
+ { createGenerateWatchChangeSignal, resolveGenerateWatchTargets },
829
829
  { resolveStandaloneSourceMirrorBase },
830
830
  ] = await Promise.all([
831
831
  import('./lib/resolver'),
@@ -836,10 +836,18 @@ async function createGenerateWatchRuntime(quiet = false) {
836
836
 
837
837
  const collectWatchState = () => {
838
838
  const resolver = createResolver()
839
- const moduleRoots = []
839
+ const moduleRoots: Array<{
840
+ appBase: string
841
+ pkgBase: string
842
+ watchPackageBase: boolean
843
+ }> = []
844
+ const watchAppPackageFallbacks = resolver.isMonorepo()
840
845
  for (const entry of resolver.loadEnabledModules()) {
841
846
  const roots = resolver.getModulePaths(entry)
842
- moduleRoots.push({ appBase: roots.appBase, pkgBase: roots.pkgBase })
847
+ moduleRoots.push({
848
+ ...roots,
849
+ watchPackageBase: entry.from !== '@app' || watchAppPackageFallbacks,
850
+ })
843
851
  }
844
852
  return {
845
853
  modulesFile: resolver.getModulesConfigPath(),
@@ -857,20 +865,11 @@ async function createGenerateWatchRuntime(quiet = false) {
857
865
  : (directory) => console.log(`[generate:watch] Skipping missing watch directory: ${directory}`),
858
866
  getWatchTargets: () => {
859
867
  const state = collectWatchState()
860
- const targets: Array<{ directory: string; recursive: boolean; fileName?: string }> = [{
861
- directory: path.dirname(state.modulesFile),
862
- recursive: false,
863
- fileName: path.basename(state.modulesFile),
864
- }]
865
- for (const roots of state.moduleRoots) {
866
- targets.push({ directory: path.dirname(roots.appBase), recursive: true })
867
- targets.push({ directory: path.dirname(roots.pkgBase), recursive: true })
868
- const sourceMirror = resolveStandaloneSourceMirrorBase(roots.pkgBase)
869
- if (sourceMirror) {
870
- targets.push({ directory: path.dirname(sourceMirror), recursive: true })
871
- }
872
- }
873
- return targets
868
+ return resolveGenerateWatchTargets({
869
+ modulesFile: state.modulesFile,
870
+ moduleRoots: state.moduleRoots,
871
+ resolveSourceMirrorBase: resolveStandaloneSourceMirrorBase,
872
+ })
874
873
  },
875
874
  }),
876
875
  }