@mikro-orm/entity-generator 7.0.0-dev.33 → 7.0.0-dev.330
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.d.ts +5 -0
- package/DefineEntitySourceFile.js +146 -0
- package/EntityGenerator.d.ts +3 -10
- package/EntityGenerator.js +161 -76
- package/EntitySchemaSourceFile.d.ts +3 -2
- package/EntitySchemaSourceFile.js +53 -38
- package/NativeEnumSourceFile.d.ts +12 -0
- package/NativeEnumSourceFile.js +47 -0
- package/README.md +7 -4
- package/SourceFile.d.ts +9 -2
- package/SourceFile.js +307 -112
- package/package.json +32 -32
package/SourceFile.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { Cascade, Config, DecimalType, ReferenceKind, SCALAR_TYPES, UnknownType, Utils, } from '@mikro-orm/core';
|
|
1
|
+
import { Cascade, Config, DecimalType, ReferenceKind, SCALAR_TYPES, UnknownType, Utils, inspect, } from '@mikro-orm/core';
|
|
2
2
|
import { parse, relative } from 'node:path';
|
|
3
|
-
import { inspect } from 'node:util';
|
|
4
3
|
import { POSSIBLE_TYPE_IMPORTS } from './CoreImportsHelper.js';
|
|
5
4
|
/**
|
|
6
5
|
* @see https://github.com/tc39/proposal-regexp-unicode-property-escapes#other-examples
|
|
7
6
|
*/
|
|
8
7
|
export const identifierRegex = /^(?:[$_\p{ID_Start}])(?:[$\u200C\u200D\p{ID_Continue}])*$/u;
|
|
9
|
-
const primitivesAndLibs = [...SCALAR_TYPES, '
|
|
8
|
+
const primitivesAndLibs = [...SCALAR_TYPES, 'unknown', 'object', 'any'];
|
|
10
9
|
export class SourceFile {
|
|
11
10
|
meta;
|
|
12
11
|
namingStrategy;
|
|
13
12
|
platform;
|
|
14
13
|
options;
|
|
15
14
|
coreImports = new Set();
|
|
15
|
+
decoratorImports = new Set();
|
|
16
16
|
entityImports = new Set();
|
|
17
|
+
enumImports = new Map();
|
|
17
18
|
constructor(meta, namingStrategy, platform, options) {
|
|
18
19
|
this.meta = meta;
|
|
19
20
|
this.namingStrategy = namingStrategy;
|
|
@@ -25,24 +26,24 @@ export class SourceFile {
|
|
|
25
26
|
if (this.meta.embeddable || this.meta.collection) {
|
|
26
27
|
if (this.meta.embeddable) {
|
|
27
28
|
const options = this.getEmbeddableDeclOptions();
|
|
28
|
-
ret += `@${this.
|
|
29
|
+
ret += `@${this.referenceDecoratorImport('Embeddable')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
29
30
|
}
|
|
30
31
|
else {
|
|
31
32
|
const options = this.getEntityDeclOptions();
|
|
32
|
-
ret += `@${this.
|
|
33
|
+
ret += `@${this.referenceDecoratorImport('Entity')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
for (const index of this.meta.indexes) {
|
|
36
37
|
if (index.properties?.length === 1 && typeof this.meta.properties[index.properties[0]] !== 'undefined') {
|
|
37
38
|
continue;
|
|
38
39
|
}
|
|
39
|
-
ret += `@${this.
|
|
40
|
+
ret += `@${this.referenceDecoratorImport('Index')}(${this.serializeObject(this.getIndexOptions(index))})\n`;
|
|
40
41
|
}
|
|
41
42
|
for (const index of this.meta.uniques) {
|
|
42
43
|
if (index.properties?.length === 1 && typeof this.meta.properties[index.properties[0]] !== 'undefined') {
|
|
43
44
|
continue;
|
|
44
45
|
}
|
|
45
|
-
ret += `@${this.
|
|
46
|
+
ret += `@${this.referenceDecoratorImport('Unique')}(${this.serializeObject(this.getUniqueOptions(index))})\n`;
|
|
46
47
|
}
|
|
47
48
|
let classHead = '';
|
|
48
49
|
if (this.meta.className === this.options.customBaseEntityName) {
|
|
@@ -65,7 +66,10 @@ export class SourceFile {
|
|
|
65
66
|
classBody += definition;
|
|
66
67
|
classBody += '\n';
|
|
67
68
|
if (prop.enum) {
|
|
68
|
-
|
|
69
|
+
const def = this.getEnumClassDefinition(prop, 2);
|
|
70
|
+
if (def.length) {
|
|
71
|
+
enumDefinitions.push(def);
|
|
72
|
+
}
|
|
69
73
|
}
|
|
70
74
|
if (prop.eager) {
|
|
71
75
|
eagerProperties.push(prop);
|
|
@@ -94,6 +98,30 @@ export class SourceFile {
|
|
|
94
98
|
}
|
|
95
99
|
return ret;
|
|
96
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Convert index column options to quoted output format.
|
|
103
|
+
*/
|
|
104
|
+
getColumnOptions(columns) {
|
|
105
|
+
if (!columns?.length) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return columns.map(col => {
|
|
109
|
+
const colOpt = { name: this.quote(col.name) };
|
|
110
|
+
if (col.sort) {
|
|
111
|
+
colOpt.sort = this.quote(col.sort.toUpperCase());
|
|
112
|
+
}
|
|
113
|
+
if (col.nulls) {
|
|
114
|
+
colOpt.nulls = this.quote(col.nulls.toUpperCase());
|
|
115
|
+
}
|
|
116
|
+
if (col.length != null) {
|
|
117
|
+
colOpt.length = col.length;
|
|
118
|
+
}
|
|
119
|
+
if (col.collation) {
|
|
120
|
+
colOpt.collation = this.quote(col.collation);
|
|
121
|
+
}
|
|
122
|
+
return colOpt;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
97
125
|
getIndexOptions(index, isAtEntityLevel = true) {
|
|
98
126
|
const indexOpt = {};
|
|
99
127
|
if (typeof index.name === 'string') {
|
|
@@ -108,6 +136,30 @@ export class SourceFile {
|
|
|
108
136
|
if (isAtEntityLevel && index.properties) {
|
|
109
137
|
indexOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
110
138
|
}
|
|
139
|
+
// Index type (e.g., 'fulltext', 'spatial', 'btree', 'hash')
|
|
140
|
+
if (index.type) {
|
|
141
|
+
indexOpt.type = this.quote(index.type);
|
|
142
|
+
}
|
|
143
|
+
// Advanced index options
|
|
144
|
+
const columns = this.getColumnOptions(index.columns);
|
|
145
|
+
if (columns) {
|
|
146
|
+
indexOpt.columns = columns;
|
|
147
|
+
}
|
|
148
|
+
if (index.include) {
|
|
149
|
+
indexOpt.include = Utils.asArray(index.include).map(prop => this.quote('' + prop));
|
|
150
|
+
}
|
|
151
|
+
if (index.fillFactor != null) {
|
|
152
|
+
indexOpt.fillFactor = index.fillFactor;
|
|
153
|
+
}
|
|
154
|
+
if (index.invisible) {
|
|
155
|
+
indexOpt.invisible = true;
|
|
156
|
+
}
|
|
157
|
+
if (index.disabled) {
|
|
158
|
+
indexOpt.disabled = true;
|
|
159
|
+
}
|
|
160
|
+
if (index.clustered) {
|
|
161
|
+
indexOpt.clustered = true;
|
|
162
|
+
}
|
|
111
163
|
return indexOpt;
|
|
112
164
|
}
|
|
113
165
|
getUniqueOptions(index, isAtEntityLevel = true) {
|
|
@@ -125,53 +177,97 @@ export class SourceFile {
|
|
|
125
177
|
uniqueOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
126
178
|
}
|
|
127
179
|
if (index.deferMode) {
|
|
128
|
-
uniqueOpt.deferMode =
|
|
180
|
+
uniqueOpt.deferMode =
|
|
181
|
+
`${this.referenceCoreImport('DeferMode')}.INITIALLY_${index.deferMode.toUpperCase()}`;
|
|
182
|
+
}
|
|
183
|
+
const columns = this.getColumnOptions(index.columns);
|
|
184
|
+
if (columns) {
|
|
185
|
+
uniqueOpt.columns = columns;
|
|
186
|
+
}
|
|
187
|
+
if (index.include) {
|
|
188
|
+
uniqueOpt.include = Utils.asArray(index.include).map(prop => this.quote('' + prop));
|
|
189
|
+
}
|
|
190
|
+
if (index.fillFactor != null) {
|
|
191
|
+
uniqueOpt.fillFactor = index.fillFactor;
|
|
192
|
+
}
|
|
193
|
+
if (index.disabled) {
|
|
194
|
+
uniqueOpt.disabled = true;
|
|
129
195
|
}
|
|
130
196
|
return uniqueOpt;
|
|
131
197
|
}
|
|
132
198
|
generateImports() {
|
|
133
199
|
const imports = new Set();
|
|
134
200
|
if (this.coreImports.size > 0) {
|
|
135
|
-
imports.add(`import { ${
|
|
201
|
+
imports.add(`import { ${[...this.coreImports]
|
|
202
|
+
.sort()
|
|
203
|
+
.map(t => {
|
|
136
204
|
let ret = POSSIBLE_TYPE_IMPORTS.includes(t) ? `type ${t}` : t;
|
|
137
205
|
if (this.options.coreImportsPrefix) {
|
|
138
206
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
139
207
|
ret += ` as ${resolvedIdentifier}`;
|
|
140
208
|
}
|
|
141
209
|
return ret;
|
|
142
|
-
})
|
|
210
|
+
})
|
|
211
|
+
.join(', ')} } from '@mikro-orm/core';`);
|
|
212
|
+
}
|
|
213
|
+
if (this.decoratorImports.size > 0) {
|
|
214
|
+
const type = this.options.decorators;
|
|
215
|
+
imports.add(`import { ${[...this.decoratorImports]
|
|
216
|
+
.sort()
|
|
217
|
+
.map(t => {
|
|
218
|
+
let ret = t;
|
|
219
|
+
if (this.options.coreImportsPrefix) {
|
|
220
|
+
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
221
|
+
ret += ` as ${resolvedIdentifier}`;
|
|
222
|
+
}
|
|
223
|
+
return ret;
|
|
224
|
+
})
|
|
225
|
+
.join(', ')} } from '@mikro-orm/decorators/${type}';`);
|
|
143
226
|
}
|
|
144
227
|
const extension = this.options.esmImport ? '.js' : '';
|
|
145
228
|
const { dir, base } = parse(`${this.options.path ?? '.'}/${this.getBaseName()}`);
|
|
146
229
|
const basePath = relative(dir, this.options.path ?? '.') || '.';
|
|
147
230
|
(this.options.extraImports?.(basePath, base) ?? []).forEach(v => this.entityImports.add(v));
|
|
148
231
|
const entityImports = [...this.entityImports].filter(e => e !== this.meta.className);
|
|
149
|
-
|
|
232
|
+
const importMap = new Map();
|
|
233
|
+
for (const entity of entityImports) {
|
|
150
234
|
const file = this.options.onImport?.(entity, basePath, extension, base) ?? {
|
|
151
235
|
path: `${basePath}/${this.options.fileName(entity)}${extension}`,
|
|
152
236
|
name: entity,
|
|
153
237
|
};
|
|
154
238
|
if (file.path === '') {
|
|
155
239
|
if (file.name === '') {
|
|
156
|
-
|
|
240
|
+
continue;
|
|
157
241
|
}
|
|
158
|
-
|
|
159
|
-
|
|
242
|
+
importMap.set(file.path, `import ${this.quote(file.name)};`);
|
|
243
|
+
continue;
|
|
160
244
|
}
|
|
161
245
|
if (file.name === '') {
|
|
162
|
-
|
|
163
|
-
|
|
246
|
+
importMap.set(file.path, `import * as ${entity} from ${this.quote(file.path)};`);
|
|
247
|
+
continue;
|
|
164
248
|
}
|
|
165
249
|
if (file.name === 'default') {
|
|
166
|
-
|
|
167
|
-
|
|
250
|
+
importMap.set(file.path, `import ${entity} from ${this.quote(file.path)};`);
|
|
251
|
+
continue;
|
|
168
252
|
}
|
|
169
253
|
if (file.name === entity) {
|
|
170
|
-
|
|
171
|
-
|
|
254
|
+
importMap.set(file.path, `import { ${entity} } from ${this.quote(file.path)};`);
|
|
255
|
+
continue;
|
|
172
256
|
}
|
|
173
|
-
|
|
174
|
-
}
|
|
257
|
+
importMap.set(file.path, `import { ${identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
|
|
258
|
+
}
|
|
259
|
+
if (this.enumImports.size) {
|
|
260
|
+
for (const [name, exports] of this.enumImports.entries()) {
|
|
261
|
+
const file = this.options.onImport?.(name, basePath, extension, base) ?? {
|
|
262
|
+
path: `${basePath}/${this.options.fileName(name)}${extension}`,
|
|
263
|
+
name,
|
|
264
|
+
};
|
|
265
|
+
importMap.set(file.path, `import { ${exports.join(', ')} } from ${this.quote(file.path)};`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
for (const key of [...importMap.keys()].sort()) {
|
|
269
|
+
imports.add(importMap.get(key));
|
|
270
|
+
}
|
|
175
271
|
return Array.from(imports.values()).join('\n');
|
|
176
272
|
}
|
|
177
273
|
getEntityClass(classBody) {
|
|
@@ -181,8 +277,8 @@ export class SourceFile {
|
|
|
181
277
|
}
|
|
182
278
|
ret += `class ${this.meta.className}`;
|
|
183
279
|
if (this.meta.extends) {
|
|
184
|
-
this.entityImports.add(this.meta.extends);
|
|
185
|
-
ret += ` extends ${this.meta.extends}`;
|
|
280
|
+
this.entityImports.add(Utils.className(this.meta.extends));
|
|
281
|
+
ret += ` extends ${Utils.className(this.meta.extends)}`;
|
|
186
282
|
}
|
|
187
283
|
else if (this.options.useCoreBaseEntity) {
|
|
188
284
|
ret += ` extends ${this.referenceCoreImport('BaseEntity')}`;
|
|
@@ -201,6 +297,7 @@ export class SourceFile {
|
|
|
201
297
|
getPropertyDefinition(prop, padLeft) {
|
|
202
298
|
const padding = ' '.repeat(padLeft);
|
|
203
299
|
const propName = identifierRegex.test(prop.name) ? prop.name : this.quote(prop.name);
|
|
300
|
+
const enumMode = this.options.enumMode;
|
|
204
301
|
let hiddenType = '';
|
|
205
302
|
if (prop.hidden) {
|
|
206
303
|
hiddenType += ` & ${this.referenceCoreImport('Hidden')}`;
|
|
@@ -218,7 +315,11 @@ export class SourceFile {
|
|
|
218
315
|
: (() => {
|
|
219
316
|
if (isScalar) {
|
|
220
317
|
if (prop.enum) {
|
|
221
|
-
|
|
318
|
+
const method = enumMode === 'ts-enum' ? 'getEnumClassName' : 'getEnumTypeName';
|
|
319
|
+
if (prop.nativeEnumName) {
|
|
320
|
+
return this.namingStrategy[method](prop.nativeEnumName, undefined, this.meta.schema);
|
|
321
|
+
}
|
|
322
|
+
return this.namingStrategy[method](prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
222
323
|
}
|
|
223
324
|
breakdownOfIType = this.breakdownOfIType(prop);
|
|
224
325
|
if (typeof breakdownOfIType !== 'undefined') {
|
|
@@ -231,30 +332,42 @@ export class SourceFile {
|
|
|
231
332
|
}
|
|
232
333
|
return prop.type;
|
|
233
334
|
})();
|
|
234
|
-
const hasUsableNullDefault =
|
|
235
|
-
const useDefault = hasUsableNullDefault ||
|
|
236
|
-
|
|
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 ? '' : '!';
|
|
237
341
|
let ret = `${propName}${optional}: `;
|
|
238
342
|
const isArray = prop.array && (prop.kind === ReferenceKind.EMBEDDED || prop.enum);
|
|
239
343
|
const complexType = isArray ? `${propType}[]` : propType;
|
|
240
344
|
let wrappedType = prop.ref
|
|
241
|
-
? `${this.referenceCoreImport('Ref')}<${complexType}${
|
|
242
|
-
:
|
|
243
|
-
|
|
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')))) {
|
|
244
352
|
wrappedType += ' | null';
|
|
245
353
|
}
|
|
246
|
-
const optionalType =
|
|
247
|
-
|
|
248
|
-
:
|
|
249
|
-
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;
|
|
250
357
|
ret += hiddenType;
|
|
251
358
|
ret += optionalType;
|
|
252
359
|
if (!useDefault) {
|
|
253
360
|
return `${padding}${ret};\n`;
|
|
254
361
|
}
|
|
255
362
|
if (prop.enum && typeof prop.default === 'string') {
|
|
363
|
+
if (enumMode === 'union-type') {
|
|
364
|
+
return `${padding}${ret} = ${this.quote(prop.default)};\n`;
|
|
365
|
+
}
|
|
366
|
+
const enumClassName = prop.nativeEnumName
|
|
367
|
+
? this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema)
|
|
368
|
+
: this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
256
369
|
const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
257
|
-
return `${padding}${ret} = ${
|
|
370
|
+
return `${padding}${ret} = ${enumClassName}${identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
|
|
258
371
|
}
|
|
259
372
|
if (prop.fieldNames?.length > 1) {
|
|
260
373
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
@@ -270,15 +383,51 @@ export class SourceFile {
|
|
|
270
383
|
return `${padding}${ret} = ${prop.ref ? this.referenceCoreImport('ref') : this.referenceCoreImport('rel')}(${propType}, ${defaultVal});\n`;
|
|
271
384
|
}
|
|
272
385
|
getEnumClassDefinition(prop, padLeft) {
|
|
386
|
+
const enumMode = this.options.enumMode;
|
|
387
|
+
if (prop.nativeEnumName) {
|
|
388
|
+
const imports = [];
|
|
389
|
+
if (enumMode !== 'union-type') {
|
|
390
|
+
imports.push(prop.runtimeType);
|
|
391
|
+
}
|
|
392
|
+
if (!this.options.inferEntityType && enumMode !== 'ts-enum') {
|
|
393
|
+
const enumTypeName = this.namingStrategy.getEnumTypeName(prop.nativeEnumName, undefined, this.meta.schema);
|
|
394
|
+
imports.push(enumTypeName);
|
|
395
|
+
}
|
|
396
|
+
this.enumImports.set(prop.runtimeType, imports);
|
|
397
|
+
return '';
|
|
398
|
+
}
|
|
273
399
|
const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
400
|
+
const enumTypeName = this.namingStrategy.getEnumTypeName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
274
401
|
const padding = ' '.repeat(padLeft);
|
|
275
|
-
let ret = `export enum ${enumClassName} {\n`;
|
|
276
402
|
const enumValues = prop.items;
|
|
403
|
+
if (enumMode === 'union-type') {
|
|
404
|
+
return `export type ${enumTypeName} = ${enumValues.map(item => this.quote(item)).join(' | ')};\n`;
|
|
405
|
+
}
|
|
406
|
+
let ret = '';
|
|
407
|
+
if (enumMode === 'dictionary') {
|
|
408
|
+
ret += `export const ${enumClassName} = {\n`;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
ret += `export enum ${enumClassName} {\n`;
|
|
412
|
+
}
|
|
277
413
|
for (const enumValue of enumValues) {
|
|
278
414
|
const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
279
|
-
|
|
415
|
+
if (enumMode === 'dictionary') {
|
|
416
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)}: ${this.quote(enumValue)},\n`;
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (enumMode === 'dictionary') {
|
|
423
|
+
ret += '} as const;\n';
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
ret += '}\n';
|
|
427
|
+
}
|
|
428
|
+
if (enumMode === 'dictionary') {
|
|
429
|
+
ret += `\nexport type ${enumTypeName} = (typeof ${enumClassName})[keyof typeof ${enumClassName}];\n`;
|
|
280
430
|
}
|
|
281
|
-
ret += '}\n';
|
|
282
431
|
return ret;
|
|
283
432
|
}
|
|
284
433
|
serializeObject(options, wordwrap, spaces, level = 0) {
|
|
@@ -288,17 +437,19 @@ export class SourceFile {
|
|
|
288
437
|
return res;
|
|
289
438
|
}
|
|
290
439
|
}
|
|
291
|
-
const nextWordwrap = typeof wordwrap === 'number' ? 80 - (spaces ?? 0) -
|
|
440
|
+
const nextWordwrap = typeof wordwrap === 'number' ? 80 - (spaces ?? 0) - level * 2 : undefined;
|
|
292
441
|
const sep = typeof spaces === 'undefined' ? ', ' : `,\n${' '.repeat(spaces)}`;
|
|
293
442
|
const doIndent = typeof spaces !== 'undefined';
|
|
294
443
|
if (Array.isArray(options)) {
|
|
295
|
-
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)}` : ''}]`;
|
|
296
445
|
}
|
|
297
446
|
const entries = Object.entries(options);
|
|
298
|
-
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries
|
|
447
|
+
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries
|
|
448
|
+
.map(([opt, val]) => {
|
|
299
449
|
const key = identifierRegex.test(opt) ? opt : this.quote(opt);
|
|
300
|
-
return `${doIndent ? ' '.repeat(
|
|
301
|
-
})
|
|
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)}` : ' '}}`;
|
|
302
453
|
}
|
|
303
454
|
serializeValue(val, wordwrap, spaces, level = 1) {
|
|
304
455
|
if (typeof val === 'object' && val !== null) {
|
|
@@ -308,8 +459,8 @@ export class SourceFile {
|
|
|
308
459
|
}
|
|
309
460
|
getEntityDeclOptions() {
|
|
310
461
|
const options = {};
|
|
311
|
-
if (this.meta.
|
|
312
|
-
options.tableName = this.quote(this.meta.
|
|
462
|
+
if (this.meta.tableName !== this.namingStrategy.classToTableName(this.meta.className)) {
|
|
463
|
+
options.tableName = this.quote(this.meta.tableName);
|
|
313
464
|
}
|
|
314
465
|
if (this.meta.schema && this.meta.schema !== this.platform.getDefaultSchemaName()) {
|
|
315
466
|
options.schema = this.quote(this.meta.schema);
|
|
@@ -318,7 +469,7 @@ export class SourceFile {
|
|
|
318
469
|
options.expression = this.quote(this.meta.expression);
|
|
319
470
|
}
|
|
320
471
|
else if (typeof this.meta.expression === 'function') {
|
|
321
|
-
options.expression =
|
|
472
|
+
options.expression = this.meta.expression.toString();
|
|
322
473
|
}
|
|
323
474
|
if (this.meta.repositoryClass) {
|
|
324
475
|
this.entityImports.add(this.meta.repositoryClass);
|
|
@@ -337,28 +488,38 @@ export class SourceFile {
|
|
|
337
488
|
}
|
|
338
489
|
getEmbeddableDeclOptions() {
|
|
339
490
|
const options = {};
|
|
340
|
-
|
|
491
|
+
const result = this.getCollectionDecl(options);
|
|
492
|
+
if (result.discriminatorColumn) {
|
|
493
|
+
result.discriminator = result.discriminatorColumn;
|
|
494
|
+
delete result.discriminatorColumn;
|
|
495
|
+
}
|
|
496
|
+
return result;
|
|
341
497
|
}
|
|
342
498
|
getCollectionDecl(options) {
|
|
343
499
|
if (this.meta.abstract) {
|
|
344
500
|
options.abstract = true;
|
|
345
501
|
}
|
|
346
502
|
if (this.meta.discriminatorValue) {
|
|
347
|
-
options.discriminatorValue =
|
|
503
|
+
options.discriminatorValue =
|
|
504
|
+
typeof this.meta.discriminatorValue === 'string'
|
|
505
|
+
? this.quote(this.meta.discriminatorValue)
|
|
506
|
+
: this.meta.discriminatorValue;
|
|
348
507
|
}
|
|
349
508
|
if (this.meta.discriminatorColumn) {
|
|
350
509
|
options.discriminatorColumn = this.quote(this.meta.discriminatorColumn);
|
|
351
510
|
}
|
|
352
511
|
if (this.meta.discriminatorMap) {
|
|
353
|
-
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap)
|
|
354
|
-
|
|
512
|
+
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap).map(([discriminatorValue, cls]) => [
|
|
513
|
+
discriminatorValue,
|
|
514
|
+
this.quote(Utils.className(cls)),
|
|
515
|
+
]));
|
|
355
516
|
}
|
|
356
517
|
return options;
|
|
357
518
|
}
|
|
358
519
|
getPropertyDecorator(prop, padLeft) {
|
|
359
520
|
const padding = ' '.repeat(padLeft);
|
|
360
521
|
const options = {};
|
|
361
|
-
let decorator = `@${this.
|
|
522
|
+
let decorator = `@${this.referenceDecoratorImport(this.getDecoratorType(prop))}`;
|
|
362
523
|
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
363
524
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
364
525
|
}
|
|
@@ -379,10 +540,10 @@ export class SourceFile {
|
|
|
379
540
|
decorator = [...indexes.sort(), decorator].map(d => padding + d).join('\n');
|
|
380
541
|
const decoratorArgs = [];
|
|
381
542
|
if (prop.formula) {
|
|
382
|
-
decoratorArgs.push(
|
|
543
|
+
decoratorArgs.push(prop.formula.toString());
|
|
383
544
|
}
|
|
384
545
|
if (Utils.hasObjectKeys(options)) {
|
|
385
|
-
decoratorArgs.push(
|
|
546
|
+
decoratorArgs.push(this.serializeObject(options));
|
|
386
547
|
}
|
|
387
548
|
return `${decorator}(${decoratorArgs.join(', ')})\n`;
|
|
388
549
|
}
|
|
@@ -393,7 +554,7 @@ export class SourceFile {
|
|
|
393
554
|
return;
|
|
394
555
|
}
|
|
395
556
|
const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
|
|
396
|
-
options[type] =
|
|
557
|
+
options[type] = propType === true || defaultName === propType ? 'true' : this.quote(propType);
|
|
397
558
|
const expected = {
|
|
398
559
|
index: this.platform.indexForeignKeys(),
|
|
399
560
|
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
@@ -408,26 +569,26 @@ export class SourceFile {
|
|
|
408
569
|
let propIndexIsNonTrivialIndex = false;
|
|
409
570
|
const nonTrivialIndexes = this.meta.indexes.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
410
571
|
for (const i of nonTrivialIndexes) {
|
|
411
|
-
ret.push(`@${this.
|
|
572
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${this.serializeObject(this.getIndexOptions(i, false))})`);
|
|
412
573
|
if (prop.index === i.name) {
|
|
413
574
|
propIndexIsNonTrivialIndex = true;
|
|
414
575
|
delete options.index;
|
|
415
576
|
}
|
|
416
577
|
}
|
|
417
578
|
if (prop.index && !options.index && !propIndexIsNonTrivialIndex) {
|
|
418
|
-
ret.push(`@${this.
|
|
579
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${typeof prop.index === 'string' ? `{ name: ${this.quote(prop.index)} }` : ''})`);
|
|
419
580
|
}
|
|
420
581
|
let propIndexIsNonTrivialUnique = false;
|
|
421
582
|
const nonTrivialUnique = this.meta.uniques.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
422
583
|
for (const i of nonTrivialUnique) {
|
|
423
|
-
ret.push(`@${this.
|
|
584
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${this.serializeObject(this.getUniqueOptions(i, false))})`);
|
|
424
585
|
if (prop.unique === i.name) {
|
|
425
586
|
propIndexIsNonTrivialUnique = true;
|
|
426
587
|
delete options.unique;
|
|
427
588
|
}
|
|
428
589
|
}
|
|
429
590
|
if (prop.unique && !options.unique && !propIndexIsNonTrivialUnique) {
|
|
430
|
-
ret.push(`@${this.
|
|
591
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${typeof prop.unique === 'string' ? `{ name: ${this.quote(prop.unique)} }` : ''})`);
|
|
431
592
|
}
|
|
432
593
|
return ret;
|
|
433
594
|
}
|
|
@@ -438,12 +599,10 @@ export class SourceFile {
|
|
|
438
599
|
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
439
600
|
options.primary = true;
|
|
440
601
|
}
|
|
441
|
-
['persist', 'hydrate'
|
|
442
|
-
.filter(key => prop[key] === false)
|
|
443
|
-
.forEach(key => options[key] = false);
|
|
602
|
+
['persist', 'hydrate'].filter(key => prop[key] === false).forEach(key => (options[key] = false));
|
|
444
603
|
['onCreate', 'onUpdate', 'serializer']
|
|
445
604
|
.filter(key => typeof prop[key] === 'function')
|
|
446
|
-
.forEach(key => options[key] = `${prop[key]}`);
|
|
605
|
+
.forEach(key => (options[key] = `${prop[key]}`));
|
|
447
606
|
if (typeof prop.serializedName === 'string') {
|
|
448
607
|
options.serializedName = this.quote(prop.serializedName);
|
|
449
608
|
}
|
|
@@ -452,7 +611,7 @@ export class SourceFile {
|
|
|
452
611
|
}
|
|
453
612
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
454
613
|
.filter(key => prop[key])
|
|
455
|
-
.forEach(key => options[key] = true);
|
|
614
|
+
.forEach(key => (options[key] = true));
|
|
456
615
|
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
457
616
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
458
617
|
}
|
|
@@ -461,11 +620,17 @@ export class SourceFile {
|
|
|
461
620
|
}
|
|
462
621
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
463
622
|
if (prop.fieldNames?.length <= 1) {
|
|
464
|
-
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
623
|
+
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
624
|
+
prop.defaultRaw !== 'null' &&
|
|
625
|
+
prop.defaultRaw !== '' &&
|
|
465
626
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
466
627
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
467
628
|
}
|
|
468
|
-
else if (!(typeof prop.default === 'undefined' || prop.default === null) &&
|
|
629
|
+
else if (!(typeof prop.default === 'undefined' || prop.default === null) &&
|
|
630
|
+
(prop.ref ||
|
|
631
|
+
(!prop.enum &&
|
|
632
|
+
(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR) &&
|
|
633
|
+
(prop.type === 'unknown' || typeof this.breakdownOfIType(prop) !== 'undefined')))) {
|
|
469
634
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
470
635
|
}
|
|
471
636
|
}
|
|
@@ -480,17 +645,18 @@ export class SourceFile {
|
|
|
480
645
|
options.ignoreSchemaChanges.push(...prop.ignoreSchemaChanges.map(v => this.quote(v)));
|
|
481
646
|
}
|
|
482
647
|
}
|
|
483
|
-
propTypeBreakdowns = new WeakMap();
|
|
648
|
+
#propTypeBreakdowns = new WeakMap();
|
|
484
649
|
breakdownOfIType(prop) {
|
|
485
|
-
if (this
|
|
486
|
-
return this
|
|
650
|
+
if (this.#propTypeBreakdowns.has(prop)) {
|
|
651
|
+
return this.#propTypeBreakdowns.get(prop);
|
|
487
652
|
}
|
|
488
653
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
489
|
-
const mappedRawType =
|
|
490
|
-
|
|
491
|
-
|
|
654
|
+
const mappedRawType = prop.customTypes?.[0] ??
|
|
655
|
+
(prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType
|
|
656
|
+
? this.platform.getMappedType(prop.columnTypes[0])
|
|
657
|
+
: mappedDeclaredType);
|
|
492
658
|
const rawType = mappedRawType.runtimeType;
|
|
493
|
-
const mappedSerializedType =
|
|
659
|
+
const mappedSerializedType = prop.customType ?? mappedRawType;
|
|
494
660
|
const serializedType = mappedSerializedType.runtimeType;
|
|
495
661
|
// Add non-lib imports where needed.
|
|
496
662
|
for (const typeSpec of [prop.runtimeType, rawType, serializedType]) {
|
|
@@ -504,10 +670,12 @@ export class SourceFile {
|
|
|
504
670
|
mappedRawType.prop?.nullable ?? prop.nullable ?? false,
|
|
505
671
|
mappedSerializedType.prop?.nullable ?? prop.nullable ?? false,
|
|
506
672
|
];
|
|
507
|
-
const hasMixedNullability =
|
|
673
|
+
const hasMixedNullability = new Set(nullables).size > 1;
|
|
508
674
|
if (prop.runtimeType !== rawType || rawType !== serializedType || hasMixedNullability) {
|
|
509
675
|
const nullType = this.options.forceUndefined ? ' | undefined' : ' | null';
|
|
510
|
-
if (rawType !== serializedType ||
|
|
676
|
+
if (rawType !== serializedType ||
|
|
677
|
+
nullables[1] !== nullables[2] ||
|
|
678
|
+
(prop.hidden && nullables[0] !== nullables[1])) {
|
|
511
679
|
const r = [prop.runtimeType, rawType, serializedType];
|
|
512
680
|
if (hasMixedNullability || prop.hidden) {
|
|
513
681
|
for (let i = r.length - 1; i >= 0; --i) {
|
|
@@ -519,7 +687,7 @@ export class SourceFile {
|
|
|
519
687
|
r[2] = `(${r[2]}) & ${this.referenceCoreImport('Hidden')}`;
|
|
520
688
|
}
|
|
521
689
|
}
|
|
522
|
-
this
|
|
690
|
+
this.#propTypeBreakdowns.set(prop, r);
|
|
523
691
|
return r;
|
|
524
692
|
}
|
|
525
693
|
const r = [prop.runtimeType, rawType];
|
|
@@ -530,19 +698,30 @@ export class SourceFile {
|
|
|
530
698
|
}
|
|
531
699
|
}
|
|
532
700
|
}
|
|
533
|
-
this
|
|
701
|
+
this.#propTypeBreakdowns.set(prop, r);
|
|
534
702
|
return r;
|
|
535
703
|
}
|
|
536
704
|
const r = undefined;
|
|
537
|
-
this
|
|
705
|
+
this.#propTypeBreakdowns.set(prop, r);
|
|
538
706
|
return r;
|
|
539
707
|
}
|
|
540
|
-
getScalarPropertyDecoratorOptions(options, prop) {
|
|
708
|
+
getScalarPropertyDecoratorOptions(options, prop, quote = true) {
|
|
541
709
|
if (prop.fieldNames[0] !== this.namingStrategy.propertyToColumnName(prop.name)) {
|
|
542
710
|
options.fieldName = this.quote(prop.fieldNames[0]);
|
|
543
711
|
}
|
|
544
712
|
if (prop.enum) {
|
|
545
|
-
options.
|
|
713
|
+
if (this.options.enumMode === 'union-type') {
|
|
714
|
+
options.items = `[${prop.items.map(item => this.quote(item)).join(', ')}]`;
|
|
715
|
+
}
|
|
716
|
+
else if (prop.nativeEnumName) {
|
|
717
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema);
|
|
718
|
+
options.items = `() => ${enumClassName}`;
|
|
719
|
+
options.nativeEnumName = this.quote(prop.nativeEnumName);
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
723
|
+
options.items = `() => ${enumClassName}`;
|
|
724
|
+
}
|
|
546
725
|
}
|
|
547
726
|
// For enum properties, we don't need a column type
|
|
548
727
|
// or the property length or other information in the decorator.
|
|
@@ -561,30 +740,38 @@ export class SourceFile {
|
|
|
561
740
|
options.type = prop.type;
|
|
562
741
|
}
|
|
563
742
|
else {
|
|
564
|
-
if (this.options.scalarTypeInDecorator // always output type if forced by the generator options
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
743
|
+
if (this.options.scalarTypeInDecorator || // always output type if forced by the generator options
|
|
744
|
+
(prop.nullable && !this.options.forceUndefined) || // also when there is the "| null" type modifier (because reflect-metadata can't extract the base)
|
|
745
|
+
prop.hidden || // also when there is the "& Hidden" type modifier (because reflect-metadata can't extract the base)
|
|
746
|
+
new Set([
|
|
747
|
+
mappedRuntimeType.name,
|
|
748
|
+
mappedColumnType.name,
|
|
749
|
+
mappedDeclaredType.name,
|
|
750
|
+
this.platform.getMappedType(prop.runtimeType === 'Date' ? 'datetime' : prop.runtimeType).name,
|
|
751
|
+
]).size > 1 || // also, if there's any ambiguity in the type
|
|
752
|
+
(() => {
|
|
753
|
+
const hasUsableNullDefault = prop.nullable && !this.options.forceUndefined && prop.default === null;
|
|
570
754
|
const useDefault = hasUsableNullDefault || !(typeof prop.default === 'undefined' || prop.default === null);
|
|
571
|
-
return (
|
|
755
|
+
return (useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable);
|
|
572
756
|
})() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
|
|
573
757
|
) {
|
|
574
|
-
options.type = this.quote(prop.type);
|
|
758
|
+
options.type = quote ? this.quote(prop.type) : prop.type;
|
|
575
759
|
}
|
|
576
760
|
}
|
|
577
761
|
const columnTypeFromMappedRuntimeType = mappedRuntimeType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
578
762
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
579
763
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
580
764
|
const needsExplicitColumnType = () => {
|
|
581
|
-
if (isTypeStringMissingFromMap ||
|
|
765
|
+
if (isTypeStringMissingFromMap ||
|
|
766
|
+
[mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
582
767
|
return true;
|
|
583
768
|
}
|
|
584
|
-
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
769
|
+
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
770
|
+
this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
585
771
|
return prop.columnTypes[0] !== columnTypeFromMappedColumnType;
|
|
586
772
|
}
|
|
587
|
-
return columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
773
|
+
return (columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
774
|
+
columnTypeFromMappedDeclaredType !== columnTypeFromMappedColumnType);
|
|
588
775
|
};
|
|
589
776
|
if (needsExplicitColumnType()) {
|
|
590
777
|
options.columnType = this.quote(prop.columnTypes[0]);
|
|
@@ -594,11 +781,13 @@ export class SourceFile {
|
|
|
594
781
|
options[key] = prop[key];
|
|
595
782
|
}
|
|
596
783
|
};
|
|
597
|
-
if (!options.columnType &&
|
|
784
|
+
if (!options.columnType &&
|
|
785
|
+
(typeof mappedColumnType.getDefaultLength === 'undefined' ||
|
|
786
|
+
mappedColumnType.getDefaultLength(this.platform) !== prop.length)) {
|
|
598
787
|
assign('length');
|
|
599
788
|
}
|
|
600
789
|
// those are already included in the `columnType` in most cases, and when that option is present, they would be ignored anyway
|
|
601
|
-
/* v8 ignore next
|
|
790
|
+
/* v8 ignore next */
|
|
602
791
|
if (mappedColumnType instanceof DecimalType && !options.columnType) {
|
|
603
792
|
assign('precision');
|
|
604
793
|
assign('scale');
|
|
@@ -609,14 +798,16 @@ export class SourceFile {
|
|
|
609
798
|
assign('unsigned');
|
|
610
799
|
}
|
|
611
800
|
if (prop.autoincrement) {
|
|
612
|
-
if (!prop.primary ||
|
|
801
|
+
if (!prop.primary ||
|
|
802
|
+
!this.platform.isNumericColumn(mappedColumnType) ||
|
|
803
|
+
this.meta.getPrimaryProps().length !== 1) {
|
|
613
804
|
options.autoincrement = true;
|
|
614
805
|
}
|
|
615
806
|
}
|
|
616
|
-
else
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
807
|
+
else if (prop.primary &&
|
|
808
|
+
this.platform.isNumericColumn(mappedColumnType) &&
|
|
809
|
+
this.meta.getPrimaryProps().length === 1) {
|
|
810
|
+
options.autoincrement = false;
|
|
620
811
|
}
|
|
621
812
|
if (prop.generated) {
|
|
622
813
|
options.generated = typeof prop.generated === 'string' ? this.quote(prop.generated) : `${prop.generated}`;
|
|
@@ -632,24 +823,25 @@ export class SourceFile {
|
|
|
632
823
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
633
824
|
return;
|
|
634
825
|
}
|
|
635
|
-
if (prop.pivotTable !==
|
|
826
|
+
if (prop.pivotTable !==
|
|
827
|
+
this.namingStrategy.joinTableName(this.meta.collection, prop.type, prop.name, this.meta.tableName)) {
|
|
636
828
|
options.pivotTable = this.quote(prop.pivotTable);
|
|
637
829
|
}
|
|
638
|
-
if (prop.pivotEntity && prop.pivotEntity !== prop.pivotTable) {
|
|
639
|
-
this.entityImports.add(prop.pivotEntity);
|
|
640
|
-
options.pivotEntity = `() => ${prop.pivotEntity}`;
|
|
830
|
+
if (prop.pivotEntity && Utils.className(prop.pivotEntity) !== prop.pivotTable) {
|
|
831
|
+
this.entityImports.add(Utils.className(prop.pivotEntity));
|
|
832
|
+
options.pivotEntity = `() => ${Utils.className(prop.pivotEntity)}`;
|
|
641
833
|
}
|
|
642
834
|
if (prop.joinColumns.length === 1) {
|
|
643
835
|
options.joinColumn = this.quote(prop.joinColumns[0]);
|
|
644
836
|
}
|
|
645
837
|
else {
|
|
646
|
-
options.joinColumns = `[${prop.joinColumns.map(this.quote).join(', ')}]`;
|
|
838
|
+
options.joinColumns = `[${prop.joinColumns.map(c => this.quote(c)).join(', ')}]`;
|
|
647
839
|
}
|
|
648
840
|
if (prop.inverseJoinColumns.length === 1) {
|
|
649
841
|
options.inverseJoinColumn = this.quote(prop.inverseJoinColumns[0]);
|
|
650
842
|
}
|
|
651
843
|
else {
|
|
652
|
-
options.inverseJoinColumns = `[${prop.inverseJoinColumns.map(this.quote).join(', ')}]`;
|
|
844
|
+
options.inverseJoinColumns = `[${prop.inverseJoinColumns.map(c => this.quote(c)).join(', ')}]`;
|
|
653
845
|
}
|
|
654
846
|
if (prop.fixedOrder) {
|
|
655
847
|
options.fixedOrder = true;
|
|
@@ -672,7 +864,7 @@ export class SourceFile {
|
|
|
672
864
|
if (prop.array) {
|
|
673
865
|
options.array = true;
|
|
674
866
|
}
|
|
675
|
-
if (prop.object) {
|
|
867
|
+
if (prop.object && !prop.array) {
|
|
676
868
|
options.object = true;
|
|
677
869
|
}
|
|
678
870
|
if (prop.prefix === false || typeof prop.prefix === 'string') {
|
|
@@ -698,17 +890,18 @@ export class SourceFile {
|
|
|
698
890
|
}
|
|
699
891
|
}
|
|
700
892
|
else {
|
|
701
|
-
if (prop.fieldNames.length > 1 &&
|
|
893
|
+
if (prop.fieldNames.length > 1 &&
|
|
894
|
+
prop.fieldNames.some((fieldName, i) => fieldName !== this.namingStrategy.joinKeyColumnName(prop.name, prop.referencedColumnNames[i]))) {
|
|
702
895
|
options.fieldNames = prop.fieldNames.map(fieldName => this.quote(fieldName));
|
|
703
896
|
}
|
|
704
897
|
}
|
|
705
898
|
if (prop.ownColumns && prop.ownColumns.length !== prop.fieldNames.length) {
|
|
706
899
|
options.referencedColumnNames = prop.referencedColumnNames.map(fieldName => this.quote(fieldName));
|
|
707
900
|
}
|
|
708
|
-
if (
|
|
901
|
+
if (prop.updateRule) {
|
|
709
902
|
options.updateRule = this.quote(prop.updateRule);
|
|
710
903
|
}
|
|
711
|
-
if (
|
|
904
|
+
if (prop.deleteRule) {
|
|
712
905
|
options.deleteRule = this.quote(prop.deleteRule);
|
|
713
906
|
}
|
|
714
907
|
if (prop.primary) {
|
|
@@ -751,8 +944,10 @@ export class SourceFile {
|
|
|
751
944
|
}
|
|
752
945
|
referenceCoreImport(identifier) {
|
|
753
946
|
this.coreImports.add(identifier);
|
|
754
|
-
return this.options.coreImportsPrefix
|
|
755
|
-
|
|
756
|
-
|
|
947
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
948
|
+
}
|
|
949
|
+
referenceDecoratorImport(identifier) {
|
|
950
|
+
this.decoratorImports.add(identifier);
|
|
951
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
757
952
|
}
|
|
758
953
|
}
|