@mikro-orm/entity-generator 7.0.0-rc.2 → 7.0.0-rc.3
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/DefineEntitySourceFile.js +37 -6
- package/EntityGenerator.js +21 -13
- package/EntitySchemaSourceFile.js +6 -2
- package/SourceFile.js +97 -58
- package/package.json +31 -31
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -28,7 +28,7 @@ export class DefineEntitySourceFile extends EntitySchemaSourceFile {
|
|
|
28
28
|
else {
|
|
29
29
|
entitySchemaOptions.class = this.meta.className;
|
|
30
30
|
}
|
|
31
|
-
Object.assign(entitySchemaOptions,
|
|
31
|
+
Object.assign(entitySchemaOptions, this.meta.embeddable ? this.getEmbeddableDeclOptions() : this.meta.collection ? this.getEntityDeclOptions() : {});
|
|
32
32
|
const nameSuffix = this.options.inferEntityType ? '' : 'Schema';
|
|
33
33
|
const declLine = `export const ${this.meta.className + nameSuffix} = ${this.referenceCoreImport('defineEntity')}(`;
|
|
34
34
|
ret += declLine;
|
|
@@ -81,14 +81,45 @@ export class DefineEntitySourceFile extends EntitySchemaSourceFile {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
const simpleOptions = new Set([
|
|
84
|
-
'primary',
|
|
85
|
-
'
|
|
86
|
-
'
|
|
84
|
+
'primary',
|
|
85
|
+
'ref',
|
|
86
|
+
'nullable',
|
|
87
|
+
'array',
|
|
88
|
+
'object',
|
|
89
|
+
'mapToPk',
|
|
90
|
+
'hidden',
|
|
91
|
+
'concurrencyCheck',
|
|
92
|
+
'lazy',
|
|
93
|
+
'eager',
|
|
94
|
+
'orphanRemoval',
|
|
95
|
+
'version',
|
|
96
|
+
'unsigned',
|
|
97
|
+
'returning',
|
|
98
|
+
'createForeignKeyConstraint',
|
|
99
|
+
'fixedOrder',
|
|
100
|
+
'owner',
|
|
101
|
+
'getter',
|
|
102
|
+
'setter',
|
|
103
|
+
'unique',
|
|
104
|
+
'index',
|
|
105
|
+
'hydrate',
|
|
106
|
+
'persist',
|
|
107
|
+
'autoincrement',
|
|
87
108
|
]);
|
|
88
109
|
const skipOptions = new Set(['entity', 'kind', 'type', 'items']);
|
|
89
110
|
const spreadOptions = new Set([
|
|
90
|
-
'fieldNames',
|
|
91
|
-
'
|
|
111
|
+
'fieldNames',
|
|
112
|
+
'joinColumns',
|
|
113
|
+
'inverseJoinColumns',
|
|
114
|
+
'referencedColumnNames',
|
|
115
|
+
'ownColumns',
|
|
116
|
+
'columnTypes',
|
|
117
|
+
'cascade',
|
|
118
|
+
'ignoreSchemaChanges',
|
|
119
|
+
'customOrder',
|
|
120
|
+
'groups',
|
|
121
|
+
'where',
|
|
122
|
+
'orderBy',
|
|
92
123
|
]);
|
|
93
124
|
const rename = {
|
|
94
125
|
fieldName: 'name',
|
package/EntityGenerator.js
CHANGED
|
@@ -71,7 +71,8 @@ export class EntityGenerator {
|
|
|
71
71
|
return files.map(([, data]) => data);
|
|
72
72
|
}
|
|
73
73
|
async getEntityMetadata(schema, options) {
|
|
74
|
-
const metadata = schema
|
|
74
|
+
const metadata = schema
|
|
75
|
+
.getTables()
|
|
75
76
|
.filter(table => !options.schema || table.schema === options.schema)
|
|
76
77
|
.sort((a, b) => `${a.schema}.${a.name}`.localeCompare(`${b.schema}.${b.name}`))
|
|
77
78
|
.map(table => {
|
|
@@ -87,12 +88,17 @@ export class EntityGenerator {
|
|
|
87
88
|
});
|
|
88
89
|
for (const meta of metadata) {
|
|
89
90
|
for (const prop of meta.relations) {
|
|
90
|
-
if (!metadata.some(otherMeta => prop.referencedTableName === otherMeta.collection ||
|
|
91
|
+
if (!metadata.some(otherMeta => prop.referencedTableName === otherMeta.collection ||
|
|
92
|
+
prop.referencedTableName === `${otherMeta.schema ?? schema.name}.${otherMeta.collection}`)) {
|
|
91
93
|
prop.kind = ReferenceKind.SCALAR;
|
|
92
94
|
const mappedTypes = prop.columnTypes.map((t, i) => this.platform.getMappedType(t));
|
|
93
95
|
const runtimeTypes = mappedTypes.map(t => t.runtimeType);
|
|
94
96
|
prop.runtimeType = (runtimeTypes.length === 1 ? runtimeTypes[0] : `[${runtimeTypes.join(', ')}]`);
|
|
95
|
-
prop.type =
|
|
97
|
+
prop.type =
|
|
98
|
+
mappedTypes.length === 1
|
|
99
|
+
? (Utils.entries(types).find(([k, v]) => Object.getPrototypeOf(mappedTypes[0]) === v.prototype)?.[0] ??
|
|
100
|
+
mappedTypes[0].name)
|
|
101
|
+
: 'unknown';
|
|
96
102
|
}
|
|
97
103
|
const meta2 = metadata.find(meta2 => meta2.className === prop.type);
|
|
98
104
|
const targetPrimaryColumns = meta2?.getPrimaryProps().flatMap(p => p.fieldNames);
|
|
@@ -111,7 +117,9 @@ export class EntityGenerator {
|
|
|
111
117
|
meta.className = this.namingStrategy.getEntityName(`${meta.schema ?? schema.name}_${meta.className}`);
|
|
112
118
|
for (const relMeta of metadata) {
|
|
113
119
|
for (const prop of relMeta.relations) {
|
|
114
|
-
if (prop.type === duplicate &&
|
|
120
|
+
if (prop.type === duplicate &&
|
|
121
|
+
(prop.referencedTableName === meta.collection ||
|
|
122
|
+
prop.referencedTableName === `${meta.schema ?? schema.name}.${meta.collection}`)) {
|
|
115
123
|
prop.type = meta.className;
|
|
116
124
|
}
|
|
117
125
|
}
|
|
@@ -197,9 +205,11 @@ export class EntityGenerator {
|
|
|
197
205
|
detectManyToManyRelations(metadata, onlyPurePivotTables, readOnlyPivotTables, outputPurePivotTables) {
|
|
198
206
|
for (const meta of metadata) {
|
|
199
207
|
const isReferenced = metadata.some(m => {
|
|
200
|
-
return m.tableName !== meta.tableName &&
|
|
201
|
-
|
|
202
|
-
|
|
208
|
+
return (m.tableName !== meta.tableName &&
|
|
209
|
+
m.relations.some(r => {
|
|
210
|
+
return (r.referencedTableName === meta.tableName &&
|
|
211
|
+
[ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(r.kind));
|
|
212
|
+
}));
|
|
203
213
|
});
|
|
204
214
|
if (isReferenced) {
|
|
205
215
|
this.referencedEntities.add(meta);
|
|
@@ -210,8 +220,7 @@ export class EntityGenerator {
|
|
|
210
220
|
}
|
|
211
221
|
// Entities where there are not exactly 2 PK relations that are both ManyToOne are never pivot tables. Skip.
|
|
212
222
|
const pkRelations = meta.relations.filter(rel => rel.primary);
|
|
213
|
-
if (pkRelations.length !== 2 ||
|
|
214
|
-
pkRelations.some(rel => rel.kind !== ReferenceKind.MANY_TO_ONE)) {
|
|
223
|
+
if (pkRelations.length !== 2 || pkRelations.some(rel => rel.kind !== ReferenceKind.MANY_TO_ONE)) {
|
|
215
224
|
continue;
|
|
216
225
|
}
|
|
217
226
|
const pkRelationFields = new Set(pkRelations.flatMap(rel => rel.fieldNames));
|
|
@@ -227,8 +236,7 @@ export class EntityGenerator {
|
|
|
227
236
|
continue;
|
|
228
237
|
}
|
|
229
238
|
const pkRelationNames = pkRelations.map(rel => rel.name);
|
|
230
|
-
let otherProps = meta.props
|
|
231
|
-
.filter(prop => !pkRelationNames.includes(prop.name) &&
|
|
239
|
+
let otherProps = meta.props.filter(prop => !pkRelationNames.includes(prop.name) &&
|
|
232
240
|
prop.persist !== false && // Skip checking non-persist props
|
|
233
241
|
prop.fieldNames.some(fieldName => nonPkFields.includes(fieldName)));
|
|
234
242
|
// Deal with the auto increment column first. That is the column used for fixed ordering, if present.
|
|
@@ -327,9 +335,9 @@ export class EntityGenerator {
|
|
|
327
335
|
continue;
|
|
328
336
|
}
|
|
329
337
|
let i = 1;
|
|
330
|
-
const name = newProp.name = this.namingStrategy.inverseSideName(meta.className, prop.name, newProp.kind);
|
|
338
|
+
const name = (newProp.name = this.namingStrategy.inverseSideName(meta.className, prop.name, newProp.kind));
|
|
331
339
|
while (targetMeta.properties[newProp.name]) {
|
|
332
|
-
newProp.name = name +
|
|
340
|
+
newProp.name = name + i++;
|
|
333
341
|
}
|
|
334
342
|
targetMeta.addProperty(newProp);
|
|
335
343
|
}
|
|
@@ -19,7 +19,11 @@ export class EntitySchemaSourceFile extends SourceFile {
|
|
|
19
19
|
ret += `\n`;
|
|
20
20
|
const entitySchemaOptions = {
|
|
21
21
|
class: this.meta.className,
|
|
22
|
-
...(this.meta.embeddable
|
|
22
|
+
...(this.meta.embeddable
|
|
23
|
+
? this.getEmbeddableDeclOptions()
|
|
24
|
+
: this.meta.collection
|
|
25
|
+
? this.getEntityDeclOptions()
|
|
26
|
+
: {}),
|
|
23
27
|
};
|
|
24
28
|
const declLine = `export const ${this.meta.className}Schema = new ${this.referenceCoreImport('EntitySchema')}(`;
|
|
25
29
|
ret += declLine;
|
|
@@ -122,7 +126,7 @@ export class EntitySchemaSourceFile extends SourceFile {
|
|
|
122
126
|
}
|
|
123
127
|
const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
|
|
124
128
|
/* v8 ignore next */
|
|
125
|
-
options[type] =
|
|
129
|
+
options[type] = propType === true || defaultName === propType ? 'true' : this.quote(propType);
|
|
126
130
|
const expected = {
|
|
127
131
|
index: this.platform.indexForeignKeys(),
|
|
128
132
|
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
package/SourceFile.js
CHANGED
|
@@ -177,7 +177,8 @@ export class SourceFile {
|
|
|
177
177
|
uniqueOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
178
178
|
}
|
|
179
179
|
if (index.deferMode) {
|
|
180
|
-
uniqueOpt.deferMode =
|
|
180
|
+
uniqueOpt.deferMode =
|
|
181
|
+
`${this.referenceCoreImport('DeferMode')}.INITIALLY_${index.deferMode.toUpperCase()}`;
|
|
181
182
|
}
|
|
182
183
|
const columns = this.getColumnOptions(index.columns);
|
|
183
184
|
if (columns) {
|
|
@@ -197,25 +198,31 @@ export class SourceFile {
|
|
|
197
198
|
generateImports() {
|
|
198
199
|
const imports = new Set();
|
|
199
200
|
if (this.coreImports.size > 0) {
|
|
200
|
-
imports.add(`import { ${
|
|
201
|
+
imports.add(`import { ${[...this.coreImports]
|
|
202
|
+
.sort()
|
|
203
|
+
.map(t => {
|
|
201
204
|
let ret = POSSIBLE_TYPE_IMPORTS.includes(t) ? `type ${t}` : t;
|
|
202
205
|
if (this.options.coreImportsPrefix) {
|
|
203
206
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
204
207
|
ret += ` as ${resolvedIdentifier}`;
|
|
205
208
|
}
|
|
206
209
|
return ret;
|
|
207
|
-
})
|
|
210
|
+
})
|
|
211
|
+
.join(', ')} } from '@mikro-orm/core';`);
|
|
208
212
|
}
|
|
209
213
|
if (this.decoratorImports.size > 0) {
|
|
210
214
|
const type = this.options.decorators;
|
|
211
|
-
imports.add(`import { ${
|
|
215
|
+
imports.add(`import { ${[...this.decoratorImports]
|
|
216
|
+
.sort()
|
|
217
|
+
.map(t => {
|
|
212
218
|
let ret = t;
|
|
213
219
|
if (this.options.coreImportsPrefix) {
|
|
214
220
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
215
221
|
ret += ` as ${resolvedIdentifier}`;
|
|
216
222
|
}
|
|
217
223
|
return ret;
|
|
218
|
-
})
|
|
224
|
+
})
|
|
225
|
+
.join(', ')} } from '@mikro-orm/decorators/${type}';`);
|
|
219
226
|
}
|
|
220
227
|
const extension = this.options.esmImport ? '.js' : '';
|
|
221
228
|
const { dir, base } = parse(`${this.options.path ?? '.'}/${this.getBaseName()}`);
|
|
@@ -325,22 +332,28 @@ export class SourceFile {
|
|
|
325
332
|
}
|
|
326
333
|
return prop.type;
|
|
327
334
|
})();
|
|
328
|
-
const hasUsableNullDefault =
|
|
329
|
-
const useDefault = hasUsableNullDefault ||
|
|
330
|
-
|
|
335
|
+
const hasUsableNullDefault = prop.nullable && !this.options.forceUndefined && prop.default === null;
|
|
336
|
+
const useDefault = hasUsableNullDefault ||
|
|
337
|
+
(!(typeof prop.default === 'undefined' || prop.default === null) &&
|
|
338
|
+
propType !== 'unknown' &&
|
|
339
|
+
typeof breakdownOfIType === 'undefined');
|
|
340
|
+
const optional = prop.nullable && (this.options.forceUndefined || prop.optional) ? '?' : useDefault ? '' : '!';
|
|
331
341
|
let ret = `${propName}${optional}: `;
|
|
332
342
|
const isArray = prop.array && (prop.kind === ReferenceKind.EMBEDDED || prop.enum);
|
|
333
343
|
const complexType = isArray ? `${propType}[]` : propType;
|
|
334
344
|
let wrappedType = prop.ref
|
|
335
|
-
? `${this.referenceCoreImport('Ref')}<${complexType}${
|
|
336
|
-
:
|
|
337
|
-
|
|
345
|
+
? `${this.referenceCoreImport('Ref')}<${complexType}${isScalar && prop.nullable && !this.options.forceUndefined ? ' | null' : ''}>`
|
|
346
|
+
: this.options.esmImport && !isScalar
|
|
347
|
+
? `${this.referenceCoreImport('Rel')}<${complexType}>`
|
|
348
|
+
: complexType;
|
|
349
|
+
if (prop.nullable &&
|
|
350
|
+
!this.options.forceUndefined &&
|
|
351
|
+
(!isScalar || (!prop.ref && !wrappedType.includes(' | null')))) {
|
|
338
352
|
wrappedType += ' | null';
|
|
339
353
|
}
|
|
340
|
-
const optionalType =
|
|
341
|
-
|
|
342
|
-
:
|
|
343
|
-
ret += (!this.options.forceUndefined && prop.nullable && (hiddenType || optionalType)) ? `(${wrappedType})` : wrappedType;
|
|
354
|
+
const optionalType = optional !== '?' && prop.optional ? ` & ${this.referenceCoreImport('Opt')}` : '';
|
|
355
|
+
ret +=
|
|
356
|
+
!this.options.forceUndefined && prop.nullable && (hiddenType || optionalType) ? `(${wrappedType})` : wrappedType;
|
|
344
357
|
ret += hiddenType;
|
|
345
358
|
ret += optionalType;
|
|
346
359
|
if (!useDefault) {
|
|
@@ -424,17 +437,19 @@ export class SourceFile {
|
|
|
424
437
|
return res;
|
|
425
438
|
}
|
|
426
439
|
}
|
|
427
|
-
const nextWordwrap = typeof wordwrap === 'number' ? 80 - (spaces ?? 0) -
|
|
440
|
+
const nextWordwrap = typeof wordwrap === 'number' ? 80 - (spaces ?? 0) - level * 2 : undefined;
|
|
428
441
|
const sep = typeof spaces === 'undefined' ? ', ' : `,\n${' '.repeat(spaces)}`;
|
|
429
442
|
const doIndent = typeof spaces !== 'undefined';
|
|
430
443
|
if (Array.isArray(options)) {
|
|
431
|
-
return `[${doIndent ? `\n${' '.repeat(spaces)}` : ''}${options.map(val => `${doIndent ? ' '.repeat(
|
|
444
|
+
return `[${doIndent ? `\n${' '.repeat(spaces)}` : ''}${options.map(val => `${doIndent ? ' '.repeat(level * 2 + (spaces + 2)) : ''}${this.serializeValue(val, typeof nextWordwrap === 'number' ? nextWordwrap : undefined, doIndent ? spaces : undefined, level + 1)}`).join(sep)}${doIndent ? `${options.length > 0 ? ',\n' : ''}${' '.repeat(spaces + level * 2)}` : ''}]`;
|
|
432
445
|
}
|
|
433
446
|
const entries = Object.entries(options);
|
|
434
|
-
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries
|
|
447
|
+
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries
|
|
448
|
+
.map(([opt, val]) => {
|
|
435
449
|
const key = identifierRegex.test(opt) ? opt : this.quote(opt);
|
|
436
|
-
return `${doIndent ? ' '.repeat(
|
|
437
|
-
})
|
|
450
|
+
return `${doIndent ? ' '.repeat(level * 2 + (spaces + 2)) : ''}${key}: ${this.serializeValue(val, typeof nextWordwrap === 'number' ? nextWordwrap - key.length - 2 /* ': '.length*/ : undefined, doIndent ? spaces : undefined, level + 1)}`;
|
|
451
|
+
})
|
|
452
|
+
.join(sep)}${doIndent ? `${entries.length > 0 ? ',\n' : ''}${' '.repeat(spaces + level * 2)}` : ' '}}`;
|
|
438
453
|
}
|
|
439
454
|
serializeValue(val, wordwrap, spaces, level = 1) {
|
|
440
455
|
if (typeof val === 'object' && val !== null) {
|
|
@@ -480,14 +495,19 @@ export class SourceFile {
|
|
|
480
495
|
options.abstract = true;
|
|
481
496
|
}
|
|
482
497
|
if (this.meta.discriminatorValue) {
|
|
483
|
-
options.discriminatorValue =
|
|
498
|
+
options.discriminatorValue =
|
|
499
|
+
typeof this.meta.discriminatorValue === 'string'
|
|
500
|
+
? this.quote(this.meta.discriminatorValue)
|
|
501
|
+
: this.meta.discriminatorValue;
|
|
484
502
|
}
|
|
485
503
|
if (this.meta.discriminatorColumn) {
|
|
486
504
|
options.discriminatorColumn = this.quote(this.meta.discriminatorColumn);
|
|
487
505
|
}
|
|
488
506
|
if (this.meta.discriminatorMap) {
|
|
489
|
-
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap)
|
|
490
|
-
|
|
507
|
+
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap).map(([discriminatorValue, cls]) => [
|
|
508
|
+
discriminatorValue,
|
|
509
|
+
this.quote(Utils.className(cls)),
|
|
510
|
+
]));
|
|
491
511
|
}
|
|
492
512
|
return options;
|
|
493
513
|
}
|
|
@@ -529,7 +549,7 @@ export class SourceFile {
|
|
|
529
549
|
return;
|
|
530
550
|
}
|
|
531
551
|
const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
|
|
532
|
-
options[type] =
|
|
552
|
+
options[type] = propType === true || defaultName === propType ? 'true' : this.quote(propType);
|
|
533
553
|
const expected = {
|
|
534
554
|
index: this.platform.indexForeignKeys(),
|
|
535
555
|
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
@@ -574,12 +594,10 @@ export class SourceFile {
|
|
|
574
594
|
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
575
595
|
options.primary = true;
|
|
576
596
|
}
|
|
577
|
-
['persist', 'hydrate']
|
|
578
|
-
.filter(key => prop[key] === false)
|
|
579
|
-
.forEach(key => options[key] = false);
|
|
597
|
+
['persist', 'hydrate'].filter(key => prop[key] === false).forEach(key => (options[key] = false));
|
|
580
598
|
['onCreate', 'onUpdate', 'serializer']
|
|
581
599
|
.filter(key => typeof prop[key] === 'function')
|
|
582
|
-
.forEach(key => options[key] = `${prop[key]}`);
|
|
600
|
+
.forEach(key => (options[key] = `${prop[key]}`));
|
|
583
601
|
if (typeof prop.serializedName === 'string') {
|
|
584
602
|
options.serializedName = this.quote(prop.serializedName);
|
|
585
603
|
}
|
|
@@ -588,7 +606,7 @@ export class SourceFile {
|
|
|
588
606
|
}
|
|
589
607
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
590
608
|
.filter(key => prop[key])
|
|
591
|
-
.forEach(key => options[key] = true);
|
|
609
|
+
.forEach(key => (options[key] = true));
|
|
592
610
|
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
593
611
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
594
612
|
}
|
|
@@ -597,11 +615,17 @@ export class SourceFile {
|
|
|
597
615
|
}
|
|
598
616
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
599
617
|
if (prop.fieldNames?.length <= 1) {
|
|
600
|
-
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
618
|
+
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
619
|
+
prop.defaultRaw !== 'null' &&
|
|
620
|
+
prop.defaultRaw !== '' &&
|
|
601
621
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
602
622
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
603
623
|
}
|
|
604
|
-
else if (!(typeof prop.default === 'undefined' || prop.default === null) &&
|
|
624
|
+
else if (!(typeof prop.default === 'undefined' || prop.default === null) &&
|
|
625
|
+
(prop.ref ||
|
|
626
|
+
(!prop.enum &&
|
|
627
|
+
(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR) &&
|
|
628
|
+
(prop.type === 'unknown' || typeof this.breakdownOfIType(prop) !== 'undefined')))) {
|
|
605
629
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
606
630
|
}
|
|
607
631
|
}
|
|
@@ -622,11 +646,12 @@ export class SourceFile {
|
|
|
622
646
|
return this.propTypeBreakdowns.get(prop);
|
|
623
647
|
}
|
|
624
648
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
625
|
-
const mappedRawType =
|
|
626
|
-
|
|
627
|
-
|
|
649
|
+
const mappedRawType = prop.customTypes?.[0] ??
|
|
650
|
+
(prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType
|
|
651
|
+
? this.platform.getMappedType(prop.columnTypes[0])
|
|
652
|
+
: mappedDeclaredType);
|
|
628
653
|
const rawType = mappedRawType.runtimeType;
|
|
629
|
-
const mappedSerializedType =
|
|
654
|
+
const mappedSerializedType = prop.customType ?? mappedRawType;
|
|
630
655
|
const serializedType = mappedSerializedType.runtimeType;
|
|
631
656
|
// Add non-lib imports where needed.
|
|
632
657
|
for (const typeSpec of [prop.runtimeType, rawType, serializedType]) {
|
|
@@ -640,10 +665,12 @@ export class SourceFile {
|
|
|
640
665
|
mappedRawType.prop?.nullable ?? prop.nullable ?? false,
|
|
641
666
|
mappedSerializedType.prop?.nullable ?? prop.nullable ?? false,
|
|
642
667
|
];
|
|
643
|
-
const hasMixedNullability =
|
|
668
|
+
const hasMixedNullability = new Set(nullables).size > 1;
|
|
644
669
|
if (prop.runtimeType !== rawType || rawType !== serializedType || hasMixedNullability) {
|
|
645
670
|
const nullType = this.options.forceUndefined ? ' | undefined' : ' | null';
|
|
646
|
-
if (rawType !== serializedType ||
|
|
671
|
+
if (rawType !== serializedType ||
|
|
672
|
+
nullables[1] !== nullables[2] ||
|
|
673
|
+
(prop.hidden && nullables[0] !== nullables[1])) {
|
|
647
674
|
const r = [prop.runtimeType, rawType, serializedType];
|
|
648
675
|
if (hasMixedNullability || prop.hidden) {
|
|
649
676
|
for (let i = r.length - 1; i >= 0; --i) {
|
|
@@ -708,14 +735,19 @@ export class SourceFile {
|
|
|
708
735
|
options.type = prop.type;
|
|
709
736
|
}
|
|
710
737
|
else {
|
|
711
|
-
if (this.options.scalarTypeInDecorator // always output type if forced by the generator options
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
738
|
+
if (this.options.scalarTypeInDecorator || // always output type if forced by the generator options
|
|
739
|
+
(prop.nullable && !this.options.forceUndefined) || // also when there is the "| null" type modifier (because reflect-metadata can't extract the base)
|
|
740
|
+
prop.hidden || // also when there is the "& Hidden" type modifier (because reflect-metadata can't extract the base)
|
|
741
|
+
new Set([
|
|
742
|
+
mappedRuntimeType.name,
|
|
743
|
+
mappedColumnType.name,
|
|
744
|
+
mappedDeclaredType.name,
|
|
745
|
+
this.platform.getMappedType(prop.runtimeType === 'Date' ? 'datetime' : prop.runtimeType).name,
|
|
746
|
+
]).size > 1 || // also, if there's any ambiguity in the type
|
|
747
|
+
(() => {
|
|
748
|
+
const hasUsableNullDefault = prop.nullable && !this.options.forceUndefined && prop.default === null;
|
|
717
749
|
const useDefault = hasUsableNullDefault || !(typeof prop.default === 'undefined' || prop.default === null);
|
|
718
|
-
return (
|
|
750
|
+
return (useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable);
|
|
719
751
|
})() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
|
|
720
752
|
) {
|
|
721
753
|
options.type = quote ? this.quote(prop.type) : prop.type;
|
|
@@ -725,13 +757,16 @@ export class SourceFile {
|
|
|
725
757
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
726
758
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
727
759
|
const needsExplicitColumnType = () => {
|
|
728
|
-
if (isTypeStringMissingFromMap ||
|
|
760
|
+
if (isTypeStringMissingFromMap ||
|
|
761
|
+
[mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
729
762
|
return true;
|
|
730
763
|
}
|
|
731
|
-
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
764
|
+
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
765
|
+
this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
732
766
|
return prop.columnTypes[0] !== columnTypeFromMappedColumnType;
|
|
733
767
|
}
|
|
734
|
-
return columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
768
|
+
return (columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
769
|
+
columnTypeFromMappedDeclaredType !== columnTypeFromMappedColumnType);
|
|
735
770
|
};
|
|
736
771
|
if (needsExplicitColumnType()) {
|
|
737
772
|
options.columnType = this.quote(prop.columnTypes[0]);
|
|
@@ -741,7 +776,9 @@ export class SourceFile {
|
|
|
741
776
|
options[key] = prop[key];
|
|
742
777
|
}
|
|
743
778
|
};
|
|
744
|
-
if (!options.columnType &&
|
|
779
|
+
if (!options.columnType &&
|
|
780
|
+
(typeof mappedColumnType.getDefaultLength === 'undefined' ||
|
|
781
|
+
mappedColumnType.getDefaultLength(this.platform) !== prop.length)) {
|
|
745
782
|
assign('length');
|
|
746
783
|
}
|
|
747
784
|
// those are already included in the `columnType` in most cases, and when that option is present, they would be ignored anyway
|
|
@@ -756,11 +793,15 @@ export class SourceFile {
|
|
|
756
793
|
assign('unsigned');
|
|
757
794
|
}
|
|
758
795
|
if (prop.autoincrement) {
|
|
759
|
-
if (!prop.primary ||
|
|
796
|
+
if (!prop.primary ||
|
|
797
|
+
!this.platform.isNumericColumn(mappedColumnType) ||
|
|
798
|
+
this.meta.getPrimaryProps().length !== 1) {
|
|
760
799
|
options.autoincrement = true;
|
|
761
800
|
}
|
|
762
801
|
}
|
|
763
|
-
else if (prop.primary &&
|
|
802
|
+
else if (prop.primary &&
|
|
803
|
+
this.platform.isNumericColumn(mappedColumnType) &&
|
|
804
|
+
this.meta.getPrimaryProps().length === 1) {
|
|
764
805
|
options.autoincrement = false;
|
|
765
806
|
}
|
|
766
807
|
if (prop.generated) {
|
|
@@ -777,7 +818,8 @@ export class SourceFile {
|
|
|
777
818
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
778
819
|
return;
|
|
779
820
|
}
|
|
780
|
-
if (prop.pivotTable !==
|
|
821
|
+
if (prop.pivotTable !==
|
|
822
|
+
this.namingStrategy.joinTableName(this.meta.collection, prop.type, prop.name, this.meta.tableName)) {
|
|
781
823
|
options.pivotTable = this.quote(prop.pivotTable);
|
|
782
824
|
}
|
|
783
825
|
if (prop.pivotEntity && Utils.className(prop.pivotEntity) !== prop.pivotTable) {
|
|
@@ -843,7 +885,8 @@ export class SourceFile {
|
|
|
843
885
|
}
|
|
844
886
|
}
|
|
845
887
|
else {
|
|
846
|
-
if (prop.fieldNames.length > 1 &&
|
|
888
|
+
if (prop.fieldNames.length > 1 &&
|
|
889
|
+
prop.fieldNames.some((fieldName, i) => fieldName !== this.namingStrategy.joinKeyColumnName(prop.name, prop.referencedColumnNames[i]))) {
|
|
847
890
|
options.fieldNames = prop.fieldNames.map(fieldName => this.quote(fieldName));
|
|
848
891
|
}
|
|
849
892
|
}
|
|
@@ -896,14 +939,10 @@ export class SourceFile {
|
|
|
896
939
|
}
|
|
897
940
|
referenceCoreImport(identifier) {
|
|
898
941
|
this.coreImports.add(identifier);
|
|
899
|
-
return this.options.coreImportsPrefix
|
|
900
|
-
? `${this.options.coreImportsPrefix}${identifier}`
|
|
901
|
-
: identifier;
|
|
942
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
902
943
|
}
|
|
903
944
|
referenceDecoratorImport(identifier) {
|
|
904
945
|
this.decoratorImports.add(identifier);
|
|
905
|
-
return this.options.coreImportsPrefix
|
|
906
|
-
? `${this.options.coreImportsPrefix}${identifier}`
|
|
907
|
-
: identifier;
|
|
946
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
908
947
|
}
|
|
909
948
|
}
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/entity-generator",
|
|
3
|
-
"
|
|
4
|
-
"version": "7.0.0-rc.2",
|
|
3
|
+
"version": "7.0.0-rc.3",
|
|
5
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
6
|
-
"exports": {
|
|
7
|
-
"./package.json": "./package.json",
|
|
8
|
-
".": "./index.js"
|
|
9
|
-
},
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+ssh://git@github.com/mikro-orm/mikro-orm.git"
|
|
13
|
-
},
|
|
14
5
|
"keywords": [
|
|
15
|
-
"
|
|
6
|
+
"data-mapper",
|
|
7
|
+
"ddd",
|
|
8
|
+
"entity",
|
|
9
|
+
"identity-map",
|
|
10
|
+
"javascript",
|
|
11
|
+
"js",
|
|
12
|
+
"mariadb",
|
|
13
|
+
"mikro-orm",
|
|
16
14
|
"mongo",
|
|
17
15
|
"mongodb",
|
|
18
16
|
"mysql",
|
|
19
|
-
"
|
|
17
|
+
"orm",
|
|
20
18
|
"postgresql",
|
|
21
19
|
"sqlite",
|
|
22
20
|
"sqlite3",
|
|
23
21
|
"ts",
|
|
24
22
|
"typescript",
|
|
25
|
-
"
|
|
26
|
-
"javascript",
|
|
27
|
-
"entity",
|
|
28
|
-
"ddd",
|
|
29
|
-
"mikro-orm",
|
|
30
|
-
"unit-of-work",
|
|
31
|
-
"data-mapper",
|
|
32
|
-
"identity-map"
|
|
23
|
+
"unit-of-work"
|
|
33
24
|
],
|
|
34
|
-
"
|
|
35
|
-
"license": "MIT",
|
|
25
|
+
"homepage": "https://mikro-orm.io",
|
|
36
26
|
"bugs": {
|
|
37
27
|
"url": "https://github.com/mikro-orm/mikro-orm/issues"
|
|
38
28
|
},
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"author": "Martin Adámek",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+ssh://git@github.com/mikro-orm/mikro-orm.git"
|
|
34
|
+
},
|
|
35
|
+
"type": "module",
|
|
36
|
+
"exports": {
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
".": "./index.js"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "yarn compile && yarn copy",
|
|
@@ -46,16 +46,16 @@
|
|
|
46
46
|
"compile": "yarn run -T tsc -p tsconfig.build.json",
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
|
-
"publishConfig": {
|
|
50
|
-
"access": "public"
|
|
51
|
-
},
|
|
52
49
|
"dependencies": {
|
|
53
|
-
"@mikro-orm/sql": "7.0.0-rc.
|
|
50
|
+
"@mikro-orm/sql": "7.0.0-rc.3"
|
|
54
51
|
},
|
|
55
52
|
"devDependencies": {
|
|
56
|
-
"@mikro-orm/core": "^6.6.
|
|
53
|
+
"@mikro-orm/core": "^6.6.8"
|
|
57
54
|
},
|
|
58
55
|
"peerDependencies": {
|
|
59
|
-
"@mikro-orm/core": "7.0.0-rc.
|
|
56
|
+
"@mikro-orm/core": "7.0.0-rc.3"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">= 22.17.0"
|
|
60
60
|
}
|
|
61
61
|
}
|