@mikro-orm/entity-generator 6.3.14-dev.1 → 6.3.14-dev.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/EntityGenerator.d.ts +1 -0
- package/EntityGenerator.js +15 -0
- package/SourceFile.js +67 -23
- package/package.json +3 -3
package/EntityGenerator.d.ts
CHANGED
package/EntityGenerator.js
CHANGED
|
@@ -108,6 +108,9 @@ class EntityGenerator {
|
|
|
108
108
|
if (options.customBaseEntityName) {
|
|
109
109
|
this.generateAndAttachCustomBaseEntity(metadata, options.customBaseEntityName);
|
|
110
110
|
}
|
|
111
|
+
if (options.undefinedDefaults) {
|
|
112
|
+
this.castNullDefaultsToUndefined(metadata);
|
|
113
|
+
}
|
|
111
114
|
await options.onProcessedMetadata?.(metadata, this.platform);
|
|
112
115
|
return metadata;
|
|
113
116
|
}
|
|
@@ -226,6 +229,8 @@ class EntityGenerator {
|
|
|
226
229
|
else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.mappedBy) {
|
|
227
230
|
newProp.kind = core_1.ReferenceKind.ONE_TO_ONE;
|
|
228
231
|
newProp.nullable = true;
|
|
232
|
+
newProp.default = null;
|
|
233
|
+
newProp.defaultRaw = 'null';
|
|
229
234
|
}
|
|
230
235
|
else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && !prop.mappedBy) {
|
|
231
236
|
newProp.kind = core_1.ReferenceKind.MANY_TO_MANY;
|
|
@@ -268,5 +273,15 @@ class EntityGenerator {
|
|
|
268
273
|
}));
|
|
269
274
|
}
|
|
270
275
|
}
|
|
276
|
+
castNullDefaultsToUndefined(metadata) {
|
|
277
|
+
for (const meta of metadata) {
|
|
278
|
+
for (const prop of Object.values(meta.properties)) {
|
|
279
|
+
if (prop.nullable && !prop.optional && prop.default === null && typeof prop.defaultRaw === 'undefined') {
|
|
280
|
+
prop.default = undefined;
|
|
281
|
+
prop.optional = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
271
286
|
}
|
|
272
287
|
exports.EntityGenerator = EntityGenerator;
|
package/SourceFile.js
CHANGED
|
@@ -204,7 +204,7 @@ class SourceFile {
|
|
|
204
204
|
return `${padding}${propName}${hiddenType ? `: ${this.referenceCoreImport('Collection')}<${prop.type}>${hiddenType}` : ''} = new ${this.referenceCoreImport('Collection')}<${prop.type}>(this);\n`;
|
|
205
205
|
}
|
|
206
206
|
const isScalar = typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR;
|
|
207
|
-
let
|
|
207
|
+
let breakdownOfIType;
|
|
208
208
|
const propType = prop.mapToPk
|
|
209
209
|
? (() => {
|
|
210
210
|
const runtimeTypes = prop.columnTypes.map((t, i) => (prop.customTypes?.[i] ?? this.platform.getMappedType(t)).runtimeType);
|
|
@@ -215,33 +215,43 @@ class SourceFile {
|
|
|
215
215
|
if (prop.enum) {
|
|
216
216
|
return prop.runtimeType;
|
|
217
217
|
}
|
|
218
|
-
|
|
218
|
+
breakdownOfIType = this.breakdownOfIType(prop);
|
|
219
219
|
if (typeof breakdownOfIType !== 'undefined') {
|
|
220
|
-
|
|
220
|
+
if (breakdownOfIType.length >= 3) {
|
|
221
|
+
hiddenType = '';
|
|
222
|
+
}
|
|
221
223
|
return `${this.referenceCoreImport('IType')}<${breakdownOfIType.join(', ')}>`;
|
|
222
224
|
}
|
|
223
225
|
return prop.runtimeType;
|
|
224
226
|
}
|
|
225
227
|
return prop.type;
|
|
226
228
|
})();
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
229
|
+
const hasUsableNullDefault = (prop.nullable && !this.options.forceUndefined && prop.default === null);
|
|
230
|
+
const useDefault = hasUsableNullDefault || (!(typeof prop.default === 'undefined' || prop.default === null) && propType !== 'unknown' && typeof breakdownOfIType === 'undefined');
|
|
231
|
+
const optional = (prop.nullable && (this.options.forceUndefined || prop.optional)) ? '?' : (useDefault ? '' : '!');
|
|
232
|
+
let ret = `${propName}${optional}: `;
|
|
233
|
+
const isArray = prop.array && (prop.kind === core_1.ReferenceKind.EMBEDDED || prop.enum);
|
|
234
|
+
const complexType = isArray ? `${propType}[]` : propType;
|
|
235
|
+
let wrappedType = prop.ref
|
|
236
|
+
? `${this.referenceCoreImport('Ref')}<${complexType}${(isScalar && prop.nullable && !this.options.forceUndefined) ? ' | null' : ''}>`
|
|
237
|
+
: ((this.options.esmImport && !isScalar) ? `${this.referenceCoreImport('Rel')}<${complexType}>` : complexType);
|
|
238
|
+
if (prop.nullable && !this.options.forceUndefined && (!isScalar || (!prop.ref && !wrappedType.includes(' | null')))) {
|
|
239
|
+
wrappedType += ' | null';
|
|
240
|
+
}
|
|
241
|
+
const optionalType = (optional !== '?' && prop.optional)
|
|
242
|
+
? ` & ${this.referenceCoreImport('Opt')}`
|
|
243
|
+
: '';
|
|
244
|
+
ret += (!this.options.forceUndefined && prop.nullable && (hiddenType || optionalType)) ? `(${wrappedType})` : wrappedType;
|
|
233
245
|
ret += hiddenType;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
if (!useDefault || hasITypeWrapper || prop.type === 'unknown') {
|
|
246
|
+
ret += optionalType;
|
|
247
|
+
if (!useDefault) {
|
|
238
248
|
return `${padding}${ret};\n`;
|
|
239
249
|
}
|
|
240
250
|
if (prop.enum && typeof prop.default === 'string') {
|
|
241
251
|
const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
242
252
|
return `${padding}${ret} = ${propType}${exports.identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
|
|
243
253
|
}
|
|
244
|
-
if (prop.fieldNames
|
|
254
|
+
if (prop.fieldNames?.length > 1) {
|
|
245
255
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
246
256
|
return `${padding}${ret};\n`;
|
|
247
257
|
}
|
|
@@ -249,6 +259,9 @@ class SourceFile {
|
|
|
249
259
|
if (isScalar) {
|
|
250
260
|
return `${padding}${ret} = ${prop.ref ? `${this.referenceCoreImport('ref')}(${defaultVal})` : defaultVal};\n`;
|
|
251
261
|
}
|
|
262
|
+
if (hasUsableNullDefault) {
|
|
263
|
+
return `${padding}${ret} = null;\n`;
|
|
264
|
+
}
|
|
252
265
|
return `${padding}${ret} = ${prop.ref ? this.referenceCoreImport('ref') : this.referenceCoreImport('rel')}(${propType}, ${defaultVal});\n`;
|
|
253
266
|
}
|
|
254
267
|
getEnumClassDefinition(prop, padLeft) {
|
|
@@ -414,7 +427,7 @@ class SourceFile {
|
|
|
414
427
|
return ret;
|
|
415
428
|
}
|
|
416
429
|
getCommonDecoratorOptions(options, prop) {
|
|
417
|
-
if (prop.
|
|
430
|
+
if (!prop.mappedBy && (prop.nullable || prop.customTypes?.[0]?.prop?.nullable)) {
|
|
418
431
|
options.nullable = true;
|
|
419
432
|
}
|
|
420
433
|
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR))) {
|
|
@@ -443,11 +456,11 @@ class SourceFile {
|
|
|
443
456
|
}
|
|
444
457
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
445
458
|
if (prop.fieldNames?.length <= 1) {
|
|
446
|
-
if (typeof prop.defaultRaw !== 'undefined' && prop.defaultRaw !== 'null' &&
|
|
459
|
+
if (typeof prop.defaultRaw !== 'undefined' && prop.defaultRaw !== 'null' && prop.defaultRaw !== '' &&
|
|
447
460
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
448
461
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
449
462
|
}
|
|
450
|
-
else if (prop.default
|
|
463
|
+
else if (!(typeof prop.default === 'undefined' || prop.default === null) && (prop.ref || (!prop.enum && (typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR) && (prop.type === 'unknown' || typeof this.breakdownOfIType(prop) !== 'undefined')))) {
|
|
451
464
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
452
465
|
}
|
|
453
466
|
}
|
|
@@ -472,7 +485,8 @@ class SourceFile {
|
|
|
472
485
|
? this.platform.getMappedType(prop.columnTypes[0])
|
|
473
486
|
: mappedDeclaredType));
|
|
474
487
|
const rawType = mappedRawType.runtimeType;
|
|
475
|
-
const
|
|
488
|
+
const mappedSerializedType = (prop.customType ?? mappedRawType);
|
|
489
|
+
const serializedType = mappedSerializedType.runtimeType;
|
|
476
490
|
// Add non-lib imports where needed.
|
|
477
491
|
for (const typeSpec of [prop.runtimeType, rawType, serializedType]) {
|
|
478
492
|
const simplePropType = typeSpec.replace(/\[]+$/, '');
|
|
@@ -480,13 +494,37 @@ class SourceFile {
|
|
|
480
494
|
this.entityImports.add(simplePropType);
|
|
481
495
|
}
|
|
482
496
|
}
|
|
483
|
-
|
|
484
|
-
|
|
497
|
+
const nullables = [
|
|
498
|
+
prop.nullable ?? false,
|
|
499
|
+
mappedRawType.prop?.nullable ?? prop.nullable ?? false,
|
|
500
|
+
mappedSerializedType.prop?.nullable ?? prop.nullable ?? false,
|
|
501
|
+
];
|
|
502
|
+
const hasMixedNullability = (new Set(nullables)).size > 1;
|
|
503
|
+
if (prop.runtimeType !== rawType || rawType !== serializedType || hasMixedNullability) {
|
|
504
|
+
const nullType = this.options.forceUndefined ? ' | undefined' : ' | null';
|
|
505
|
+
if (rawType !== serializedType || nullables[1] !== nullables[2] || (prop.hidden && nullables[0] !== nullables[1])) {
|
|
485
506
|
const r = [prop.runtimeType, rawType, serializedType];
|
|
507
|
+
if (hasMixedNullability || prop.hidden) {
|
|
508
|
+
for (let i = r.length - 1; i >= 0; --i) {
|
|
509
|
+
if (nullables[i]) {
|
|
510
|
+
r[i] += nullType;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (prop.hidden) {
|
|
514
|
+
r[2] = `(${r[2]}) & ${this.referenceCoreImport('Hidden')}`;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
486
517
|
this.propTypeBreakdowns.set(prop, r);
|
|
487
518
|
return r;
|
|
488
519
|
}
|
|
489
520
|
const r = [prop.runtimeType, rawType];
|
|
521
|
+
if (hasMixedNullability) {
|
|
522
|
+
for (let i = r.length - 1; i >= 0; --i) {
|
|
523
|
+
if (nullables[i]) {
|
|
524
|
+
r[i] += nullType;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
490
528
|
this.propTypeBreakdowns.set(prop, r);
|
|
491
529
|
return r;
|
|
492
530
|
}
|
|
@@ -519,8 +557,14 @@ class SourceFile {
|
|
|
519
557
|
}
|
|
520
558
|
else {
|
|
521
559
|
if (this.options.scalarTypeInDecorator // always output type if forced by the generator options
|
|
522
|
-
||
|
|
523
|
-
||
|
|
560
|
+
|| (prop.nullable && !this.options.forceUndefined) // also when there is the "| null" type modifier (because reflect-metadata can't extract the base)
|
|
561
|
+
|| prop.hidden // also when there is the "& Hidden" type modifier (because reflect-metadata can't extract the base)
|
|
562
|
+
|| (new Set([mappedRuntimeType.name, mappedColumnType.name, mappedDeclaredType.name, this.platform.getMappedType(prop.runtimeType === 'Date' ? 'datetime' : prop.runtimeType).name])).size > 1 // also, if there's any ambiguity in the type
|
|
563
|
+
|| (() => {
|
|
564
|
+
const hasUsableNullDefault = (prop.nullable && !this.options.forceUndefined && prop.default === null);
|
|
565
|
+
const useDefault = hasUsableNullDefault || !(typeof prop.default === 'undefined' || prop.default === null);
|
|
566
|
+
return ((useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable));
|
|
567
|
+
})() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
|
|
524
568
|
) {
|
|
525
569
|
options.type = this.quote(prop.type);
|
|
526
570
|
}
|
|
@@ -659,7 +703,7 @@ class SourceFile {
|
|
|
659
703
|
if (prop.generated) {
|
|
660
704
|
options.generated = typeof prop.generated === 'string' ? this.quote(prop.generated) : `${prop.generated}`;
|
|
661
705
|
}
|
|
662
|
-
if (prop.fieldNames.length > 1 && prop.default
|
|
706
|
+
if (prop.fieldNames.length > 1 && !(typeof prop.default === 'undefined' || prop.default === null)) {
|
|
663
707
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
664
708
|
options.ignoreSchemaChanges = [this.quote('default')];
|
|
665
709
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/entity-generator",
|
|
3
|
-
"version": "6.3.14-dev.
|
|
3
|
+
"version": "6.3.14-dev.3",
|
|
4
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.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@mikro-orm/knex": "6.3.14-dev.
|
|
61
|
+
"@mikro-orm/knex": "6.3.14-dev.3",
|
|
62
62
|
"fs-extra": "11.2.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@mikro-orm/core": "^6.3.13"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
|
-
"@mikro-orm/core": "6.3.14-dev.
|
|
68
|
+
"@mikro-orm/core": "6.3.14-dev.3"
|
|
69
69
|
}
|
|
70
70
|
}
|