@open-mercato/cli 0.4.2-canary-f80d1bfa83 โ 0.4.2-canary-5035717565
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/db/commands.js +17 -8
- package/dist/lib/db/commands.js.map +2 -2
- package/dist/lib/generators/entity-ids.js +2 -3
- package/dist/lib/generators/entity-ids.js.map +2 -2
- package/dist/lib/generators/module-di.js +4 -6
- package/dist/lib/generators/module-di.js.map +2 -2
- package/dist/lib/generators/module-entities.js +3 -4
- package/dist/lib/generators/module-entities.js.map +2 -2
- package/dist/lib/generators/module-registry.js +72 -89
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +2 -2
- package/dist/lib/resolver.js.map +2 -2
- package/dist/mercato.js +21 -33
- package/dist/mercato.js.map +2 -2
- package/package.json +2 -2
- package/src/lib/db/commands.ts +19 -12
- package/src/lib/generators/entity-ids.ts +2 -4
- package/src/lib/generators/module-di.ts +4 -7
- package/src/lib/generators/module-entities.ts +3 -4
- package/src/lib/generators/module-registry.ts +76 -99
- package/src/lib/resolver.ts +5 -4
- package/src/mercato.ts +21 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.4.2-canary-
|
|
3
|
+
"version": "0.4.2-canary-5035717565",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@mikro-orm/core": "^6.6.2",
|
|
56
56
|
"@mikro-orm/migrations": "^6.6.2",
|
|
57
57
|
"@mikro-orm/postgresql": "^6.6.2",
|
|
58
|
-
"@open-mercato/shared": "0.4.2-canary-
|
|
58
|
+
"@open-mercato/shared": "0.4.2-canary-5035717565",
|
|
59
59
|
"pg": "^8.16.3",
|
|
60
60
|
"typescript": "^5.9.3"
|
|
61
61
|
},
|
package/src/lib/db/commands.ts
CHANGED
|
@@ -77,8 +77,7 @@ async function loadModuleEntities(entry: ModuleEntry, resolver: PackageResolver)
|
|
|
77
77
|
path.join(roots.appBase, 'db'),
|
|
78
78
|
path.join(roots.pkgBase, 'db'),
|
|
79
79
|
]
|
|
80
|
-
|
|
81
|
-
const candidates = ['entities.ts', 'entities.js', 'schema.ts', 'schema.js']
|
|
80
|
+
const candidates = ['entities.ts', 'schema.ts']
|
|
82
81
|
|
|
83
82
|
for (const base of bases) {
|
|
84
83
|
for (const f of candidates) {
|
|
@@ -86,12 +85,10 @@ async function loadModuleEntities(entry: ModuleEntry, resolver: PackageResolver)
|
|
|
86
85
|
if (fs.existsSync(p)) {
|
|
87
86
|
const sub = path.basename(base)
|
|
88
87
|
const fromApp = base.startsWith(roots.appBase)
|
|
89
|
-
const ext = path.extname(f)
|
|
90
|
-
const baseName = f.replace(ext, '')
|
|
91
88
|
// For @app modules, use file:// URL since @/ alias doesn't work in Node.js runtime
|
|
92
89
|
const importPath = (isAppModule && fromApp)
|
|
93
90
|
? `file://${p.replace(/\.ts$/, '.js')}`
|
|
94
|
-
: `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${
|
|
91
|
+
: `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\.ts$/, '')}`
|
|
95
92
|
try {
|
|
96
93
|
const mod = await import(importPath)
|
|
97
94
|
const entities = Object.values(mod).filter((v) => typeof v === 'function')
|
|
@@ -110,15 +107,25 @@ async function loadModuleEntities(entry: ModuleEntry, resolver: PackageResolver)
|
|
|
110
107
|
|
|
111
108
|
function getMigrationsPath(entry: ModuleEntry, resolver: PackageResolver): string {
|
|
112
109
|
const from = entry.from || '@open-mercato/core'
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
let pkgModRoot: string
|
|
111
|
+
|
|
112
|
+
if (from === '@open-mercato/core') {
|
|
113
|
+
pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)
|
|
114
|
+
} else if (/^@open-mercato\//.test(from)) {
|
|
115
|
+
const segs = from.split('/')
|
|
116
|
+
if (segs.length > 1 && segs[1]) {
|
|
117
|
+
pkgModRoot = path.join(resolver.getRootDir(), `packages/${segs[1]}/src/modules`, entry.id)
|
|
118
|
+
} else {
|
|
119
|
+
pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)
|
|
120
|
+
}
|
|
121
|
+
} else if (from === '@app') {
|
|
122
|
+
// For @app modules, use the app directory not the monorepo root
|
|
123
|
+
pkgModRoot = path.join(resolver.getAppDir(), 'src/modules', entry.id)
|
|
124
|
+
} else {
|
|
125
|
+
pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)
|
|
117
126
|
}
|
|
118
127
|
|
|
119
|
-
|
|
120
|
-
const { pkgBase } = resolver.getModulePaths(entry)
|
|
121
|
-
return path.join(pkgBase, 'migrations')
|
|
128
|
+
return path.join(pkgModRoot, 'migrations')
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
export interface DbOptions {
|
|
@@ -179,8 +179,7 @@ export async function generateEntityIds(options: EntityIdsOptions): Promise<Gene
|
|
|
179
179
|
const appDb = path.join(roots.appBase, 'db')
|
|
180
180
|
const pkgDb = path.join(roots.pkgBase, 'db')
|
|
181
181
|
const bases = [appData, pkgData, appDb, pkgDb]
|
|
182
|
-
|
|
183
|
-
const candidates = ['entities.override.ts', 'entities.override.js', 'entities.ts', 'entities.js', 'schema.ts', 'schema.js']
|
|
182
|
+
const candidates = ['entities.override.ts', 'entities.ts', 'schema.ts']
|
|
184
183
|
let importPath: string | null = null
|
|
185
184
|
let filePath: string | null = null
|
|
186
185
|
|
|
@@ -190,8 +189,7 @@ export async function generateEntityIds(options: EntityIdsOptions): Promise<Gene
|
|
|
190
189
|
if (fs.existsSync(p)) {
|
|
191
190
|
const fromApp = base.startsWith(roots.appBase)
|
|
192
191
|
const sub = path.basename(base) // 'data' | 'db'
|
|
193
|
-
|
|
194
|
-
importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${fileBaseName}`
|
|
192
|
+
importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\.ts$/, '')}`
|
|
195
193
|
filePath = p
|
|
196
194
|
break
|
|
197
195
|
}
|
|
@@ -34,13 +34,10 @@ export async function generateModuleDi(options: ModuleDiOptions): Promise<Genera
|
|
|
34
34
|
const modId = entry.id
|
|
35
35
|
const roots = resolver.getModulePaths(entry)
|
|
36
36
|
const imp = resolver.getModuleImportBase(entry)
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const pkgDiJs = path.join(roots.pkgBase, 'di.js')
|
|
42
|
-
const useApp = fs.existsSync(appDiTs) || fs.existsSync(appDiJs)
|
|
43
|
-
const usePkg = fs.existsSync(pkgDiTs) || fs.existsSync(pkgDiJs)
|
|
37
|
+
const appDi = path.join(roots.appBase, 'di.ts')
|
|
38
|
+
const pkgDi = path.join(roots.pkgBase, 'di.ts')
|
|
39
|
+
const useApp = fs.existsSync(appDi)
|
|
40
|
+
const usePkg = fs.existsSync(pkgDi)
|
|
44
41
|
const importName = `D_${toVar(modId)}_${i++}`
|
|
45
42
|
|
|
46
43
|
if (useApp) {
|
|
@@ -41,7 +41,7 @@ export async function generateModuleEntities(options: ModuleEntitiesOptions): Pr
|
|
|
41
41
|
const appDb = path.join(roots.appBase, 'db')
|
|
42
42
|
const pkgDb = path.join(roots.pkgBase, 'db')
|
|
43
43
|
const bases = [appData, pkgData, appDb, pkgDb]
|
|
44
|
-
const candidates = ['entities.override.ts', 'entities.
|
|
44
|
+
const candidates = ['entities.override.ts', 'entities.ts', 'schema.ts']
|
|
45
45
|
|
|
46
46
|
let found: { base: string; file: string } | null = null
|
|
47
47
|
for (const base of bases) {
|
|
@@ -63,13 +63,12 @@ export async function generateModuleEntities(options: ModuleEntitiesOptions): Pr
|
|
|
63
63
|
// For @app modules, use relative path to ensure it works both in Next.js and Node.js CLI context
|
|
64
64
|
// From .mercato/generated/, the relative path to src/modules/ is ../src/modules/
|
|
65
65
|
let relImport: string
|
|
66
|
-
const fileBaseName = found.file.replace(/\.(ts|js)$/, '')
|
|
67
66
|
if (isAppModule && fromApp) {
|
|
68
67
|
// From .mercato/generated/, go up two levels (../..) to reach the app root, then into src/modules/
|
|
69
|
-
relImport = `../../src/modules/${modId}/${sub}/${
|
|
68
|
+
relImport = `../../src/modules/${modId}/${sub}/${found.file.replace(/\.ts$/, '')}`
|
|
70
69
|
} else {
|
|
71
70
|
const baseImport = fromApp ? imp.appBase : imp.pkgBase
|
|
72
|
-
relImport = `${baseImport}/${sub}/${
|
|
71
|
+
relImport = `${baseImport}/${sub}/${found.file.replace(/\.ts$/, '')}`
|
|
73
72
|
}
|
|
74
73
|
imports.push(`import * as ${importName} from '${relImport}'`)
|
|
75
74
|
entitySources.push({ importName, moduleId: modId })
|
|
@@ -15,21 +15,6 @@ import {
|
|
|
15
15
|
|
|
16
16
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* Find a module file, checking for both .ts (src) and .js (dist) extensions.
|
|
20
|
-
* Supports both simple names (e.g., 'cli') and nested paths (e.g., 'data/extensions').
|
|
21
|
-
* Returns the path if found, null otherwise.
|
|
22
|
-
*/
|
|
23
|
-
function findModuleFile(basePath: string, ...segments: string[]): string | null {
|
|
24
|
-
const name = segments.pop()!
|
|
25
|
-
const dir = segments.length ? path.join(basePath, ...segments) : basePath
|
|
26
|
-
const tsPath = path.join(dir, `${name}.ts`)
|
|
27
|
-
if (fs.existsSync(tsPath)) return tsPath
|
|
28
|
-
const jsPath = path.join(dir, `${name}.js`)
|
|
29
|
-
if (fs.existsSync(jsPath)) return jsPath
|
|
30
|
-
return null
|
|
31
|
-
}
|
|
32
|
-
|
|
33
18
|
export interface ModuleRegistryOptions {
|
|
34
19
|
resolver: PackageResolver
|
|
35
20
|
quiet?: boolean
|
|
@@ -94,9 +79,9 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
94
79
|
let injectionTableImportName: string | null = null
|
|
95
80
|
|
|
96
81
|
// Module metadata: index.ts (overrideable)
|
|
97
|
-
const appIndex =
|
|
98
|
-
const pkgIndex =
|
|
99
|
-
const indexTs = appIndex
|
|
82
|
+
const appIndex = path.join(roots.appBase, 'index.ts')
|
|
83
|
+
const pkgIndex = path.join(roots.pkgBase, 'index.ts')
|
|
84
|
+
const indexTs = fs.existsSync(appIndex) ? appIndex : fs.existsSync(pkgIndex) ? pkgIndex : null
|
|
100
85
|
if (indexTs) {
|
|
101
86
|
infoImportName = `I${importId++}_${toVar(modId)}`
|
|
102
87
|
const importPath = indexTs.startsWith(roots.appBase) ? `${appImportBase}/index` : `${imps.pkgBase}/index`
|
|
@@ -205,10 +190,10 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
205
190
|
|
|
206
191
|
// Entity extensions: src/modules/<module>/data/extensions.ts
|
|
207
192
|
{
|
|
208
|
-
const appFile =
|
|
209
|
-
const pkgFile =
|
|
210
|
-
const hasApp =
|
|
211
|
-
const hasPkg =
|
|
193
|
+
const appFile = path.join(roots.appBase, 'data', 'extensions.ts')
|
|
194
|
+
const pkgFile = path.join(roots.pkgBase, 'data', 'extensions.ts')
|
|
195
|
+
const hasApp = fs.existsSync(appFile)
|
|
196
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
212
197
|
if (hasApp || hasPkg) {
|
|
213
198
|
const importName = `X_${toVar(modId)}_${importId++}`
|
|
214
199
|
const importPath = hasApp ? `${appImportBase}/data/extensions` : `${imps.pkgBase}/data/extensions`
|
|
@@ -219,12 +204,12 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
219
204
|
|
|
220
205
|
// RBAC feature declarations: module root acl.ts
|
|
221
206
|
{
|
|
222
|
-
const rootApp =
|
|
223
|
-
const rootPkg =
|
|
224
|
-
const hasRoot = rootApp || rootPkg
|
|
207
|
+
const rootApp = path.join(roots.appBase, 'acl.ts')
|
|
208
|
+
const rootPkg = path.join(roots.pkgBase, 'acl.ts')
|
|
209
|
+
const hasRoot = fs.existsSync(rootApp) || fs.existsSync(rootPkg)
|
|
225
210
|
if (hasRoot) {
|
|
226
211
|
const importName = `ACL_${toVar(modId)}_${importId++}`
|
|
227
|
-
const useApp = rootApp
|
|
212
|
+
const useApp = fs.existsSync(rootApp) ? rootApp : rootPkg
|
|
228
213
|
const importPath = useApp.startsWith(roots.appBase) ? `${appImportBase}/acl` : `${imps.pkgBase}/acl`
|
|
229
214
|
imports.push(`import * as ${importName} from '${importPath}'`)
|
|
230
215
|
featuresImportName = importName
|
|
@@ -233,10 +218,10 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
233
218
|
|
|
234
219
|
// Custom entities declarations: module root ce.ts
|
|
235
220
|
{
|
|
236
|
-
const appFile =
|
|
237
|
-
const pkgFile =
|
|
238
|
-
const hasApp =
|
|
239
|
-
const hasPkg =
|
|
221
|
+
const appFile = path.join(roots.appBase, 'ce.ts')
|
|
222
|
+
const pkgFile = path.join(roots.pkgBase, 'ce.ts')
|
|
223
|
+
const hasApp = fs.existsSync(appFile)
|
|
224
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
240
225
|
if (hasApp || hasPkg) {
|
|
241
226
|
const importName = `CE_${toVar(modId)}_${importId++}`
|
|
242
227
|
const importPath = hasApp ? `${appImportBase}/ce` : `${imps.pkgBase}/ce`
|
|
@@ -247,10 +232,10 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
247
232
|
|
|
248
233
|
// Search module configuration: module root search.ts
|
|
249
234
|
{
|
|
250
|
-
const appFile =
|
|
251
|
-
const pkgFile =
|
|
252
|
-
const hasApp =
|
|
253
|
-
const hasPkg =
|
|
235
|
+
const appFile = path.join(roots.appBase, 'search.ts')
|
|
236
|
+
const pkgFile = path.join(roots.pkgBase, 'search.ts')
|
|
237
|
+
const hasApp = fs.existsSync(appFile)
|
|
238
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
254
239
|
if (hasApp || hasPkg) {
|
|
255
240
|
const importName = `SEARCH_${toVar(modId)}_${importId++}`
|
|
256
241
|
const importPath = hasApp ? `${appImportBase}/search` : `${imps.pkgBase}/search`
|
|
@@ -263,10 +248,10 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
263
248
|
|
|
264
249
|
// Custom field declarations: src/modules/<module>/data/fields.ts
|
|
265
250
|
{
|
|
266
|
-
const appFile =
|
|
267
|
-
const pkgFile =
|
|
268
|
-
const hasApp =
|
|
269
|
-
const hasPkg =
|
|
251
|
+
const appFile = path.join(roots.appBase, 'data', 'fields.ts')
|
|
252
|
+
const pkgFile = path.join(roots.pkgBase, 'data', 'fields.ts')
|
|
253
|
+
const hasApp = fs.existsSync(appFile)
|
|
254
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
270
255
|
if (hasApp || hasPkg) {
|
|
271
256
|
const importName = `F_${toVar(modId)}_${importId++}`
|
|
272
257
|
const importPath = hasApp ? `${appImportBase}/data/fields` : `${imps.pkgBase}/data/fields`
|
|
@@ -483,9 +468,9 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
483
468
|
}
|
|
484
469
|
|
|
485
470
|
// CLI
|
|
486
|
-
const cliApp =
|
|
487
|
-
const cliPkg =
|
|
488
|
-
const cliPath = cliApp
|
|
471
|
+
const cliApp = path.join(roots.appBase, 'cli.ts')
|
|
472
|
+
const cliPkg = path.join(roots.pkgBase, 'cli.ts')
|
|
473
|
+
const cliPath = fs.existsSync(cliApp) ? cliApp : fs.existsSync(cliPkg) ? cliPkg : null
|
|
489
474
|
if (cliPath) {
|
|
490
475
|
const importName = `CLI_${toVar(modId)}`
|
|
491
476
|
const importPath = cliPath.startsWith(roots.appBase) ? `${appImportBase}/cli` : `${imps.pkgBase}/cli`
|
|
@@ -525,7 +510,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
525
510
|
}
|
|
526
511
|
}
|
|
527
512
|
|
|
528
|
-
// Subscribers: src/modules/<module>/subscribers/*.ts
|
|
513
|
+
// Subscribers: src/modules/<module>/subscribers/*.ts
|
|
529
514
|
const subApp = path.join(roots.appBase, 'subscribers')
|
|
530
515
|
const subPkg = path.join(roots.pkgBase, 'subscribers')
|
|
531
516
|
if (fs.existsSync(subApp) || fs.existsSync(subPkg)) {
|
|
@@ -535,9 +520,8 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
535
520
|
if (e.isDirectory()) {
|
|
536
521
|
if (e.name === '__tests__' || e.name === '__mocks__') continue
|
|
537
522
|
walk(path.join(dir, e.name), [...rel, e.name])
|
|
538
|
-
} else if (e.isFile() &&
|
|
539
|
-
if (/\.(test|spec)\.
|
|
540
|
-
if (e.name.endsWith('.d.ts')) continue
|
|
523
|
+
} else if (e.isFile() && e.name.endsWith('.ts')) {
|
|
524
|
+
if (/\.(test|spec)\.ts$/.test(e.name)) continue
|
|
541
525
|
found.push([...rel, e.name].join('/'))
|
|
542
526
|
}
|
|
543
527
|
}
|
|
@@ -548,12 +532,11 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
548
532
|
for (const rel of files) {
|
|
549
533
|
const segs = rel.split('/')
|
|
550
534
|
const file = segs.pop()!
|
|
551
|
-
const name = file.replace(/\.
|
|
535
|
+
const name = file.replace(/\.ts$/, '')
|
|
552
536
|
const importName = `Subscriber${importId++}_${toVar(modId)}_${toVar([...segs, name].join('_') || 'index')}`
|
|
553
537
|
const metaName = `SubscriberMeta${importId++}_${toVar(modId)}_${toVar([...segs, name].join('_') || 'index')}`
|
|
554
|
-
const
|
|
555
|
-
const
|
|
556
|
-
const fromApp = fs.existsSync(appFileTs) || fs.existsSync(appFileJs)
|
|
538
|
+
const appFile = path.join(subApp, ...segs, `${name}.ts`)
|
|
539
|
+
const fromApp = fs.existsSync(appFile)
|
|
557
540
|
const importPath = `${fromApp ? appImportBase : imps.pkgBase}/subscribers/${[...segs, name].join('/')}`
|
|
558
541
|
imports.push(`import ${importName}, * as ${metaName} from '${importPath}'`)
|
|
559
542
|
const sid = [modId, ...segs, name].filter(Boolean).join(':')
|
|
@@ -563,7 +546,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
563
546
|
}
|
|
564
547
|
}
|
|
565
548
|
|
|
566
|
-
// Workers: src/modules/<module>/workers/*.ts
|
|
549
|
+
// Workers: src/modules/<module>/workers/*.ts
|
|
567
550
|
// Only includes files that export `metadata` with a `queue` property
|
|
568
551
|
{
|
|
569
552
|
const wrkApp = path.join(roots.appBase, 'workers')
|
|
@@ -575,9 +558,8 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
575
558
|
if (e.isDirectory()) {
|
|
576
559
|
if (e.name === '__tests__' || e.name === '__mocks__') continue
|
|
577
560
|
walk(path.join(dir, e.name), [...rel, e.name])
|
|
578
|
-
} else if (e.isFile() &&
|
|
579
|
-
if (/\.(test|spec)\.
|
|
580
|
-
if (e.name.endsWith('.d.ts')) continue
|
|
561
|
+
} else if (e.isFile() && e.name.endsWith('.ts')) {
|
|
562
|
+
if (/\.(test|spec)\.ts$/.test(e.name)) continue
|
|
581
563
|
found.push([...rel, e.name].join('/'))
|
|
582
564
|
}
|
|
583
565
|
}
|
|
@@ -588,10 +570,9 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
588
570
|
for (const rel of files) {
|
|
589
571
|
const segs = rel.split('/')
|
|
590
572
|
const file = segs.pop()!
|
|
591
|
-
const name = file.replace(/\.
|
|
592
|
-
const
|
|
593
|
-
const
|
|
594
|
-
const fromApp = fs.existsSync(appFileTs) || fs.existsSync(appFileJs)
|
|
573
|
+
const name = file.replace(/\.ts$/, '')
|
|
574
|
+
const appFile = path.join(wrkApp, ...segs, `${name}.ts`)
|
|
575
|
+
const fromApp = fs.existsSync(appFile)
|
|
595
576
|
// Use package import path for checking exports (file path fails due to relative imports)
|
|
596
577
|
const importPath = `${fromApp ? appImportBase : imps.pkgBase}/workers/${[...segs, name].join('/')}`
|
|
597
578
|
// Only include files that export metadata with a queue property
|
|
@@ -949,9 +930,9 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
949
930
|
let customFieldSetsExpr: string = '[]'
|
|
950
931
|
|
|
951
932
|
// Module metadata: index.ts (overrideable)
|
|
952
|
-
const appIndex =
|
|
953
|
-
const pkgIndex =
|
|
954
|
-
const indexTs = appIndex
|
|
933
|
+
const appIndex = path.join(roots.appBase, 'index.ts')
|
|
934
|
+
const pkgIndex = path.join(roots.pkgBase, 'index.ts')
|
|
935
|
+
const indexTs = fs.existsSync(appIndex) ? appIndex : fs.existsSync(pkgIndex) ? pkgIndex : null
|
|
955
936
|
if (indexTs) {
|
|
956
937
|
infoImportName = `I${importId++}_${toVar(modId)}`
|
|
957
938
|
const importPath = indexTs.startsWith(roots.appBase) ? `${appImportBase}/index` : `${imps.pkgBase}/index`
|
|
@@ -968,10 +949,10 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
968
949
|
|
|
969
950
|
// Entity extensions: src/modules/<module>/data/extensions.ts
|
|
970
951
|
{
|
|
971
|
-
const appFile =
|
|
972
|
-
const pkgFile =
|
|
973
|
-
const hasApp =
|
|
974
|
-
const hasPkg =
|
|
952
|
+
const appFile = path.join(roots.appBase, 'data', 'extensions.ts')
|
|
953
|
+
const pkgFile = path.join(roots.pkgBase, 'data', 'extensions.ts')
|
|
954
|
+
const hasApp = fs.existsSync(appFile)
|
|
955
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
975
956
|
if (hasApp || hasPkg) {
|
|
976
957
|
const importName = `X_${toVar(modId)}_${importId++}`
|
|
977
958
|
const importPath = hasApp ? `${appImportBase}/data/extensions` : `${imps.pkgBase}/data/extensions`
|
|
@@ -982,12 +963,12 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
982
963
|
|
|
983
964
|
// RBAC feature declarations: module root acl.ts
|
|
984
965
|
{
|
|
985
|
-
const rootApp =
|
|
986
|
-
const rootPkg =
|
|
987
|
-
const hasRoot = rootApp || rootPkg
|
|
966
|
+
const rootApp = path.join(roots.appBase, 'acl.ts')
|
|
967
|
+
const rootPkg = path.join(roots.pkgBase, 'acl.ts')
|
|
968
|
+
const hasRoot = fs.existsSync(rootApp) || fs.existsSync(rootPkg)
|
|
988
969
|
if (hasRoot) {
|
|
989
970
|
const importName = `ACL_${toVar(modId)}_${importId++}`
|
|
990
|
-
const useApp = rootApp
|
|
971
|
+
const useApp = fs.existsSync(rootApp) ? rootApp : rootPkg
|
|
991
972
|
const importPath = useApp.startsWith(roots.appBase) ? `${appImportBase}/acl` : `${imps.pkgBase}/acl`
|
|
992
973
|
imports.push(`import * as ${importName} from '${importPath}'`)
|
|
993
974
|
featuresImportName = importName
|
|
@@ -996,10 +977,10 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
996
977
|
|
|
997
978
|
// Custom entities declarations: module root ce.ts
|
|
998
979
|
{
|
|
999
|
-
const appFile =
|
|
1000
|
-
const pkgFile =
|
|
1001
|
-
const hasApp =
|
|
1002
|
-
const hasPkg =
|
|
980
|
+
const appFile = path.join(roots.appBase, 'ce.ts')
|
|
981
|
+
const pkgFile = path.join(roots.pkgBase, 'ce.ts')
|
|
982
|
+
const hasApp = fs.existsSync(appFile)
|
|
983
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
1003
984
|
if (hasApp || hasPkg) {
|
|
1004
985
|
const importName = `CE_${toVar(modId)}_${importId++}`
|
|
1005
986
|
const importPath = hasApp ? `${appImportBase}/ce` : `${imps.pkgBase}/ce`
|
|
@@ -1010,10 +991,10 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1010
991
|
|
|
1011
992
|
// Vector search configuration: module root vector.ts
|
|
1012
993
|
{
|
|
1013
|
-
const appFile =
|
|
1014
|
-
const pkgFile =
|
|
1015
|
-
const hasApp =
|
|
1016
|
-
const hasPkg =
|
|
994
|
+
const appFile = path.join(roots.appBase, 'vector.ts')
|
|
995
|
+
const pkgFile = path.join(roots.pkgBase, 'vector.ts')
|
|
996
|
+
const hasApp = fs.existsSync(appFile)
|
|
997
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
1017
998
|
if (hasApp || hasPkg) {
|
|
1018
999
|
const importName = `VECTOR_${toVar(modId)}_${importId++}`
|
|
1019
1000
|
const importPath = hasApp ? `${appImportBase}/vector` : `${imps.pkgBase}/vector`
|
|
@@ -1024,10 +1005,10 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1024
1005
|
|
|
1025
1006
|
// Custom field declarations: src/modules/<module>/data/fields.ts
|
|
1026
1007
|
{
|
|
1027
|
-
const appFile =
|
|
1028
|
-
const pkgFile =
|
|
1029
|
-
const hasApp =
|
|
1030
|
-
const hasPkg =
|
|
1008
|
+
const appFile = path.join(roots.appBase, 'data', 'fields.ts')
|
|
1009
|
+
const pkgFile = path.join(roots.pkgBase, 'data', 'fields.ts')
|
|
1010
|
+
const hasApp = fs.existsSync(appFile)
|
|
1011
|
+
const hasPkg = fs.existsSync(pkgFile)
|
|
1031
1012
|
if (hasApp || hasPkg) {
|
|
1032
1013
|
const importName = `F_${toVar(modId)}_${importId++}`
|
|
1033
1014
|
const importPath = hasApp ? `${appImportBase}/data/fields` : `${imps.pkgBase}/data/fields`
|
|
@@ -1037,9 +1018,9 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1037
1018
|
}
|
|
1038
1019
|
|
|
1039
1020
|
// CLI
|
|
1040
|
-
const cliApp =
|
|
1041
|
-
const cliPkg =
|
|
1042
|
-
const cliPath = cliApp
|
|
1021
|
+
const cliApp = path.join(roots.appBase, 'cli.ts')
|
|
1022
|
+
const cliPkg = path.join(roots.pkgBase, 'cli.ts')
|
|
1023
|
+
const cliPath = fs.existsSync(cliApp) ? cliApp : fs.existsSync(cliPkg) ? cliPkg : null
|
|
1043
1024
|
if (cliPath) {
|
|
1044
1025
|
const importName = `CLI_${toVar(modId)}`
|
|
1045
1026
|
const importPath = cliPath.startsWith(roots.appBase) ? `${appImportBase}/cli` : `${imps.pkgBase}/cli`
|
|
@@ -1079,7 +1060,7 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1079
1060
|
}
|
|
1080
1061
|
}
|
|
1081
1062
|
|
|
1082
|
-
// Subscribers: src/modules/<module>/subscribers/*.ts
|
|
1063
|
+
// Subscribers: src/modules/<module>/subscribers/*.ts
|
|
1083
1064
|
const subApp = path.join(roots.appBase, 'subscribers')
|
|
1084
1065
|
const subPkg = path.join(roots.pkgBase, 'subscribers')
|
|
1085
1066
|
if (fs.existsSync(subApp) || fs.existsSync(subPkg)) {
|
|
@@ -1089,9 +1070,8 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1089
1070
|
if (e.isDirectory()) {
|
|
1090
1071
|
if (e.name === '__tests__' || e.name === '__mocks__') continue
|
|
1091
1072
|
walk(path.join(dir, e.name), [...rel, e.name])
|
|
1092
|
-
} else if (e.isFile() &&
|
|
1093
|
-
if (/\.(test|spec)\.
|
|
1094
|
-
if (e.name.endsWith('.d.ts')) continue
|
|
1073
|
+
} else if (e.isFile() && e.name.endsWith('.ts')) {
|
|
1074
|
+
if (/\.(test|spec)\.ts$/.test(e.name)) continue
|
|
1095
1075
|
found.push([...rel, e.name].join('/'))
|
|
1096
1076
|
}
|
|
1097
1077
|
}
|
|
@@ -1102,12 +1082,11 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1102
1082
|
for (const rel of files) {
|
|
1103
1083
|
const segs = rel.split('/')
|
|
1104
1084
|
const file = segs.pop()!
|
|
1105
|
-
const name = file.replace(/\.
|
|
1085
|
+
const name = file.replace(/\.ts$/, '')
|
|
1106
1086
|
const importName = `Subscriber${importId++}_${toVar(modId)}_${toVar([...segs, name].join('_') || 'index')}`
|
|
1107
1087
|
const metaName = `SubscriberMeta${importId++}_${toVar(modId)}_${toVar([...segs, name].join('_') || 'index')}`
|
|
1108
|
-
const
|
|
1109
|
-
const
|
|
1110
|
-
const fromApp = fs.existsSync(appFileTs) || fs.existsSync(appFileJs)
|
|
1088
|
+
const appFile = path.join(subApp, ...segs, `${name}.ts`)
|
|
1089
|
+
const fromApp = fs.existsSync(appFile)
|
|
1111
1090
|
const importPath = `${fromApp ? appImportBase : imps.pkgBase}/subscribers/${[...segs, name].join('/')}`
|
|
1112
1091
|
imports.push(`import ${importName}, * as ${metaName} from '${importPath}'`)
|
|
1113
1092
|
const sid = [modId, ...segs, name].filter(Boolean).join(':')
|
|
@@ -1117,7 +1096,7 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1117
1096
|
}
|
|
1118
1097
|
}
|
|
1119
1098
|
|
|
1120
|
-
// Workers: src/modules/<module>/workers/*.ts
|
|
1099
|
+
// Workers: src/modules/<module>/workers/*.ts
|
|
1121
1100
|
// Only includes files that export `metadata` with a `queue` property
|
|
1122
1101
|
{
|
|
1123
1102
|
const wrkApp = path.join(roots.appBase, 'workers')
|
|
@@ -1129,9 +1108,8 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1129
1108
|
if (e.isDirectory()) {
|
|
1130
1109
|
if (e.name === '__tests__' || e.name === '__mocks__') continue
|
|
1131
1110
|
walk(path.join(dir, e.name), [...rel, e.name])
|
|
1132
|
-
} else if (e.isFile() &&
|
|
1133
|
-
if (/\.(test|spec)\.
|
|
1134
|
-
if (e.name.endsWith('.d.ts')) continue
|
|
1111
|
+
} else if (e.isFile() && e.name.endsWith('.ts')) {
|
|
1112
|
+
if (/\.(test|spec)\.ts$/.test(e.name)) continue
|
|
1135
1113
|
found.push([...rel, e.name].join('/'))
|
|
1136
1114
|
}
|
|
1137
1115
|
}
|
|
@@ -1142,10 +1120,9 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
1142
1120
|
for (const rel of files) {
|
|
1143
1121
|
const segs = rel.split('/')
|
|
1144
1122
|
const file = segs.pop()!
|
|
1145
|
-
const name = file.replace(/\.
|
|
1146
|
-
const
|
|
1147
|
-
const
|
|
1148
|
-
const fromApp = fs.existsSync(appFileTs) || fs.existsSync(appFileJs)
|
|
1123
|
+
const name = file.replace(/\.ts$/, '')
|
|
1124
|
+
const appFile = path.join(wrkApp, ...segs, `${name}.ts`)
|
|
1125
|
+
const fromApp = fs.existsSync(appFile)
|
|
1149
1126
|
// Use package import path for checking exports (file path fails due to relative imports)
|
|
1150
1127
|
const importPath = `${fromApp ? appImportBase : imps.pkgBase}/workers/${[...segs, name].join('/')}`
|
|
1151
1128
|
// Only include files that export metadata with a queue property
|
package/src/lib/resolver.ts
CHANGED
|
@@ -28,9 +28,10 @@ export interface PackageResolver {
|
|
|
28
28
|
|
|
29
29
|
function pkgDirFor(rootDir: string, from?: string, isMonorepo = true): string {
|
|
30
30
|
if (!isMonorepo) {
|
|
31
|
-
// Production mode: look in node_modules
|
|
31
|
+
// Production mode: look in node_modules
|
|
32
|
+
// Packages include source TypeScript files in src/modules
|
|
32
33
|
const pkgName = from || '@open-mercato/core'
|
|
33
|
-
return path.join(rootDir, 'node_modules', pkgName, '
|
|
34
|
+
return path.join(rootDir, 'node_modules', pkgName, 'src', 'modules')
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// Monorepo mode
|
|
@@ -151,8 +152,8 @@ function discoverPackagesInNodeModules(rootDir: string): PackageInfo[] {
|
|
|
151
152
|
|
|
152
153
|
try {
|
|
153
154
|
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))
|
|
154
|
-
//
|
|
155
|
-
const modulesPath = path.join(pkgPath, '
|
|
155
|
+
// Packages include source TypeScript files in src/modules
|
|
156
|
+
const modulesPath = path.join(pkgPath, 'src', 'modules')
|
|
156
157
|
|
|
157
158
|
if (fs.existsSync(modulesPath)) {
|
|
158
159
|
packages.push({
|
package/src/mercato.ts
CHANGED
|
@@ -63,25 +63,6 @@ async function runModuleCommand(
|
|
|
63
63
|
await cmd.run(args)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
// Helper to run a module command, skipping silently if module is not enabled
|
|
67
|
-
async function tryRunModuleCommand(
|
|
68
|
-
allModules: Module[],
|
|
69
|
-
moduleName: string,
|
|
70
|
-
commandName: string,
|
|
71
|
-
args: string[] = []
|
|
72
|
-
): Promise<boolean> {
|
|
73
|
-
const mod = allModules.find((m) => m.id === moduleName)
|
|
74
|
-
if (!mod || !mod.cli || mod.cli.length === 0) {
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
const cmd = mod.cli.find((c) => c.command === commandName)
|
|
78
|
-
if (!cmd) {
|
|
79
|
-
return false
|
|
80
|
-
}
|
|
81
|
-
await cmd.run(args)
|
|
82
|
-
return true
|
|
83
|
-
}
|
|
84
|
-
|
|
85
66
|
// Build all CLI modules (registered + built-in)
|
|
86
67
|
async function buildAllModules(): Promise<Module[]> {
|
|
87
68
|
const modules = getCliModules()
|
|
@@ -319,13 +300,13 @@ export async function run(argv = process.argv) {
|
|
|
319
300
|
await runModuleCommand(allModules, 'customers', 'seed-dictionaries', ['--tenant', tenantId, '--org', orgId])
|
|
320
301
|
console.log('๐ โ
Customer dictionaries seeded\n')
|
|
321
302
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
303
|
+
console.log('๐ Seeding staff address types...')
|
|
304
|
+
await runModuleCommand(allModules, 'staff', 'seed-address-types', ['--tenant', tenantId, '--org', orgId])
|
|
305
|
+
console.log('๐ โ
Staff address types seeded\n')
|
|
325
306
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
307
|
+
console.log('๐ Seeding resources address types...')
|
|
308
|
+
await runModuleCommand(allModules, 'resources', 'seed-address-types', ['--tenant', tenantId, '--org', orgId])
|
|
309
|
+
console.log('๐ โ
Resources address types seeded\n')
|
|
329
310
|
|
|
330
311
|
console.log('๐ Seeding currencies...')
|
|
331
312
|
await runModuleCommand(allModules, 'currencies', 'seed', ['--tenant', tenantId, '--org', orgId])
|
|
@@ -335,9 +316,9 @@ export async function run(argv = process.argv) {
|
|
|
335
316
|
await runModuleCommand(allModules, 'catalog', 'seed-units', ['--tenant', tenantId, '--org', orgId])
|
|
336
317
|
console.log('๐ โ
Catalog units seeded\n')
|
|
337
318
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
319
|
+
console.log('๐๏ธ Seeding unavailability reasons...')
|
|
320
|
+
await runModuleCommand(allModules, 'planner', 'seed-unavailability-reasons', ['--tenant', tenantId, '--org', orgId])
|
|
321
|
+
console.log('๐๏ธ โ
Unavailability reasons seeded\n')
|
|
341
322
|
|
|
342
323
|
const parsedEncryption = parseBooleanToken(process.env.TENANT_DATA_ENCRYPTION ?? 'yes')
|
|
343
324
|
const encryptionEnabled = parsedEncryption === null ? true : parsedEncryption
|
|
@@ -396,21 +377,21 @@ export async function run(argv = process.argv) {
|
|
|
396
377
|
await runModuleCommand(allModules, 'sales', 'seed-examples', ['--tenant', tenantId, '--org', orgId])
|
|
397
378
|
console.log('๐งพ โ
Sales examples seeded\n')
|
|
398
379
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
380
|
+
console.log('๐ฅ Seeding staff examples...')
|
|
381
|
+
await runModuleCommand(allModules, 'staff', 'seed-examples', ['--tenant', tenantId, '--org', orgId])
|
|
382
|
+
console.log('๐ฅ โ
Staff examples seeded\n')
|
|
402
383
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
384
|
+
console.log('๐ฆ Seeding resource capacity units...')
|
|
385
|
+
await runModuleCommand(allModules, 'resources', 'seed-capacity-units', ['--tenant', tenantId, '--org', orgId])
|
|
386
|
+
console.log('๐ฆ โ
Resource capacity units seeded\n')
|
|
406
387
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
388
|
+
console.log('๐งฐ Seeding resource examples...')
|
|
389
|
+
await runModuleCommand(allModules, 'resources', 'seed-examples', ['--tenant', tenantId, '--org', orgId])
|
|
390
|
+
console.log('๐งฐ โ
Resource examples seeded\n')
|
|
410
391
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
392
|
+
console.log('๐๏ธ Seeding planner availability rulesets...')
|
|
393
|
+
await runModuleCommand(allModules, 'planner', 'seed-availability-rulesets', ['--tenant', tenantId, '--org', orgId])
|
|
394
|
+
console.log('๐๏ธ โ
Planner availability rulesets seeded\n')
|
|
414
395
|
|
|
415
396
|
// Optional: seed example todos if the example module is enabled
|
|
416
397
|
const exampleModule = allModules.find((m) => m.id === 'example')
|