metal-orm 1.0.101 → 1.0.103
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/index.cjs +57 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +57 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-entities/cli.mjs +1 -1
- package/scripts/generate-entities/generate.mjs +21 -12
- package/scripts/generate-entities/render.mjs +5 -4
- package/scripts/inflection/pt-br.mjs +468 -445
- package/scripts/naming-strategy.mjs +19 -3
- package/src/query-builder/relation-include-strategies.ts +35 -4
- package/src/query-builder/relation-join-planner.ts +73 -2
package/package.json
CHANGED
|
@@ -188,7 +188,7 @@ Flags:
|
|
|
188
188
|
--include=tbl1,tbl2 Only include these tables
|
|
189
189
|
--exclude=tbl3,tbl4 Exclude these tables
|
|
190
190
|
--locale=pt-BR Naming locale for class/relation names (default: en)
|
|
191
|
-
--naming-overrides Path to JSON
|
|
191
|
+
--naming-overrides Path to JSON config for naming customizations (see docs)
|
|
192
192
|
--dry-run Print to stdout instead of writing a file
|
|
193
193
|
--out=<file> Override the generated file (defaults to generated-entities.ts or the index inside --out-dir)
|
|
194
194
|
--out-dir=<dir> Emit one file per entity inside this directory plus the shared index
|
|
@@ -5,7 +5,7 @@ import { loadDriver } from './drivers.mjs';
|
|
|
5
5
|
import { renderEntityFile, renderSplitEntityFiles, renderSplitIndexFile } from './render.mjs';
|
|
6
6
|
import { printDryRun, writeSingleFile, writeSplitFiles } from './emit.mjs';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const loadNamingOverrides = async (filePath, fsPromises) => {
|
|
9
9
|
const raw = await fsPromises.readFile(filePath, 'utf8');
|
|
10
10
|
let parsed;
|
|
11
11
|
try {
|
|
@@ -13,22 +13,31 @@ const loadIrregulars = async (filePath, fsPromises) => {
|
|
|
13
13
|
} catch (err) {
|
|
14
14
|
throw new Error(`Failed to parse naming overrides at ${filePath}: ${err.message || err}`);
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
? parsed.irregulars
|
|
20
|
-
: parsed
|
|
21
|
-
: undefined;
|
|
22
|
-
if (!irregulars) {
|
|
23
|
-
throw new Error(`Naming overrides at ${filePath} must be an object or { "irregulars": { ... } }`);
|
|
16
|
+
|
|
17
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
18
|
+
throw new Error(`Naming overrides at ${filePath} must be an object`);
|
|
24
19
|
}
|
|
25
|
-
|
|
20
|
+
|
|
21
|
+
// Support both flat format { "singular": "plural" } and structured { irregulars: {...}, relationOverrides: {...} }
|
|
22
|
+
const hasStructuredFormat = parsed.irregulars || parsed.relationOverrides;
|
|
23
|
+
|
|
24
|
+
const irregulars = hasStructuredFormat
|
|
25
|
+
? (parsed.irregulars && typeof parsed.irregulars === 'object' ? parsed.irregulars : {})
|
|
26
|
+
: parsed;
|
|
27
|
+
|
|
28
|
+
const relationOverrides = hasStructuredFormat && parsed.relationOverrides && typeof parsed.relationOverrides === 'object'
|
|
29
|
+
? parsed.relationOverrides
|
|
30
|
+
: {};
|
|
31
|
+
|
|
32
|
+
return { irregulars, relationOverrides };
|
|
26
33
|
};
|
|
27
34
|
|
|
28
35
|
export const generateEntities = async (opts, context = {}) => {
|
|
29
36
|
const { fs: fsPromises = fs, logger = console } = context;
|
|
30
|
-
const irregulars
|
|
31
|
-
|
|
37
|
+
const { irregulars, relationOverrides } = opts.namingOverrides
|
|
38
|
+
? await loadNamingOverrides(opts.namingOverrides, fsPromises)
|
|
39
|
+
: { irregulars: undefined, relationOverrides: {} };
|
|
40
|
+
const naming = createNamingStrategy(opts.locale, irregulars, relationOverrides);
|
|
32
41
|
|
|
33
42
|
const { executor, cleanup } = await loadDriver(opts.dialect, opts.url, opts.dbPath);
|
|
34
43
|
let schema;
|
|
@@ -259,26 +259,27 @@ const renderEntityClassLines = ({ table, className, naming, relations, resolveCl
|
|
|
259
259
|
for (const rel of relations) {
|
|
260
260
|
const targetClass = resolveClassName(rel.target);
|
|
261
261
|
if (!targetClass) continue;
|
|
262
|
+
const propName = naming.applyRelationOverride(className, rel.property);
|
|
262
263
|
switch (rel.kind) {
|
|
263
264
|
case 'belongsTo':
|
|
264
265
|
lines.push(
|
|
265
266
|
` @BelongsTo({ target: () => ${targetClass}, foreignKey: '${escapeJsString(rel.foreignKey)}' })`
|
|
266
267
|
);
|
|
267
|
-
lines.push(` ${
|
|
268
|
+
lines.push(` ${propName}!: BelongsToReference<${targetClass}>;`);
|
|
268
269
|
lines.push('');
|
|
269
270
|
break;
|
|
270
271
|
case 'hasMany':
|
|
271
272
|
lines.push(
|
|
272
273
|
` @HasMany({ target: () => ${targetClass}, foreignKey: '${escapeJsString(rel.foreignKey)}' })`
|
|
273
274
|
);
|
|
274
|
-
lines.push(` ${
|
|
275
|
+
lines.push(` ${propName}!: HasManyCollection<${targetClass}>;`);
|
|
275
276
|
lines.push('');
|
|
276
277
|
break;
|
|
277
278
|
case 'hasOne':
|
|
278
279
|
lines.push(
|
|
279
280
|
` @HasOne({ target: () => ${targetClass}, foreignKey: '${escapeJsString(rel.foreignKey)}' })`
|
|
280
281
|
);
|
|
281
|
-
lines.push(` ${
|
|
282
|
+
lines.push(` ${propName}!: HasOneReference<${targetClass}>;`);
|
|
282
283
|
lines.push('');
|
|
283
284
|
break;
|
|
284
285
|
case 'belongsToMany': {
|
|
@@ -289,7 +290,7 @@ const renderEntityClassLines = ({ table, className, naming, relations, resolveCl
|
|
|
289
290
|
rel.pivotForeignKeyToRoot
|
|
290
291
|
)}', pivotForeignKeyToTarget: '${escapeJsString(rel.pivotForeignKeyToTarget)}' })`
|
|
291
292
|
);
|
|
292
|
-
lines.push(` ${
|
|
293
|
+
lines.push(` ${propName}!: ManyToManyCollection<${targetClass}>;`);
|
|
293
294
|
lines.push('');
|
|
294
295
|
break;
|
|
295
296
|
}
|