@open-mercato/cli 0.4.2-canary-c02407ff85
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/bin/mercato +21 -0
- package/build.mjs +78 -0
- package/dist/bin.js +51 -0
- package/dist/bin.js.map +7 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +7 -0
- package/dist/lib/db/commands.js +350 -0
- package/dist/lib/db/commands.js.map +7 -0
- package/dist/lib/db/index.js +7 -0
- package/dist/lib/db/index.js.map +7 -0
- package/dist/lib/generators/entity-ids.js +257 -0
- package/dist/lib/generators/entity-ids.js.map +7 -0
- package/dist/lib/generators/index.js +12 -0
- package/dist/lib/generators/index.js.map +7 -0
- package/dist/lib/generators/module-di.js +73 -0
- package/dist/lib/generators/module-di.js.map +7 -0
- package/dist/lib/generators/module-entities.js +104 -0
- package/dist/lib/generators/module-entities.js.map +7 -0
- package/dist/lib/generators/module-registry.js +1081 -0
- package/dist/lib/generators/module-registry.js.map +7 -0
- package/dist/lib/resolver.js +205 -0
- package/dist/lib/resolver.js.map +7 -0
- package/dist/lib/utils.js +161 -0
- package/dist/lib/utils.js.map +7 -0
- package/dist/mercato.js +1045 -0
- package/dist/mercato.js.map +7 -0
- package/dist/registry.js +7 -0
- package/dist/registry.js.map +7 -0
- package/jest.config.cjs +19 -0
- package/package.json +71 -0
- package/src/__tests__/mercato.test.ts +90 -0
- package/src/bin.ts +74 -0
- package/src/index.ts +2 -0
- package/src/lib/__tests__/resolver.test.ts +101 -0
- package/src/lib/__tests__/utils.test.ts +270 -0
- package/src/lib/db/__tests__/commands.test.ts +131 -0
- package/src/lib/db/commands.ts +431 -0
- package/src/lib/db/index.ts +1 -0
- package/src/lib/generators/__tests__/generators.test.ts +197 -0
- package/src/lib/generators/entity-ids.ts +336 -0
- package/src/lib/generators/index.ts +4 -0
- package/src/lib/generators/module-di.ts +89 -0
- package/src/lib/generators/module-entities.ts +124 -0
- package/src/lib/generators/module-registry.ts +1222 -0
- package/src/lib/resolver.ts +308 -0
- package/src/lib/utils.ts +200 -0
- package/src/mercato.ts +1106 -0
- package/src/registry.ts +2 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +12 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import {
|
|
5
|
+
calculateChecksum,
|
|
6
|
+
readChecksumRecord,
|
|
7
|
+
writeChecksumRecord,
|
|
8
|
+
ensureDir,
|
|
9
|
+
toVar,
|
|
10
|
+
toSnake,
|
|
11
|
+
rimrafDir,
|
|
12
|
+
logGenerationResult,
|
|
13
|
+
createGeneratorResult
|
|
14
|
+
} from "../utils.js";
|
|
15
|
+
function parseExportedClassNamesFromFile(filePath) {
|
|
16
|
+
const src = fs.readFileSync(filePath, "utf8");
|
|
17
|
+
const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS);
|
|
18
|
+
const classNames = [];
|
|
19
|
+
sf.forEachChild((node) => {
|
|
20
|
+
if (ts.isClassDeclaration(node) && node.name) {
|
|
21
|
+
const hasExport = node.modifiers?.some(
|
|
22
|
+
(m) => m.kind === ts.SyntaxKind.ExportKeyword
|
|
23
|
+
);
|
|
24
|
+
if (hasExport) {
|
|
25
|
+
classNames.push(node.name.text);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return classNames;
|
|
30
|
+
}
|
|
31
|
+
function parseEntityFieldsFromFile(filePath, exportedClassNames) {
|
|
32
|
+
const src = fs.readFileSync(filePath, "utf8");
|
|
33
|
+
const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS);
|
|
34
|
+
const exported = new Set(exportedClassNames);
|
|
35
|
+
const result = {};
|
|
36
|
+
function getDecoratorArgNameLiteral(dec) {
|
|
37
|
+
if (!dec) return void 0;
|
|
38
|
+
const expr = dec.expression;
|
|
39
|
+
if (!ts.isCallExpression(expr)) return void 0;
|
|
40
|
+
if (!expr.arguments.length) return void 0;
|
|
41
|
+
const first = expr.arguments[0];
|
|
42
|
+
if (!ts.isObjectLiteralExpression(first)) return void 0;
|
|
43
|
+
for (const prop of first.properties) {
|
|
44
|
+
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === "name") {
|
|
45
|
+
if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
function normalizeDbName(propertyName, _decoratorName, nameOverride) {
|
|
51
|
+
if (nameOverride) return nameOverride;
|
|
52
|
+
return toSnake(propertyName);
|
|
53
|
+
}
|
|
54
|
+
sf.forEachChild((node) => {
|
|
55
|
+
if (!ts.isClassDeclaration(node) || !node.name) return;
|
|
56
|
+
const clsName = node.name.text;
|
|
57
|
+
if (!exported.has(clsName)) return;
|
|
58
|
+
const entityKey = toSnake(clsName);
|
|
59
|
+
const fields = [];
|
|
60
|
+
for (const member of node.members) {
|
|
61
|
+
if (!ts.isPropertyDeclaration(member) || !member.name) continue;
|
|
62
|
+
const name = ts.isIdentifier(member.name) ? member.name.text : ts.isStringLiteral(member.name) ? member.name.text : void 0;
|
|
63
|
+
if (!name) continue;
|
|
64
|
+
if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue;
|
|
65
|
+
const decorators = ts.canHaveDecorators(member) ? ts.getDecorators(member) ?? [] : [];
|
|
66
|
+
let dbName;
|
|
67
|
+
if (decorators && decorators.length) {
|
|
68
|
+
for (const d of decorators) {
|
|
69
|
+
const nameOverride = getDecoratorArgNameLiteral(d);
|
|
70
|
+
dbName = normalizeDbName(name, void 0, nameOverride);
|
|
71
|
+
if (dbName) break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!dbName) dbName = normalizeDbName(name);
|
|
75
|
+
fields.push(dbName);
|
|
76
|
+
}
|
|
77
|
+
result[entityKey] = Array.from(new Set(fields));
|
|
78
|
+
});
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
function writePerEntityFieldFiles(outRoot, fieldsByEntity) {
|
|
82
|
+
fs.mkdirSync(outRoot, { recursive: true });
|
|
83
|
+
rimrafDir(outRoot);
|
|
84
|
+
fs.mkdirSync(outRoot, { recursive: true });
|
|
85
|
+
for (const [entity, fields] of Object.entries(fieldsByEntity)) {
|
|
86
|
+
const entDir = path.join(outRoot, entity);
|
|
87
|
+
fs.mkdirSync(entDir, { recursive: true });
|
|
88
|
+
const idx = fields.map((f) => `export const ${toVar(f)} = '${f}'`).join("\n") + "\n";
|
|
89
|
+
fs.writeFileSync(path.join(entDir, "index.ts"), idx);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function writeEntityFieldsRegistry(generatedRoot, fieldsByEntity) {
|
|
93
|
+
const entities = Object.keys(fieldsByEntity).sort();
|
|
94
|
+
const imports = entities.length > 0 ? entities.map((e) => `import * as ${toVar(e)} from './entities/${e}/index'`).join("\n") : "";
|
|
95
|
+
const registryEntries = entities.length > 0 ? entities.map((e) => ` ${toVar(e)}`).join(",\n") : "";
|
|
96
|
+
const src = `// AUTO-GENERATED by mercato generate entity-ids
|
|
97
|
+
// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility
|
|
98
|
+
${imports}
|
|
99
|
+
|
|
100
|
+
export const entityFieldsRegistry: Record<string, Record<string, string>> = {
|
|
101
|
+
${registryEntries}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getEntityFields(slug: string): Record<string, string> | undefined {
|
|
105
|
+
return entityFieldsRegistry[slug]
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
const outPath = path.join(generatedRoot, "entity-fields-registry.ts");
|
|
109
|
+
ensureDir(outPath);
|
|
110
|
+
fs.writeFileSync(outPath, src);
|
|
111
|
+
}
|
|
112
|
+
async function generateEntityIds(options) {
|
|
113
|
+
const { resolver, quiet = false } = options;
|
|
114
|
+
const result = createGeneratorResult();
|
|
115
|
+
const outputDir = resolver.getOutputDir();
|
|
116
|
+
const outFile = path.join(outputDir, "entities.ids.generated.ts");
|
|
117
|
+
const checksumFile = path.join(outputDir, "entities.ids.generated.checksum");
|
|
118
|
+
const entries = resolver.loadEnabledModules();
|
|
119
|
+
const consolidated = {};
|
|
120
|
+
const grouped = {};
|
|
121
|
+
const modulesDict = {};
|
|
122
|
+
const groupedModulesDict = {};
|
|
123
|
+
const fieldsByGroup = {};
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
const modId = entry.id;
|
|
126
|
+
const roots = resolver.getModulePaths(entry);
|
|
127
|
+
const imps = resolver.getModuleImportBase(entry);
|
|
128
|
+
const group = entry.from || "@open-mercato/core";
|
|
129
|
+
const appData = path.join(roots.appBase, "data");
|
|
130
|
+
const pkgData = path.join(roots.pkgBase, "data");
|
|
131
|
+
const appDb = path.join(roots.appBase, "db");
|
|
132
|
+
const pkgDb = path.join(roots.pkgBase, "db");
|
|
133
|
+
const bases = [appData, pkgData, appDb, pkgDb];
|
|
134
|
+
const candidates = ["entities.override.ts", "entities.ts", "schema.ts"];
|
|
135
|
+
let importPath = null;
|
|
136
|
+
let filePath = null;
|
|
137
|
+
for (const base of bases) {
|
|
138
|
+
for (const f of candidates) {
|
|
139
|
+
const p = path.join(base, f);
|
|
140
|
+
if (fs.existsSync(p)) {
|
|
141
|
+
const fromApp = base.startsWith(roots.appBase);
|
|
142
|
+
const sub = path.basename(base);
|
|
143
|
+
importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\.ts$/, "")}`;
|
|
144
|
+
filePath = p;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (importPath) break;
|
|
149
|
+
}
|
|
150
|
+
if (!importPath) {
|
|
151
|
+
modulesDict[modId] = modId;
|
|
152
|
+
groupedModulesDict[group] = groupedModulesDict[group] || {};
|
|
153
|
+
groupedModulesDict[group][modId] = modId;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
let exportNames;
|
|
157
|
+
const isAppModule = entry.from === "@app";
|
|
158
|
+
if (isAppModule && filePath) {
|
|
159
|
+
exportNames = parseExportedClassNamesFromFile(filePath);
|
|
160
|
+
} else {
|
|
161
|
+
let mod;
|
|
162
|
+
try {
|
|
163
|
+
mod = await import(importPath);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
166
|
+
result.errors.push(`Failed to import ${importPath}: ${errorMessage}`);
|
|
167
|
+
modulesDict[modId] = modId;
|
|
168
|
+
groupedModulesDict[group] = groupedModulesDict[group] || {};
|
|
169
|
+
groupedModulesDict[group][modId] = modId;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
exportNames = Object.keys(mod).filter((k) => typeof mod[k] === "function");
|
|
173
|
+
}
|
|
174
|
+
const entityNames = exportNames.map((k) => toSnake(k)).filter((k, idx, arr) => arr.indexOf(k) === idx);
|
|
175
|
+
modulesDict[modId] = modId;
|
|
176
|
+
groupedModulesDict[group] = groupedModulesDict[group] || {};
|
|
177
|
+
groupedModulesDict[group][modId] = modId;
|
|
178
|
+
consolidated[modId] = consolidated[modId] || {};
|
|
179
|
+
grouped[group] = grouped[group] || {};
|
|
180
|
+
grouped[group][modId] = grouped[group][modId] || {};
|
|
181
|
+
for (const en of entityNames) {
|
|
182
|
+
consolidated[modId][en] = `${modId}:${en}`;
|
|
183
|
+
grouped[group][modId][en] = `${modId}:${en}`;
|
|
184
|
+
}
|
|
185
|
+
if (filePath) {
|
|
186
|
+
const entityFieldMap = parseEntityFieldsFromFile(filePath, exportNames);
|
|
187
|
+
fieldsByGroup[group] = fieldsByGroup[group] || {};
|
|
188
|
+
fieldsByGroup[group][modId] = entityFieldMap;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const consolidatedSrc = `// AUTO-GENERATED by mercato generate entity-ids
|
|
192
|
+
export const M = ${JSON.stringify(modulesDict, null, 2)} as const
|
|
193
|
+
export const E = ${JSON.stringify(consolidated, null, 2)} as const
|
|
194
|
+
export type KnownModuleId = keyof typeof M
|
|
195
|
+
export type KnownEntities = typeof E
|
|
196
|
+
`;
|
|
197
|
+
const newChecksum = calculateChecksum(consolidatedSrc);
|
|
198
|
+
let shouldWrite = true;
|
|
199
|
+
const existingRecord = readChecksumRecord(checksumFile);
|
|
200
|
+
if (existingRecord && existingRecord.content === newChecksum) {
|
|
201
|
+
shouldWrite = false;
|
|
202
|
+
}
|
|
203
|
+
if (shouldWrite) {
|
|
204
|
+
ensureDir(outFile);
|
|
205
|
+
fs.writeFileSync(outFile, consolidatedSrc);
|
|
206
|
+
writeChecksumRecord(checksumFile, { content: newChecksum, structure: "" });
|
|
207
|
+
result.filesWritten.push(outFile);
|
|
208
|
+
if (!quiet) {
|
|
209
|
+
logGenerationResult(path.relative(process.cwd(), outFile), true);
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
result.filesUnchanged.push(outFile);
|
|
213
|
+
}
|
|
214
|
+
const groups = Object.keys(grouped);
|
|
215
|
+
for (const g of groups) {
|
|
216
|
+
const pkgOutputDir = resolver.getPackageOutputDir(g);
|
|
217
|
+
if (g === "@app" && pkgOutputDir === outputDir) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const out = path.join(pkgOutputDir, "entities.ids.generated.ts");
|
|
221
|
+
const src = `// AUTO-GENERATED by mercato generate entity-ids
|
|
222
|
+
export const M = ${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const
|
|
223
|
+
export const E = ${JSON.stringify(grouped[g] || {}, null, 2)} as const
|
|
224
|
+
export type KnownModuleId = keyof typeof M
|
|
225
|
+
export type KnownEntities = typeof E
|
|
226
|
+
`;
|
|
227
|
+
ensureDir(out);
|
|
228
|
+
fs.writeFileSync(out, src);
|
|
229
|
+
result.filesWritten.push(out);
|
|
230
|
+
const fieldsRoot = path.join(pkgOutputDir, "entities");
|
|
231
|
+
const fieldsByModule = fieldsByGroup[g] || {};
|
|
232
|
+
const combined = {};
|
|
233
|
+
for (const mId of Object.keys(fieldsByModule)) {
|
|
234
|
+
const mMap = fieldsByModule[mId];
|
|
235
|
+
for (const [entity, fields] of Object.entries(mMap)) {
|
|
236
|
+
combined[entity] = Array.from(/* @__PURE__ */ new Set([...combined[entity] || [], ...fields]));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
writePerEntityFieldFiles(fieldsRoot, combined);
|
|
240
|
+
writeEntityFieldsRegistry(pkgOutputDir, combined);
|
|
241
|
+
}
|
|
242
|
+
const combinedAll = {};
|
|
243
|
+
for (const groupFields of Object.values(fieldsByGroup)) {
|
|
244
|
+
for (const mMap of Object.values(groupFields)) {
|
|
245
|
+
for (const [entity, fields] of Object.entries(mMap)) {
|
|
246
|
+
combinedAll[entity] = Array.from(/* @__PURE__ */ new Set([...combinedAll[entity] || [], ...fields]));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
writePerEntityFieldFiles(path.join(outputDir, "entities"), combinedAll);
|
|
251
|
+
writeEntityFieldsRegistry(outputDir, combinedAll);
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
export {
|
|
255
|
+
generateEntityIds
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=entity-ids.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/generators/entity-ids.ts"],
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport {\n calculateChecksum,\n readChecksumRecord,\n writeChecksumRecord,\n ensureDir,\n toVar,\n toSnake,\n rimrafDir,\n logGenerationResult,\n type GeneratorResult,\n createGeneratorResult,\n} from '../utils'\n\ntype GroupKey = '@app' | '@open-mercato/core' | string\ntype EntityFieldMap = Record<string, string[]>\n\nexport interface EntityIdsOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\n/**\n * Extract exported class names from a TypeScript source file without dynamic import.\n * This is used for @app modules since Node.js can't import TypeScript files directly.\n */\nfunction parseExportedClassNamesFromFile(filePath: string): string[] {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n const classNames: string[] = []\n\n sf.forEachChild((node) => {\n // Check for exported class declarations\n if (ts.isClassDeclaration(node) && node.name) {\n const hasExport = node.modifiers?.some(\n (m) => m.kind === ts.SyntaxKind.ExportKeyword\n )\n if (hasExport) {\n classNames.push(node.name.text)\n }\n }\n })\n\n return classNames\n}\n\nfunction parseEntityFieldsFromFile(filePath: string, exportedClassNames: string[]): EntityFieldMap {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n\n const exported = new Set(exportedClassNames)\n const result: EntityFieldMap = {}\n\n function getDecoratorArgNameLiteral(dec: ts.Decorator | undefined): string | undefined {\n if (!dec) return undefined\n const expr = dec.expression\n if (!ts.isCallExpression(expr)) return undefined\n if (!expr.arguments.length) return undefined\n const first = expr.arguments[0]\n if (!ts.isObjectLiteralExpression(first)) return undefined\n for (const prop of first.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'name') {\n if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text\n }\n }\n return undefined\n }\n\n function normalizeDbName(propertyName: string, _decoratorName?: string, nameOverride?: string): string {\n if (nameOverride) return nameOverride\n return toSnake(propertyName)\n }\n\n sf.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n const clsName = node.name.text\n if (!exported.has(clsName)) return\n const entityKey = toSnake(clsName)\n const fields: string[] = []\n\n for (const member of node.members) {\n if (!ts.isPropertyDeclaration(member) || !member.name) continue\n const name = ts.isIdentifier(member.name)\n ? member.name.text\n : ts.isStringLiteral(member.name)\n ? member.name.text\n : undefined\n if (!name) continue\n if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue\n const decorators = ts.canHaveDecorators(member)\n ? ts.getDecorators(member) ?? []\n : []\n let dbName: string | undefined\n if (decorators && decorators.length) {\n for (const d of decorators) {\n const nameOverride = getDecoratorArgNameLiteral(d)\n dbName = normalizeDbName(name, undefined, nameOverride)\n if (dbName) break\n }\n }\n if (!dbName) dbName = normalizeDbName(name)\n fields.push(dbName)\n }\n result[entityKey] = Array.from(new Set(fields))\n })\n\n return result\n}\n\nfunction writePerEntityFieldFiles(outRoot: string, fieldsByEntity: EntityFieldMap): void {\n fs.mkdirSync(outRoot, { recursive: true })\n rimrafDir(outRoot)\n fs.mkdirSync(outRoot, { recursive: true })\n for (const [entity, fields] of Object.entries(fieldsByEntity)) {\n const entDir = path.join(outRoot, entity)\n fs.mkdirSync(entDir, { recursive: true })\n const idx = fields.map((f) => `export const ${toVar(f)} = '${f}'`).join('\\n') + '\\n'\n fs.writeFileSync(path.join(entDir, 'index.ts'), idx)\n }\n}\n\nfunction writeEntityFieldsRegistry(generatedRoot: string, fieldsByEntity: EntityFieldMap): void {\n const entities = Object.keys(fieldsByEntity).sort()\n\n // Always write the file, even if empty, to prevent TypeScript import errors\n const imports = entities.length > 0\n ? entities.map((e) => `import * as ${toVar(e)} from './entities/${e}/index'`).join('\\n')\n : ''\n const registryEntries = entities.length > 0\n ? entities.map((e) => ` ${toVar(e)}`).join(',\\n')\n : ''\n\n const src = `// AUTO-GENERATED by mercato generate entity-ids\n// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility\n${imports}\n\nexport const entityFieldsRegistry: Record<string, Record<string, string>> = {\n${registryEntries}\n}\n\nexport function getEntityFields(slug: string): Record<string, string> | undefined {\n return entityFieldsRegistry[slug]\n}\n`\n const outPath = path.join(generatedRoot, 'entity-fields-registry.ts')\n ensureDir(outPath)\n fs.writeFileSync(outPath, src)\n}\n\nexport async function generateEntityIds(options: EntityIdsOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.ids.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.ids.generated.checksum')\n\n const entries = resolver.loadEnabledModules()\n\n const consolidated: Record<string, Record<string, string>> = {}\n const grouped: Record<GroupKey, Record<string, Record<string, string>>> = {}\n const modulesDict: Record<string, string> = {}\n const groupedModulesDict: Record<GroupKey, Record<string, string>> = {}\n\n const fieldsByGroup: Record<GroupKey, Record<string, EntityFieldMap>> = {}\n\n for (const entry of entries) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const group: GroupKey = (entry.from as GroupKey) || '@open-mercato/core'\n\n // Locate entities definition file (prefer app override)\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override.ts', 'entities.ts', 'schema.ts']\n let importPath: string | null = null\n let filePath: string | null = null\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = path.join(base, f)\n if (fs.existsSync(p)) {\n const fromApp = base.startsWith(roots.appBase)\n const sub = path.basename(base) // 'data' | 'db'\n importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\\.ts$/, '')}`\n filePath = p\n break\n }\n }\n if (importPath) break\n }\n\n // No entities file found -> still register module id\n if (!importPath) {\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n\n // Get exported class names - either via dynamic import or TypeScript parsing\n let exportNames: string[]\n const isAppModule = entry.from === '@app'\n\n if (isAppModule && filePath) {\n // For @app modules, parse TypeScript source directly\n // since Node.js can't import TypeScript files (path alias @/ doesn't resolve at runtime)\n exportNames = parseExportedClassNamesFromFile(filePath)\n } else {\n // For package modules, use dynamic import\n let mod: Record<string, unknown>\n try {\n mod = await import(importPath)\n } catch (err) {\n // Module import failed, record error and skip\n const errorMessage = err instanceof Error ? err.message : String(err)\n result.errors.push(`Failed to import ${importPath}: ${errorMessage}`)\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n exportNames = Object.keys(mod).filter((k) => typeof mod[k] === 'function')\n }\n\n const entityNames = exportNames\n .map((k) => toSnake(k))\n .filter((k, idx, arr) => arr.indexOf(k) === idx)\n\n // Build dictionaries\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n\n consolidated[modId] = consolidated[modId] || {}\n grouped[group] = grouped[group] || {}\n grouped[group][modId] = grouped[group][modId] || {}\n\n for (const en of entityNames) {\n consolidated[modId][en] = `${modId}:${en}`\n grouped[group][modId][en] = `${modId}:${en}`\n }\n\n if (filePath) {\n // exportNames already contains only class/function names from either source\n const entityFieldMap = parseEntityFieldsFromFile(filePath, exportNames)\n fieldsByGroup[group] = fieldsByGroup[group] || {}\n fieldsByGroup[group][modId] = entityFieldMap\n }\n }\n\n // Write consolidated output\n const consolidatedSrc = `// AUTO-GENERATED by mercato generate entity-ids\nexport const M = ${JSON.stringify(modulesDict, null, 2)} as const\nexport const E = ${JSON.stringify(consolidated, null, 2)} as const\nexport type KnownModuleId = keyof typeof M\nexport type KnownEntities = typeof E\n`\n\n // Check if content has changed\n const newChecksum = calculateChecksum(consolidatedSrc)\n let shouldWrite = true\n\n const existingRecord = readChecksumRecord(checksumFile)\n if (existingRecord && existingRecord.content === newChecksum) {\n shouldWrite = false\n }\n\n if (shouldWrite) {\n ensureDir(outFile)\n fs.writeFileSync(outFile, consolidatedSrc)\n writeChecksumRecord(checksumFile, { content: newChecksum, structure: '' })\n result.filesWritten.push(outFile)\n if (!quiet) {\n logGenerationResult(path.relative(process.cwd(), outFile), true)\n }\n } else {\n result.filesUnchanged.push(outFile)\n }\n\n // Write per-group outputs\n const groups = Object.keys(grouped) as GroupKey[]\n for (const g of groups) {\n const pkgOutputDir = resolver.getPackageOutputDir(g)\n // Skip @app group since it writes to the same location as the consolidated output\n if (g === '@app' && pkgOutputDir === outputDir) {\n continue\n }\n const out = path.join(pkgOutputDir, 'entities.ids.generated.ts')\n\n const src = `// AUTO-GENERATED by mercato generate entity-ids\nexport const M = ${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const\nexport const E = ${JSON.stringify(grouped[g] || {}, null, 2)} as const\nexport type KnownModuleId = keyof typeof M\nexport type KnownEntities = typeof E\n`\n ensureDir(out)\n fs.writeFileSync(out, src)\n result.filesWritten.push(out)\n\n const fieldsRoot = path.join(pkgOutputDir, 'entities')\n const fieldsByModule = fieldsByGroup[g] || {}\n const combined: EntityFieldMap = {}\n for (const mId of Object.keys(fieldsByModule)) {\n const mMap = fieldsByModule[mId]\n for (const [entity, fields] of Object.entries(mMap)) {\n combined[entity] = Array.from(new Set([...(combined[entity] || []), ...fields]))\n }\n }\n writePerEntityFieldFiles(fieldsRoot, combined)\n\n // Generate static entity fields registry for Turbopack compatibility\n writeEntityFieldsRegistry(pkgOutputDir, combined)\n }\n\n // Write combined entity fields to root generated/ folder\n const combinedAll: EntityFieldMap = {}\n for (const groupFields of Object.values(fieldsByGroup)) {\n for (const mMap of Object.values(groupFields)) {\n for (const [entity, fields] of Object.entries(mMap)) {\n combinedAll[entity] = Array.from(new Set([...(combinedAll[entity] || []), ...fields]))\n }\n }\n }\n writePerEntityFieldFiles(path.join(outputDir, 'entities'), combinedAll)\n writeEntityFieldsRegistry(outputDir, combinedAll)\n\n return result\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { generateEntityIds } from "./entity-ids.js";
|
|
2
|
+
import { generateModuleRegistry, generateModuleRegistryCli } from "./module-registry.js";
|
|
3
|
+
import { generateModuleEntities } from "./module-entities.js";
|
|
4
|
+
import { generateModuleDi } from "./module-di.js";
|
|
5
|
+
export {
|
|
6
|
+
generateEntityIds,
|
|
7
|
+
generateModuleDi,
|
|
8
|
+
generateModuleEntities,
|
|
9
|
+
generateModuleRegistry,
|
|
10
|
+
generateModuleRegistryCli
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/generators/index.ts"],
|
|
4
|
+
"sourcesContent": ["export { generateEntityIds, type EntityIdsOptions } from './entity-ids'\nexport { generateModuleRegistry, generateModuleRegistryCli, type ModuleRegistryOptions } from './module-registry'\nexport { generateModuleEntities, type ModuleEntitiesOptions } from './module-entities'\nexport { generateModuleDi, type ModuleDiOptions } from './module-di'\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,yBAAgD;AACzD,SAAS,wBAAwB,iCAA6D;AAC9F,SAAS,8BAA0D;AACnE,SAAS,wBAA8C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
calculateChecksum,
|
|
5
|
+
readChecksumRecord,
|
|
6
|
+
writeChecksumRecord,
|
|
7
|
+
ensureDir,
|
|
8
|
+
toVar,
|
|
9
|
+
logGenerationResult,
|
|
10
|
+
createGeneratorResult
|
|
11
|
+
} from "../utils.js";
|
|
12
|
+
async function generateModuleDi(options) {
|
|
13
|
+
const { resolver, quiet = false } = options;
|
|
14
|
+
const result = createGeneratorResult();
|
|
15
|
+
const outputDir = resolver.getOutputDir();
|
|
16
|
+
const outFile = path.join(outputDir, "di.generated.ts");
|
|
17
|
+
const checksumFile = path.join(outputDir, "di.generated.checksum");
|
|
18
|
+
const mods = resolver.loadEnabledModules();
|
|
19
|
+
const imports = [];
|
|
20
|
+
const registrars = [];
|
|
21
|
+
let i = 0;
|
|
22
|
+
for (const entry of mods) {
|
|
23
|
+
const modId = entry.id;
|
|
24
|
+
const roots = resolver.getModulePaths(entry);
|
|
25
|
+
const imp = resolver.getModuleImportBase(entry);
|
|
26
|
+
const appDi = path.join(roots.appBase, "di.ts");
|
|
27
|
+
const pkgDi = path.join(roots.pkgBase, "di.ts");
|
|
28
|
+
const useApp = fs.existsSync(appDi);
|
|
29
|
+
const usePkg = fs.existsSync(pkgDi);
|
|
30
|
+
const importName = `D_${toVar(modId)}_${i++}`;
|
|
31
|
+
if (useApp) {
|
|
32
|
+
const isAppModule = entry.from === "@app";
|
|
33
|
+
const importPath = isAppModule ? `../../src/modules/${modId}/di` : `${imp.appBase}/di`;
|
|
34
|
+
imports.push(`import * as ${importName} from '${importPath}'`);
|
|
35
|
+
registrars.push(`${importName}.register`);
|
|
36
|
+
} else if (usePkg) {
|
|
37
|
+
imports.push(`import * as ${importName} from '${imp.pkgBase}/di'`);
|
|
38
|
+
registrars.push(`${importName}.register`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const output = `// AUTO-GENERATED by mercato generate di
|
|
42
|
+
${imports.join("\n")}
|
|
43
|
+
|
|
44
|
+
const diRegistrars = [
|
|
45
|
+
${registrars.join(",\n ")}
|
|
46
|
+
].filter(Boolean) as (((c: any) => void)|undefined)[]
|
|
47
|
+
|
|
48
|
+
export { diRegistrars }
|
|
49
|
+
export default diRegistrars
|
|
50
|
+
`;
|
|
51
|
+
const newChecksum = calculateChecksum(output);
|
|
52
|
+
let shouldWrite = true;
|
|
53
|
+
const existingRecord = readChecksumRecord(checksumFile);
|
|
54
|
+
if (existingRecord && existingRecord.content === newChecksum) {
|
|
55
|
+
shouldWrite = false;
|
|
56
|
+
}
|
|
57
|
+
if (shouldWrite) {
|
|
58
|
+
ensureDir(outFile);
|
|
59
|
+
fs.writeFileSync(outFile, output);
|
|
60
|
+
writeChecksumRecord(checksumFile, { content: newChecksum, structure: "" });
|
|
61
|
+
result.filesWritten.push(outFile);
|
|
62
|
+
if (!quiet) {
|
|
63
|
+
logGenerationResult(path.relative(process.cwd(), outFile), true);
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
result.filesUnchanged.push(outFile);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
generateModuleDi
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=module-di.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/generators/module-di.ts"],
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { PackageResolver } from '../resolver'\nimport {\n calculateChecksum,\n readChecksumRecord,\n writeChecksumRecord,\n ensureDir,\n toVar,\n logGenerationResult,\n type GeneratorResult,\n createGeneratorResult,\n} from '../utils'\n\nexport interface ModuleDiOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\nexport async function generateModuleDi(options: ModuleDiOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'di.generated.ts')\n const checksumFile = path.join(outputDir, 'di.generated.checksum')\n\n const mods = resolver.loadEnabledModules()\n const imports: string[] = []\n const registrars: string[] = []\n let i = 0\n\n for (const entry of mods) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imp = resolver.getModuleImportBase(entry)\n const appDi = path.join(roots.appBase, 'di.ts')\n const pkgDi = path.join(roots.pkgBase, 'di.ts')\n const useApp = fs.existsSync(appDi)\n const usePkg = fs.existsSync(pkgDi)\n const importName = `D_${toVar(modId)}_${i++}`\n\n if (useApp) {\n // For @app modules, use relative path to work in both Next.js and Node.js CLI context\n // From .mercato/generated/, go up two levels (../..) to reach the app root, then into src/modules/\n const isAppModule = entry.from === '@app'\n const importPath = isAppModule ? `../../src/modules/${modId}/di` : `${imp.appBase}/di`\n imports.push(`import * as ${importName} from '${importPath}'`)\n registrars.push(`${importName}.register`)\n } else if (usePkg) {\n imports.push(`import * as ${importName} from '${imp.pkgBase}/di'`)\n registrars.push(`${importName}.register`)\n }\n }\n\n const output = `// AUTO-GENERATED by mercato generate di\n${imports.join('\\n')}\n\nconst diRegistrars = [\n ${registrars.join(',\\n ')}\n].filter(Boolean) as (((c: any) => void)|undefined)[]\n\nexport { diRegistrars }\nexport default diRegistrars\n`\n\n // Check if content has changed\n const newChecksum = calculateChecksum(output)\n let shouldWrite = true\n\n const existingRecord = readChecksumRecord(checksumFile)\n if (existingRecord && existingRecord.content === newChecksum) {\n shouldWrite = false\n }\n\n if (shouldWrite) {\n ensureDir(outFile)\n fs.writeFileSync(outFile, output)\n writeChecksumRecord(checksumFile, { content: newChecksum, structure: '' })\n result.filesWritten.push(outFile)\n if (!quiet) {\n logGenerationResult(path.relative(process.cwd(), outFile), true)\n }\n } else {\n result.filesUnchanged.push(outFile)\n }\n\n return result\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AAOP,eAAsB,iBAAiB,SAAoD;AACzF,QAAM,EAAE,UAAU,QAAQ,MAAM,IAAI;AACpC,QAAM,SAAS,sBAAsB;AAErC,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,UAAU,KAAK,KAAK,WAAW,iBAAiB;AACtD,QAAM,eAAe,KAAK,KAAK,WAAW,uBAAuB;AAEjE,QAAM,OAAO,SAAS,mBAAmB;AACzC,QAAM,UAAoB,CAAC;AAC3B,QAAM,aAAuB,CAAC;AAC9B,MAAI,IAAI;AAER,aAAW,SAAS,MAAM;AACxB,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,SAAS,eAAe,KAAK;AAC3C,UAAM,MAAM,SAAS,oBAAoB,KAAK;AAC9C,UAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,OAAO;AAC9C,UAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,OAAO;AAC9C,UAAM,SAAS,GAAG,WAAW,KAAK;AAClC,UAAM,SAAS,GAAG,WAAW,KAAK;AAClC,UAAM,aAAa,KAAK,MAAM,KAAK,CAAC,IAAI,GAAG;AAE3C,QAAI,QAAQ;AAGV,YAAM,cAAc,MAAM,SAAS;AACnC,YAAM,aAAa,cAAc,qBAAqB,KAAK,QAAQ,GAAG,IAAI,OAAO;AACjF,cAAQ,KAAK,eAAe,UAAU,UAAU,UAAU,GAAG;AAC7D,iBAAW,KAAK,GAAG,UAAU,WAAW;AAAA,IAC1C,WAAW,QAAQ;AACjB,cAAQ,KAAK,eAAe,UAAU,UAAU,IAAI,OAAO,MAAM;AACjE,iBAAW,KAAK,GAAG,UAAU,WAAW;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,SAAS;AAAA,EACf,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,IAGhB,WAAW,KAAK,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ1B,QAAM,cAAc,kBAAkB,MAAM;AAC5C,MAAI,cAAc;AAElB,QAAM,iBAAiB,mBAAmB,YAAY;AACtD,MAAI,kBAAkB,eAAe,YAAY,aAAa;AAC5D,kBAAc;AAAA,EAChB;AAEA,MAAI,aAAa;AACf,cAAU,OAAO;AACjB,OAAG,cAAc,SAAS,MAAM;AAChC,wBAAoB,cAAc,EAAE,SAAS,aAAa,WAAW,GAAG,CAAC;AACzE,WAAO,aAAa,KAAK,OAAO;AAChC,QAAI,CAAC,OAAO;AACV,0BAAoB,KAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,GAAG,IAAI;AAAA,IACjE;AAAA,EACF,OAAO;AACL,WAAO,eAAe,KAAK,OAAO;AAAA,EACpC;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
calculateChecksum,
|
|
5
|
+
readChecksumRecord,
|
|
6
|
+
writeChecksumRecord,
|
|
7
|
+
ensureDir,
|
|
8
|
+
toVar,
|
|
9
|
+
logGenerationResult,
|
|
10
|
+
createGeneratorResult
|
|
11
|
+
} from "../utils.js";
|
|
12
|
+
async function generateModuleEntities(options) {
|
|
13
|
+
const { resolver, quiet = false } = options;
|
|
14
|
+
const result = createGeneratorResult();
|
|
15
|
+
const outputDir = resolver.getOutputDir();
|
|
16
|
+
const outFile = path.join(outputDir, "entities.generated.ts");
|
|
17
|
+
const checksumFile = path.join(outputDir, "entities.generated.checksum");
|
|
18
|
+
const mods = resolver.loadEnabledModules();
|
|
19
|
+
const imports = [];
|
|
20
|
+
const entitySources = [];
|
|
21
|
+
let n = 0;
|
|
22
|
+
for (const entry of mods) {
|
|
23
|
+
const modId = entry.id;
|
|
24
|
+
const roots = resolver.getModulePaths(entry);
|
|
25
|
+
const imp = resolver.getModuleImportBase(entry);
|
|
26
|
+
const appData = path.join(roots.appBase, "data");
|
|
27
|
+
const pkgData = path.join(roots.pkgBase, "data");
|
|
28
|
+
const appDb = path.join(roots.appBase, "db");
|
|
29
|
+
const pkgDb = path.join(roots.pkgBase, "db");
|
|
30
|
+
const bases = [appData, pkgData, appDb, pkgDb];
|
|
31
|
+
const candidates = ["entities.override.ts", "entities.ts", "schema.ts"];
|
|
32
|
+
let found = null;
|
|
33
|
+
for (const base of bases) {
|
|
34
|
+
for (const f of candidates) {
|
|
35
|
+
const p = path.join(base, f);
|
|
36
|
+
if (fs.existsSync(p)) {
|
|
37
|
+
found = { base, file: f };
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (found) break;
|
|
42
|
+
}
|
|
43
|
+
if (!found) continue;
|
|
44
|
+
const importName = `E_${toVar(modId)}_${n++}`;
|
|
45
|
+
const sub = path.basename(found.base);
|
|
46
|
+
const fromApp = found.base.startsWith(roots.appBase);
|
|
47
|
+
const isAppModule = entry.from === "@app";
|
|
48
|
+
let relImport;
|
|
49
|
+
if (isAppModule && fromApp) {
|
|
50
|
+
relImport = `../../src/modules/${modId}/${sub}/${found.file.replace(/\.ts$/, "")}`;
|
|
51
|
+
} else {
|
|
52
|
+
const baseImport = fromApp ? imp.appBase : imp.pkgBase;
|
|
53
|
+
relImport = `${baseImport}/${sub}/${found.file.replace(/\.ts$/, "")}`;
|
|
54
|
+
}
|
|
55
|
+
imports.push(`import * as ${importName} from '${relImport}'`);
|
|
56
|
+
entitySources.push({ importName, moduleId: modId });
|
|
57
|
+
}
|
|
58
|
+
const output = `// AUTO-GENERATED by mercato generate entities
|
|
59
|
+
${imports.join("\n")}
|
|
60
|
+
|
|
61
|
+
function enhanceEntities(namespace: Record<string, unknown>, moduleId: string): any[] {
|
|
62
|
+
return Object.entries(namespace)
|
|
63
|
+
.filter(([, value]) => typeof value === 'function')
|
|
64
|
+
.map(([exportName, value]) => {
|
|
65
|
+
const entity = value as { entityName?: string }
|
|
66
|
+
if (entity && typeof entity === 'function' && !Object.prototype.hasOwnProperty.call(entity, 'entityName')) {
|
|
67
|
+
Object.defineProperty(entity, 'entityName', {
|
|
68
|
+
value: \`\${moduleId}.\${exportName}\`,
|
|
69
|
+
configurable: true,
|
|
70
|
+
enumerable: false,
|
|
71
|
+
writable: false,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
return entity
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const entities = [
|
|
79
|
+
${entitySources.map(({ importName, moduleId }) => `...enhanceEntities(${importName}, '${moduleId}')`).join(",\n ")}
|
|
80
|
+
]
|
|
81
|
+
`;
|
|
82
|
+
const newChecksum = calculateChecksum(output);
|
|
83
|
+
let shouldWrite = true;
|
|
84
|
+
const existingRecord = readChecksumRecord(checksumFile);
|
|
85
|
+
if (existingRecord && existingRecord.content === newChecksum) {
|
|
86
|
+
shouldWrite = false;
|
|
87
|
+
}
|
|
88
|
+
if (shouldWrite) {
|
|
89
|
+
ensureDir(outFile);
|
|
90
|
+
fs.writeFileSync(outFile, output);
|
|
91
|
+
writeChecksumRecord(checksumFile, { content: newChecksum, structure: "" });
|
|
92
|
+
result.filesWritten.push(outFile);
|
|
93
|
+
if (!quiet) {
|
|
94
|
+
logGenerationResult(path.relative(process.cwd(), outFile), true);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
result.filesUnchanged.push(outFile);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
generateModuleEntities
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=module-entities.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/generators/module-entities.ts"],
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { PackageResolver } from '../resolver'\nimport {\n calculateChecksum,\n readChecksumRecord,\n writeChecksumRecord,\n ensureDir,\n toVar,\n logGenerationResult,\n type GeneratorResult,\n createGeneratorResult,\n} from '../utils'\n\nexport interface ModuleEntitiesOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\nexport async function generateModuleEntities(options: ModuleEntitiesOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.generated.checksum')\n\n const mods = resolver.loadEnabledModules()\n const imports: string[] = []\n const entitySources: Array<{ importName: string; moduleId: string }> = []\n let n = 0\n\n for (const entry of mods) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imp = resolver.getModuleImportBase(entry)\n\n // prefer app override data/, fallback to core data/, then legacy db/\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override.ts', 'entities.ts', 'schema.ts']\n\n let found: { base: string; file: string } | null = null\n for (const base of bases) {\n for (const f of candidates) {\n const p = path.join(base, f)\n if (fs.existsSync(p)) {\n found = { base, file: f }\n break\n }\n }\n if (found) break\n }\n if (!found) continue\n\n const importName = `E_${toVar(modId)}_${n++}`\n const sub = path.basename(found.base) // 'data' or 'db'\n const fromApp = found.base.startsWith(roots.appBase)\n const isAppModule = entry.from === '@app'\n // For @app modules, use relative path to ensure it works both in Next.js and Node.js CLI context\n // From .mercato/generated/, the relative path to src/modules/ is ../src/modules/\n let relImport: string\n if (isAppModule && fromApp) {\n // From .mercato/generated/, go up two levels (../..) to reach the app root, then into src/modules/\n relImport = `../../src/modules/${modId}/${sub}/${found.file.replace(/\\.ts$/, '')}`\n } else {\n const baseImport = fromApp ? imp.appBase : imp.pkgBase\n relImport = `${baseImport}/${sub}/${found.file.replace(/\\.ts$/, '')}`\n }\n imports.push(`import * as ${importName} from '${relImport}'`)\n entitySources.push({ importName, moduleId: modId })\n }\n\n const output = `// AUTO-GENERATED by mercato generate entities\n${imports.join('\\n')}\n\nfunction enhanceEntities(namespace: Record<string, unknown>, moduleId: string): any[] {\n return Object.entries(namespace)\n .filter(([, value]) => typeof value === 'function')\n .map(([exportName, value]) => {\n const entity = value as { entityName?: string }\n if (entity && typeof entity === 'function' && !Object.prototype.hasOwnProperty.call(entity, 'entityName')) {\n Object.defineProperty(entity, 'entityName', {\n value: \\`\\${moduleId}.\\${exportName}\\`,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n return entity\n })\n}\n\nexport const entities = [\n ${entitySources.map(({ importName, moduleId }) => `...enhanceEntities(${importName}, '${moduleId}')`).join(',\\n ')}\n]\n`\n\n // Check if content has changed\n const newChecksum = calculateChecksum(output)\n let shouldWrite = true\n\n const existingRecord = readChecksumRecord(checksumFile)\n if (existingRecord && existingRecord.content === newChecksum) {\n shouldWrite = false\n }\n\n if (shouldWrite) {\n ensureDir(outFile)\n fs.writeFileSync(outFile, output)\n writeChecksumRecord(checksumFile, { content: newChecksum, structure: '' })\n result.filesWritten.push(outFile)\n if (!quiet) {\n logGenerationResult(path.relative(process.cwd(), outFile), true)\n }\n } else {\n result.filesUnchanged.push(outFile)\n }\n\n return result\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|