@open-mercato/cli 0.7.1-develop.7123.1.25365e718d → 0.7.1-develop.7130.1.fef2396fd8
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/.turbo/turbo-build.log +1 -1
- package/dist/agentic/guides/module-facts.json +128 -128
- package/dist/agentic/guides/module-facts.v2.json +128 -128
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_discord/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/documents/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/lib/generators/entity-class-declarations.js +186 -0
- package/dist/lib/generators/entity-class-declarations.js.map +7 -0
- package/dist/lib/generators/module-entities.js +28 -0
- package/dist/lib/generators/module-entities.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/generators/__tests__/entity-class-declarations.test.ts +287 -0
- package/src/lib/generators/__tests__/module-entities.test.ts +219 -0
- package/src/lib/generators/entity-class-declarations.ts +255 -0
- package/src/lib/generators/module-entities.ts +54 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import ts from "typescript-js";
|
|
3
|
+
const MIKRO_ORM_MODULE_PREFIX = "@mikro-orm/";
|
|
4
|
+
function inferScriptKind(filePath) {
|
|
5
|
+
if (filePath.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
6
|
+
if (filePath.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
7
|
+
if (filePath.endsWith(".js") || filePath.endsWith(".cjs") || filePath.endsWith(".mjs")) return ts.ScriptKind.JS;
|
|
8
|
+
return ts.ScriptKind.TS;
|
|
9
|
+
}
|
|
10
|
+
function isMikroOrmModule(specifier) {
|
|
11
|
+
return specifier.startsWith(MIKRO_ORM_MODULE_PREFIX);
|
|
12
|
+
}
|
|
13
|
+
function readRequiredModuleSpecifier(expression) {
|
|
14
|
+
if (!expression || !ts.isCallExpression(expression)) return void 0;
|
|
15
|
+
if (!ts.isIdentifier(expression.expression) || expression.expression.text !== "require") return void 0;
|
|
16
|
+
const [argument] = expression.arguments;
|
|
17
|
+
return argument && ts.isStringLiteralLike(argument) ? argument.text : void 0;
|
|
18
|
+
}
|
|
19
|
+
function collectEntityDecoratorBindings(sourceFile) {
|
|
20
|
+
const named = /* @__PURE__ */ new Set();
|
|
21
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
22
|
+
const addFromNamedBindings = (bindings) => {
|
|
23
|
+
if (!bindings) return;
|
|
24
|
+
if (ts.isNamespaceImport(bindings)) {
|
|
25
|
+
namespaces.add(bindings.name.text);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
for (const element of bindings.elements) {
|
|
29
|
+
if ((element.propertyName ?? element.name).text === "Entity") named.add(element.name.text);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
sourceFile.forEachChild((node) => {
|
|
33
|
+
if (ts.isImportDeclaration(node)) {
|
|
34
|
+
if (!ts.isStringLiteralLike(node.moduleSpecifier) || !isMikroOrmModule(node.moduleSpecifier.text)) return;
|
|
35
|
+
addFromNamedBindings(node.importClause?.namedBindings);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!ts.isVariableStatement(node)) return;
|
|
39
|
+
for (const declaration of node.declarationList.declarations) {
|
|
40
|
+
const specifier = readRequiredModuleSpecifier(declaration.initializer);
|
|
41
|
+
if (!specifier || !isMikroOrmModule(specifier)) continue;
|
|
42
|
+
if (ts.isIdentifier(declaration.name)) {
|
|
43
|
+
namespaces.add(declaration.name.text);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (!ts.isObjectBindingPattern(declaration.name)) continue;
|
|
47
|
+
for (const element of declaration.name.elements) {
|
|
48
|
+
const sourceName = element.propertyName ?? element.name;
|
|
49
|
+
if (ts.isIdentifier(sourceName) && sourceName.text === "Entity" && ts.isIdentifier(element.name)) {
|
|
50
|
+
named.add(element.name.text);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return { named, namespaces };
|
|
56
|
+
}
|
|
57
|
+
function unwrapReference(expression) {
|
|
58
|
+
if (ts.isParenthesizedExpression(expression)) return unwrapReference(expression.expression);
|
|
59
|
+
if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.CommaToken) {
|
|
60
|
+
return unwrapReference(expression.right);
|
|
61
|
+
}
|
|
62
|
+
return expression;
|
|
63
|
+
}
|
|
64
|
+
function isEntityReference(expression, bindings) {
|
|
65
|
+
const reference = unwrapReference(expression);
|
|
66
|
+
if (ts.isIdentifier(reference)) return bindings.named.has(reference.text);
|
|
67
|
+
if (!ts.isPropertyAccessExpression(reference)) return false;
|
|
68
|
+
if (reference.name.text !== "Entity") return false;
|
|
69
|
+
return ts.isIdentifier(reference.expression) && bindings.namespaces.has(reference.expression.text);
|
|
70
|
+
}
|
|
71
|
+
function isEntityDecorator(decorator, bindings) {
|
|
72
|
+
const expression = ts.isCallExpression(decorator.expression) ? decorator.expression.expression : decorator.expression;
|
|
73
|
+
return isEntityReference(expression, bindings);
|
|
74
|
+
}
|
|
75
|
+
function hasEntityDecorator(node, bindings) {
|
|
76
|
+
if (!ts.canHaveDecorators(node)) return false;
|
|
77
|
+
return (ts.getDecorators(node) ?? []).some((decorator) => isEntityDecorator(decorator, bindings));
|
|
78
|
+
}
|
|
79
|
+
function isExportedDeclaration(node) {
|
|
80
|
+
return ts.canHaveModifiers(node) ? (ts.getModifiers(node) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) : false;
|
|
81
|
+
}
|
|
82
|
+
function collectIndirectExportNames(sourceFile) {
|
|
83
|
+
const names = /* @__PURE__ */ new Set();
|
|
84
|
+
const addExportTable = (expression) => {
|
|
85
|
+
if (!ts.isObjectLiteralExpression(expression)) return;
|
|
86
|
+
for (const property of expression.properties) {
|
|
87
|
+
if (!property.name) continue;
|
|
88
|
+
const name = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name) ? property.name.text : void 0;
|
|
89
|
+
if (name) names.add(name);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
sourceFile.forEachChild((node) => {
|
|
93
|
+
if (ts.isExportDeclaration(node) && !node.moduleSpecifier) {
|
|
94
|
+
const clause = node.exportClause;
|
|
95
|
+
if (clause && ts.isNamedExports(clause)) {
|
|
96
|
+
for (const element of clause.elements) names.add((element.propertyName ?? element.name).text);
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!ts.isExpressionStatement(node)) return;
|
|
101
|
+
const expression = node.expression;
|
|
102
|
+
if (ts.isCallExpression(expression)) {
|
|
103
|
+
const callee = expression.expression;
|
|
104
|
+
if (ts.isIdentifier(callee) && /^_*export$/.test(callee.text) && expression.arguments.length >= 2) {
|
|
105
|
+
addExportTable(expression.arguments[1]);
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!ts.isBinaryExpression(expression) || expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return;
|
|
110
|
+
const target = expression.left;
|
|
111
|
+
if (!ts.isPropertyAccessExpression(target)) return;
|
|
112
|
+
if (!ts.isIdentifier(target.expression) || target.expression.text !== "exports") return;
|
|
113
|
+
names.add(target.name.text);
|
|
114
|
+
});
|
|
115
|
+
return names;
|
|
116
|
+
}
|
|
117
|
+
function collectCompiledDecoratedClassNames(sourceFile, bindings) {
|
|
118
|
+
const names = [];
|
|
119
|
+
sourceFile.forEachChild((node) => {
|
|
120
|
+
if (!ts.isExpressionStatement(node)) return;
|
|
121
|
+
const assignment = node.expression;
|
|
122
|
+
if (!ts.isBinaryExpression(assignment) || assignment.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return;
|
|
123
|
+
if (!ts.isIdentifier(assignment.left)) return;
|
|
124
|
+
const call = assignment.right;
|
|
125
|
+
if (!ts.isCallExpression(call) || call.arguments.length === 0) return;
|
|
126
|
+
const [decorators] = call.arguments;
|
|
127
|
+
if (!ts.isArrayLiteralExpression(decorators)) return;
|
|
128
|
+
const target = call.arguments[call.arguments.length - 1];
|
|
129
|
+
if (!target || !ts.isIdentifier(target) || target.text !== assignment.left.text) return;
|
|
130
|
+
const decoratesEntity = decorators.elements.some((element) => isEntityReference(ts.isCallExpression(element) ? element.expression : element, bindings));
|
|
131
|
+
if (decoratesEntity) names.push(assignment.left.text);
|
|
132
|
+
});
|
|
133
|
+
return names;
|
|
134
|
+
}
|
|
135
|
+
function collectVariableClassNames(sourceFile) {
|
|
136
|
+
const declared = /* @__PURE__ */ new Map();
|
|
137
|
+
sourceFile.forEachChild((node) => {
|
|
138
|
+
if (!ts.isVariableStatement(node)) return;
|
|
139
|
+
const exported = isExportedDeclaration(node);
|
|
140
|
+
for (const declaration of node.declarationList.declarations) {
|
|
141
|
+
if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;
|
|
142
|
+
if (!ts.isClassExpression(declaration.initializer)) continue;
|
|
143
|
+
declared.set(declaration.name.text, exported);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
return declared;
|
|
147
|
+
}
|
|
148
|
+
function parseEntityClassNames(filePath) {
|
|
149
|
+
let source;
|
|
150
|
+
try {
|
|
151
|
+
source = fs.readFileSync(filePath, "utf8");
|
|
152
|
+
} catch {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
const sourceFile = ts.createSourceFile(
|
|
156
|
+
filePath,
|
|
157
|
+
source,
|
|
158
|
+
ts.ScriptTarget.ES2020,
|
|
159
|
+
true,
|
|
160
|
+
inferScriptKind(filePath)
|
|
161
|
+
);
|
|
162
|
+
const bindings = collectEntityDecoratorBindings(sourceFile);
|
|
163
|
+
const indirectExports = collectIndirectExportNames(sourceFile);
|
|
164
|
+
const classNames = [];
|
|
165
|
+
const add = (className) => {
|
|
166
|
+
if (!classNames.includes(className)) classNames.push(className);
|
|
167
|
+
};
|
|
168
|
+
sourceFile.forEachChild((node) => {
|
|
169
|
+
if (!ts.isClassDeclaration(node) || !node.name) return;
|
|
170
|
+
if (!hasEntityDecorator(node, bindings)) return;
|
|
171
|
+
const className = node.name.text;
|
|
172
|
+
if (!isExportedDeclaration(node) && !indirectExports.has(className)) return;
|
|
173
|
+
add(className);
|
|
174
|
+
});
|
|
175
|
+
const variableClasses = collectVariableClassNames(sourceFile);
|
|
176
|
+
for (const className of collectCompiledDecoratedClassNames(sourceFile, bindings)) {
|
|
177
|
+
if (!variableClasses.has(className)) continue;
|
|
178
|
+
if (!variableClasses.get(className) && !indirectExports.has(className)) continue;
|
|
179
|
+
add(className);
|
|
180
|
+
}
|
|
181
|
+
return classNames;
|
|
182
|
+
}
|
|
183
|
+
export {
|
|
184
|
+
parseEntityClassNames
|
|
185
|
+
};
|
|
186
|
+
//# sourceMappingURL=entity-class-declarations.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/generators/entity-class-declarations.ts"],
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport ts from 'typescript-js'\n\n/**\n * Names of the `@Entity()`-decorated classes a module's entity file exports.\n *\n * Only decorated classes count: an entity file may also export plain helper classes,\n * and reporting those as entities would raise false collisions. Only a decorator bound\n * to a `@mikro-orm/*` import counts, so an unrelated `Entity` decorator from another\n * library never registers as one.\n *\n * Parsing is used rather than importing because the caller runs during generation,\n * before the module graph exists. A monorepo checkout and a standalone install that\n * ships `src/modules` both hand this TypeScript source; a package that ships compiled\n * output only hands it the built file instead, where a decorated class has become a\n * class expression plus a decorator-helper call, so both shapes are recognised.\n */\n\nconst MIKRO_ORM_MODULE_PREFIX = '@mikro-orm/'\n\ntype EntityDecoratorBindings = {\n /** Local names bound to MikroORM's `Entity` export, including aliased imports. */\n named: Set<string>\n /** Local names bound to a whole MikroORM module, for `@orm.Entity()`. */\n namespaces: Set<string>\n}\n\nfunction inferScriptKind(filePath: string): ts.ScriptKind {\n if (filePath.endsWith('.tsx')) return ts.ScriptKind.TSX\n if (filePath.endsWith('.jsx')) return ts.ScriptKind.JSX\n if (filePath.endsWith('.js') || filePath.endsWith('.cjs') || filePath.endsWith('.mjs')) return ts.ScriptKind.JS\n return ts.ScriptKind.TS\n}\n\nfunction isMikroOrmModule(specifier: string): boolean {\n return specifier.startsWith(MIKRO_ORM_MODULE_PREFIX)\n}\n\n/** `require('@mikro-orm/core')` as it survives into compiled CommonJS output. */\nfunction readRequiredModuleSpecifier(expression: ts.Expression | undefined): string | undefined {\n if (!expression || !ts.isCallExpression(expression)) return undefined\n if (!ts.isIdentifier(expression.expression) || expression.expression.text !== 'require') return undefined\n const [argument] = expression.arguments\n return argument && ts.isStringLiteralLike(argument) ? argument.text : undefined\n}\n\nfunction collectEntityDecoratorBindings(sourceFile: ts.SourceFile): EntityDecoratorBindings {\n const named = new Set<string>()\n const namespaces = new Set<string>()\n\n const addFromNamedBindings = (bindings: ts.NamedImportBindings | undefined): void => {\n if (!bindings) return\n if (ts.isNamespaceImport(bindings)) {\n namespaces.add(bindings.name.text)\n return\n }\n for (const element of bindings.elements) {\n if ((element.propertyName ?? element.name).text === 'Entity') named.add(element.name.text)\n }\n }\n\n sourceFile.forEachChild((node) => {\n if (ts.isImportDeclaration(node)) {\n if (!ts.isStringLiteralLike(node.moduleSpecifier) || !isMikroOrmModule(node.moduleSpecifier.text)) return\n addFromNamedBindings(node.importClause?.namedBindings)\n return\n }\n if (!ts.isVariableStatement(node)) return\n for (const declaration of node.declarationList.declarations) {\n const specifier = readRequiredModuleSpecifier(declaration.initializer)\n if (!specifier || !isMikroOrmModule(specifier)) continue\n if (ts.isIdentifier(declaration.name)) {\n namespaces.add(declaration.name.text)\n continue\n }\n if (!ts.isObjectBindingPattern(declaration.name)) continue\n for (const element of declaration.name.elements) {\n const sourceName = element.propertyName ?? element.name\n if (ts.isIdentifier(sourceName) && sourceName.text === 'Entity' && ts.isIdentifier(element.name)) {\n named.add(element.name.text)\n }\n }\n }\n })\n\n return { named, namespaces }\n}\n\n/** Unwraps the `(0, core_1.Entity)` form a CommonJS emit produces. */\nfunction unwrapReference(expression: ts.Expression): ts.Expression {\n if (ts.isParenthesizedExpression(expression)) return unwrapReference(expression.expression)\n if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.CommaToken) {\n return unwrapReference(expression.right)\n }\n return expression\n}\n\n/** Accepts `Entity`, an aliased local name, and `<mikroOrmNamespace>.Entity`. */\nfunction isEntityReference(expression: ts.Expression, bindings: EntityDecoratorBindings): boolean {\n const reference = unwrapReference(expression)\n if (ts.isIdentifier(reference)) return bindings.named.has(reference.text)\n if (!ts.isPropertyAccessExpression(reference)) return false\n if (reference.name.text !== 'Entity') return false\n return ts.isIdentifier(reference.expression) && bindings.namespaces.has(reference.expression.text)\n}\n\n/** Accepts `@Entity`, `@Entity(...)` and the aliased or namespace-qualified forms. */\nfunction isEntityDecorator(decorator: ts.Decorator, bindings: EntityDecoratorBindings): boolean {\n const expression = ts.isCallExpression(decorator.expression)\n ? decorator.expression.expression\n : decorator.expression\n return isEntityReference(expression, bindings)\n}\n\nfunction hasEntityDecorator(node: ts.ClassDeclaration, bindings: EntityDecoratorBindings): boolean {\n if (!ts.canHaveDecorators(node)) return false\n return (ts.getDecorators(node) ?? []).some((decorator) => isEntityDecorator(decorator, bindings))\n}\n\nfunction isExportedDeclaration(node: ts.Node): boolean {\n return ts.canHaveModifiers(node)\n ? (ts.getModifiers(node) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)\n : false\n}\n\n/**\n * Names the file exports without redeclaring them: `export { X }`, the CommonJS\n * `exports.X = X`, and the `__export(exports, { X: () => X })` table a bundler emits.\n */\nfunction collectIndirectExportNames(sourceFile: ts.SourceFile): Set<string> {\n const names = new Set<string>()\n\n const addExportTable = (expression: ts.Expression): void => {\n if (!ts.isObjectLiteralExpression(expression)) return\n for (const property of expression.properties) {\n if (!property.name) continue\n const name = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name) names.add(name)\n }\n }\n\n sourceFile.forEachChild((node) => {\n if (ts.isExportDeclaration(node) && !node.moduleSpecifier) {\n const clause = node.exportClause\n if (clause && ts.isNamedExports(clause)) {\n for (const element of clause.elements) names.add((element.propertyName ?? element.name).text)\n }\n return\n }\n if (!ts.isExpressionStatement(node)) return\n const expression = node.expression\n if (ts.isCallExpression(expression)) {\n const callee = expression.expression\n // esbuild emits `__export(ns, {...})`, SWC `_export(exports, {...})`.\n if (ts.isIdentifier(callee) && /^_*export$/.test(callee.text) && expression.arguments.length >= 2) {\n addExportTable(expression.arguments[1])\n }\n return\n }\n if (!ts.isBinaryExpression(expression) || expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return\n const target = expression.left\n if (!ts.isPropertyAccessExpression(target)) return\n if (!ts.isIdentifier(target.expression) || target.expression.text !== 'exports') return\n names.add(target.name.text)\n })\n\n return names\n}\n\n/**\n * The compiled shape of a decorated class: the class becomes an expression assigned to a\n * variable, and the decorators move into a helper call \u2014 `X = __decorateClass([...], X)`\n * for esbuild, `X = __decorate([...], X)` for tsc, `_ts_decorate` for SWC. The helper's\n * name is not matched, since it varies by toolchain; the shape is: a call whose first\n * argument is an array literal and whose result is assigned back to the class binding.\n */\nfunction collectCompiledDecoratedClassNames(\n sourceFile: ts.SourceFile,\n bindings: EntityDecoratorBindings,\n): string[] {\n const names: string[] = []\n sourceFile.forEachChild((node) => {\n if (!ts.isExpressionStatement(node)) return\n const assignment = node.expression\n if (!ts.isBinaryExpression(assignment) || assignment.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return\n if (!ts.isIdentifier(assignment.left)) return\n const call = assignment.right\n if (!ts.isCallExpression(call) || call.arguments.length === 0) return\n const [decorators] = call.arguments\n if (!ts.isArrayLiteralExpression(decorators)) return\n const target = call.arguments[call.arguments.length - 1]\n if (!target || !ts.isIdentifier(target) || target.text !== assignment.left.text) return\n const decoratesEntity = decorators.elements.some((element) =>\n isEntityReference(ts.isCallExpression(element) ? element.expression : element, bindings))\n if (decoratesEntity) names.push(assignment.left.text)\n })\n return names\n}\n\n/** Class-expression bindings a compiled file declares, so `let X = class {}` is seen. */\nfunction collectVariableClassNames(sourceFile: ts.SourceFile): Map<string, boolean> {\n const declared = new Map<string, boolean>()\n sourceFile.forEachChild((node) => {\n if (!ts.isVariableStatement(node)) return\n const exported = isExportedDeclaration(node)\n for (const declaration of node.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n if (!ts.isClassExpression(declaration.initializer)) continue\n declared.set(declaration.name.text, exported)\n }\n })\n return declared\n}\n\nexport function parseEntityClassNames(filePath: string): string[] {\n let source: string\n try {\n source = fs.readFileSync(filePath, 'utf8')\n } catch {\n // A warning path must never break generation.\n return []\n }\n const sourceFile = ts.createSourceFile(\n filePath,\n source,\n ts.ScriptTarget.ES2020,\n true,\n inferScriptKind(filePath),\n )\n const bindings = collectEntityDecoratorBindings(sourceFile)\n const indirectExports = collectIndirectExportNames(sourceFile)\n const classNames: string[] = []\n const add = (className: string): void => {\n if (!classNames.includes(className)) classNames.push(className)\n }\n\n sourceFile.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n if (!hasEntityDecorator(node, bindings)) return\n const className = node.name.text\n if (!isExportedDeclaration(node) && !indirectExports.has(className)) return\n add(className)\n })\n\n const variableClasses = collectVariableClassNames(sourceFile)\n for (const className of collectCompiledDecoratedClassNames(sourceFile, bindings)) {\n if (!variableClasses.has(className)) continue\n if (!variableClasses.get(className) && !indirectExports.has(className)) continue\n add(className)\n }\n\n return classNames\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { StructureKind, VariableDeclarationKind } from "ts-morph";
|
|
4
|
+
import {
|
|
5
|
+
findDuplicateEntityClassNames,
|
|
6
|
+
formatDuplicateEntityClassNamesWarning
|
|
7
|
+
} from "@open-mercato/shared/lib/db/duplicateEntityClassNames";
|
|
8
|
+
import { parseEntityClassNames } from "./entity-class-declarations.js";
|
|
4
9
|
import { MODULE_CODE_EXTENSIONS, stripModuleCodeExtension } from "./scanner.js";
|
|
5
10
|
import {
|
|
6
11
|
toVar,
|
|
@@ -40,6 +45,7 @@ async function generateModuleEntities(options) {
|
|
|
40
45
|
const mods = resolver.loadEnabledModules();
|
|
41
46
|
const imports = [];
|
|
42
47
|
const entitySources = [];
|
|
48
|
+
const classNameEntries = [];
|
|
43
49
|
let n = 0;
|
|
44
50
|
for (const entry of mods) {
|
|
45
51
|
const modId = entry.id;
|
|
@@ -76,6 +82,10 @@ async function generateModuleEntities(options) {
|
|
|
76
82
|
}
|
|
77
83
|
imports.push({ name: importName, moduleSpecifier: relImport });
|
|
78
84
|
entitySources.push({ importName, moduleId: modId });
|
|
85
|
+
const entityFilePath = resolveEntitySourceFile(resolver, entry, found, fromApp);
|
|
86
|
+
for (const className of parseEntityClassNames(entityFilePath)) {
|
|
87
|
+
classNameEntries.push({ className, moduleId: modId, sourcePath: entityFilePath });
|
|
88
|
+
}
|
|
79
89
|
}
|
|
80
90
|
const sourceFile = createGeneratedSourceFile("entities.generated.ts");
|
|
81
91
|
addAutoGeneratedComment(sourceFile, "entities");
|
|
@@ -189,8 +199,26 @@ async function generateModuleEntities(options) {
|
|
|
189
199
|
result,
|
|
190
200
|
quiet
|
|
191
201
|
});
|
|
202
|
+
warnOnDuplicateEntityClassNames(classNameEntries);
|
|
192
203
|
return result;
|
|
193
204
|
}
|
|
205
|
+
function warnOnDuplicateEntityClassNames(entries) {
|
|
206
|
+
try {
|
|
207
|
+
const duplicates = findDuplicateEntityClassNames(entries);
|
|
208
|
+
if (duplicates.length === 0) return;
|
|
209
|
+
console.warn(`\x1B[33m[Entities Warning]\x1B[0m ${formatDuplicateEntityClassNamesWarning(duplicates)}`);
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function resolveEntitySourceFile(resolver, entry, found, fromApp) {
|
|
214
|
+
const resolved = path.join(found.base, found.file);
|
|
215
|
+
const from = entry.from;
|
|
216
|
+
if (fromApp || !from || from === "@app") return resolved;
|
|
217
|
+
const sourceBase = path.join(resolver.getPackageRoot(from), "src", "modules", entry.id, path.basename(found.base));
|
|
218
|
+
if (path.resolve(sourceBase) === path.resolve(found.base)) return resolved;
|
|
219
|
+
const sourceFile = resolveConventionFile(sourceBase, stripModuleCodeExtension(found.file));
|
|
220
|
+
return sourceFile ?? resolved;
|
|
221
|
+
}
|
|
194
222
|
function resolveConventionFile(baseDir, basename) {
|
|
195
223
|
for (const extension of MODULE_CODE_EXTENSIONS) {
|
|
196
224
|
const candidate = path.join(baseDir, `${basename}${extension}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/generators/module-entities.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS, stripModuleCodeExtension } from './scanner'\nimport {\n toVar,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n} from '../utils'\nimport {\n addAutoGeneratedComment,\n addImportSpec,\n asExpression,\n arrayLiteral,\n arrowFunction,\n binaryExpression,\n callExpression,\n createGeneratedSourceFile,\n expressionStatement,\n getSourceText,\n identifier,\n ifStatement,\n logicalAnd,\n methodCall,\n objectEntries,\n objectLiteral,\n prefixExpression,\n propertyAccess,\n returnStatement,\n spreadExpression,\n templateLiteral,\n variableStatement,\n} from './ast'\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: Array<{ name: string; moduleSpecifier: 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 const isAppModule = entry.from === '@app'\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', 'entities', 'schema']\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 = resolveConventionFile(base, f)\n if (p) {\n found = { base, file: path.basename(p) }\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 // 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}/${stripModuleCodeExtension(found.file)}`\n } else {\n const baseImport = fromApp ? imp.appBase : imp.pkgBase\n relImport = `${baseImport}/${sub}/${stripModuleCodeExtension(found.file)}`\n }\n imports.push({ name: importName, moduleSpecifier: relImport })\n entitySources.push({ importName, moduleId: modId })\n }\n\n const sourceFile = createGeneratedSourceFile('entities.generated.ts')\n addAutoGeneratedComment(sourceFile, 'entities')\n imports.forEach((entry) => {\n addImportSpec(sourceFile, {\n kind: StructureKind.ImportDeclaration,\n namespaceImport: entry.name,\n moduleSpecifier: entry.moduleSpecifier,\n })\n })\n sourceFile.addFunction({\n name: 'enhanceEntities',\n parameters: [\n { name: 'namespace', type: 'Record<string, unknown>' },\n { name: 'moduleId', type: 'string' },\n ],\n returnType: 'any[]',\n statements: [\n returnStatement(\n methodCall(\n methodCall(objectEntries(identifier('namespace')), 'filter', [\n arrowFunction({\n parameters: ['[, value]'],\n body: binaryExpression(\n prefixExpression('typeof ', identifier('value')),\n '===',\n 'function',\n ),\n }),\n ]),\n 'map',\n [\n arrowFunction({\n parameters: ['[exportName, value]'],\n body: (writer) => {\n writer.block(() => {\n variableStatement({\n name: 'entity',\n initializer: asExpression(identifier('value'), '{ entityName?: string }'),\n })(writer)\n writer.newLine()\n ifStatement({\n condition: logicalAnd([\n identifier('entity'),\n binaryExpression(\n prefixExpression('typeof ', identifier('entity')),\n '===',\n 'function',\n ),\n binaryExpression(\n methodCall(\n propertyAccess(\n propertyAccess(identifier('Object'), 'prototype'),\n 'hasOwnProperty',\n ),\n 'call',\n [identifier('entity'), 'entityName'],\n ),\n '===',\n false,\n ),\n ]),\n thenStatements: [\n expressionStatement(\n callExpression(propertyAccess(identifier('Object'), 'defineProperty'), [\n identifier('entity'),\n 'entityName',\n objectLiteral([\n {\n name: 'value',\n value: templateLiteral([\n identifier('moduleId'),\n '.',\n identifier('exportName'),\n ]),\n },\n { name: 'configurable', value: true },\n { name: 'enumerable', value: false },\n { name: 'writable', value: false },\n ]),\n ]),\n ),\n ],\n })(writer)\n writer.newLine()\n returnStatement(identifier('entity'))(writer)\n })\n },\n }),\n ],\n ),\n ),\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entities',\n initializer: arrayLiteral(entitySources, (writer, entry) =>\n spreadExpression(callExpression(identifier('enhanceEntities'), [identifier(entry.importName), entry.moduleId]))(writer)),\n },\n ],\n })\n const output = getSourceText(sourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: output,\n structureChecksum: '',\n result,\n quiet,\n })\n\n return result\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,eAAe,+BAA+B;
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport {\n findDuplicateEntityClassNames,\n formatDuplicateEntityClassNamesWarning,\n type EntityClassNameEntry,\n} from '@open-mercato/shared/lib/db/duplicateEntityClassNames'\nimport type { ModuleEntry, PackageResolver } from '../resolver'\nimport { parseEntityClassNames } from './entity-class-declarations'\nimport { MODULE_CODE_EXTENSIONS, stripModuleCodeExtension } from './scanner'\nimport {\n toVar,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n} from '../utils'\nimport {\n addAutoGeneratedComment,\n addImportSpec,\n asExpression,\n arrayLiteral,\n arrowFunction,\n binaryExpression,\n callExpression,\n createGeneratedSourceFile,\n expressionStatement,\n getSourceText,\n identifier,\n ifStatement,\n logicalAnd,\n methodCall,\n objectEntries,\n objectLiteral,\n prefixExpression,\n propertyAccess,\n returnStatement,\n spreadExpression,\n templateLiteral,\n variableStatement,\n} from './ast'\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: Array<{ name: string; moduleSpecifier: string }> = []\n const entitySources: Array<{ importName: string; moduleId: string }> = []\n const classNameEntries: EntityClassNameEntry[] = []\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 const isAppModule = entry.from === '@app'\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', 'entities', 'schema']\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 = resolveConventionFile(base, f)\n if (p) {\n found = { base, file: path.basename(p) }\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 // 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}/${stripModuleCodeExtension(found.file)}`\n } else {\n const baseImport = fromApp ? imp.appBase : imp.pkgBase\n relImport = `${baseImport}/${sub}/${stripModuleCodeExtension(found.file)}`\n }\n imports.push({ name: importName, moduleSpecifier: relImport })\n entitySources.push({ importName, moduleId: modId })\n\n const entityFilePath = resolveEntitySourceFile(resolver, entry, found, fromApp)\n for (const className of parseEntityClassNames(entityFilePath)) {\n classNameEntries.push({ className, moduleId: modId, sourcePath: entityFilePath })\n }\n }\n\n const sourceFile = createGeneratedSourceFile('entities.generated.ts')\n addAutoGeneratedComment(sourceFile, 'entities')\n imports.forEach((entry) => {\n addImportSpec(sourceFile, {\n kind: StructureKind.ImportDeclaration,\n namespaceImport: entry.name,\n moduleSpecifier: entry.moduleSpecifier,\n })\n })\n sourceFile.addFunction({\n name: 'enhanceEntities',\n parameters: [\n { name: 'namespace', type: 'Record<string, unknown>' },\n { name: 'moduleId', type: 'string' },\n ],\n returnType: 'any[]',\n statements: [\n returnStatement(\n methodCall(\n methodCall(objectEntries(identifier('namespace')), 'filter', [\n arrowFunction({\n parameters: ['[, value]'],\n body: binaryExpression(\n prefixExpression('typeof ', identifier('value')),\n '===',\n 'function',\n ),\n }),\n ]),\n 'map',\n [\n arrowFunction({\n parameters: ['[exportName, value]'],\n body: (writer) => {\n writer.block(() => {\n variableStatement({\n name: 'entity',\n initializer: asExpression(identifier('value'), '{ entityName?: string }'),\n })(writer)\n writer.newLine()\n ifStatement({\n condition: logicalAnd([\n identifier('entity'),\n binaryExpression(\n prefixExpression('typeof ', identifier('entity')),\n '===',\n 'function',\n ),\n binaryExpression(\n methodCall(\n propertyAccess(\n propertyAccess(identifier('Object'), 'prototype'),\n 'hasOwnProperty',\n ),\n 'call',\n [identifier('entity'), 'entityName'],\n ),\n '===',\n false,\n ),\n ]),\n thenStatements: [\n expressionStatement(\n callExpression(propertyAccess(identifier('Object'), 'defineProperty'), [\n identifier('entity'),\n 'entityName',\n objectLiteral([\n {\n name: 'value',\n value: templateLiteral([\n identifier('moduleId'),\n '.',\n identifier('exportName'),\n ]),\n },\n { name: 'configurable', value: true },\n { name: 'enumerable', value: false },\n { name: 'writable', value: false },\n ]),\n ]),\n ),\n ],\n })(writer)\n writer.newLine()\n returnStatement(identifier('entity'))(writer)\n })\n },\n }),\n ],\n ),\n ),\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entities',\n initializer: arrayLiteral(entitySources, (writer, entry) =>\n spreadExpression(callExpression(identifier('enhanceEntities'), [identifier(entry.importName), entry.moduleId]))(writer)),\n },\n ],\n })\n const output = getSourceText(sourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: output,\n structureChecksum: '',\n result,\n quiet,\n })\n\n warnOnDuplicateEntityClassNames(classNameEntries)\n\n return result\n}\n\n/**\n * A duplicate entity class name across modules silently corrupts entity resolution at\n * runtime and no build step otherwise catches it, so surface it here \u2014 where the\n * colliding registry is produced. Reported as a warning; generation still succeeds.\n */\nfunction warnOnDuplicateEntityClassNames(entries: readonly EntityClassNameEntry[]): void {\n try {\n const duplicates = findDuplicateEntityClassNames(entries)\n if (duplicates.length === 0) return\n console.warn(`\\x1b[33m[Entities Warning]\\x1b[0m ${formatDuplicateEntityClassNamesWarning(duplicates)}`)\n } catch {\n // This check is a diagnostic. It must never be the reason generation fails.\n }\n}\n\n/**\n * The file to read class names out of, which is not always the file the runtime imports.\n * A standalone install resolves a package module to its compiled `dist/modules` tree, and\n * published packages ship `src/modules` alongside it \u2014 so prefer the shipped source, the\n * way `eject` already does, and leave the runtime import pointing at `dist`. A package\n * that ships compiled output only falls back to the resolved base, which the parser also\n * understands. An app override wins over the package tree entirely: the registry imports\n * the app file, so that is the file whose class names are registered.\n */\nfunction resolveEntitySourceFile(\n resolver: PackageResolver,\n entry: ModuleEntry,\n found: { base: string; file: string },\n fromApp: boolean,\n): string {\n const resolved = path.join(found.base, found.file)\n const from = entry.from\n if (fromApp || !from || from === '@app') return resolved\n const sourceBase = path.join(resolver.getPackageRoot(from), 'src', 'modules', entry.id, path.basename(found.base))\n if (path.resolve(sourceBase) === path.resolve(found.base)) return resolved\n const sourceFile = resolveConventionFile(sourceBase, stripModuleCodeExtension(found.file))\n return sourceFile ?? resolved\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.7.1-develop.
|
|
3
|
+
"version": "0.7.1-develop.7130.1.fef2396fd8",
|
|
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.8",
|
|
61
61
|
"@mikro-orm/migrations": "^7.1.8",
|
|
62
62
|
"@mikro-orm/postgresql": "^7.1.8",
|
|
63
|
-
"@open-mercato/queue": "0.7.1-develop.
|
|
64
|
-
"@open-mercato/shared": "0.7.1-develop.
|
|
65
|
-
"@open-mercato/telemetry": "0.7.1-develop.
|
|
63
|
+
"@open-mercato/queue": "0.7.1-develop.7130.1.fef2396fd8",
|
|
64
|
+
"@open-mercato/shared": "0.7.1-develop.7130.1.fef2396fd8",
|
|
65
|
+
"@open-mercato/telemetry": "0.7.1-develop.7130.1.fef2396fd8",
|
|
66
66
|
"cross-spawn": "^7.0.6",
|
|
67
67
|
"pg": "8.22.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.7.1-develop.
|
|
76
|
+
"@open-mercato/shared": "0.7.1-develop.7130.1.fef2396fd8"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@open-mercato/shared": "0.7.1-develop.
|
|
79
|
+
"@open-mercato/shared": "0.7.1-develop.7130.1.fef2396fd8",
|
|
80
80
|
"@types/jest": "^30.0.0",
|
|
81
81
|
"jest": "^30.4.2",
|
|
82
82
|
"ts-jest": "^29.4.12"
|