@mikro-orm/entity-generator 7.0.0-dev.31 → 7.0.0-dev.310
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 +2 -1
- package/EntityGenerator.js +132 -47
- package/EntitySchemaSourceFile.d.ts +3 -2
- package/EntitySchemaSourceFile.js +53 -38
- package/NativeEnumSourceFile.d.ts +16 -0
- package/NativeEnumSourceFile.js +47 -0
- package/README.md +5 -3
- package/SourceFile.d.ts +8 -1
- package/SourceFile.js +295 -105
- package/package.json +32 -32
- package/tsconfig.build.tsbuildinfo +1 -0
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);
|
|
@@ -344,21 +495,26 @@ export class SourceFile {
|
|
|
344
495
|
options.abstract = true;
|
|
345
496
|
}
|
|
346
497
|
if (this.meta.discriminatorValue) {
|
|
347
|
-
options.discriminatorValue =
|
|
498
|
+
options.discriminatorValue =
|
|
499
|
+
typeof this.meta.discriminatorValue === 'string'
|
|
500
|
+
? this.quote(this.meta.discriminatorValue)
|
|
501
|
+
: this.meta.discriminatorValue;
|
|
348
502
|
}
|
|
349
503
|
if (this.meta.discriminatorColumn) {
|
|
350
504
|
options.discriminatorColumn = this.quote(this.meta.discriminatorColumn);
|
|
351
505
|
}
|
|
352
506
|
if (this.meta.discriminatorMap) {
|
|
353
|
-
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap)
|
|
354
|
-
|
|
507
|
+
options.discriminatorMap = Object.fromEntries(Object.entries(this.meta.discriminatorMap).map(([discriminatorValue, cls]) => [
|
|
508
|
+
discriminatorValue,
|
|
509
|
+
this.quote(Utils.className(cls)),
|
|
510
|
+
]));
|
|
355
511
|
}
|
|
356
512
|
return options;
|
|
357
513
|
}
|
|
358
514
|
getPropertyDecorator(prop, padLeft) {
|
|
359
515
|
const padding = ' '.repeat(padLeft);
|
|
360
516
|
const options = {};
|
|
361
|
-
let decorator = `@${this.
|
|
517
|
+
let decorator = `@${this.referenceDecoratorImport(this.getDecoratorType(prop))}`;
|
|
362
518
|
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
363
519
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
364
520
|
}
|
|
@@ -379,10 +535,10 @@ export class SourceFile {
|
|
|
379
535
|
decorator = [...indexes.sort(), decorator].map(d => padding + d).join('\n');
|
|
380
536
|
const decoratorArgs = [];
|
|
381
537
|
if (prop.formula) {
|
|
382
|
-
decoratorArgs.push(
|
|
538
|
+
decoratorArgs.push(prop.formula.toString());
|
|
383
539
|
}
|
|
384
540
|
if (Utils.hasObjectKeys(options)) {
|
|
385
|
-
decoratorArgs.push(
|
|
541
|
+
decoratorArgs.push(this.serializeObject(options));
|
|
386
542
|
}
|
|
387
543
|
return `${decorator}(${decoratorArgs.join(', ')})\n`;
|
|
388
544
|
}
|
|
@@ -393,7 +549,7 @@ export class SourceFile {
|
|
|
393
549
|
return;
|
|
394
550
|
}
|
|
395
551
|
const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
|
|
396
|
-
options[type] =
|
|
552
|
+
options[type] = propType === true || defaultName === propType ? 'true' : this.quote(propType);
|
|
397
553
|
const expected = {
|
|
398
554
|
index: this.platform.indexForeignKeys(),
|
|
399
555
|
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
@@ -408,26 +564,26 @@ export class SourceFile {
|
|
|
408
564
|
let propIndexIsNonTrivialIndex = false;
|
|
409
565
|
const nonTrivialIndexes = this.meta.indexes.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
410
566
|
for (const i of nonTrivialIndexes) {
|
|
411
|
-
ret.push(`@${this.
|
|
567
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${this.serializeObject(this.getIndexOptions(i, false))})`);
|
|
412
568
|
if (prop.index === i.name) {
|
|
413
569
|
propIndexIsNonTrivialIndex = true;
|
|
414
570
|
delete options.index;
|
|
415
571
|
}
|
|
416
572
|
}
|
|
417
573
|
if (prop.index && !options.index && !propIndexIsNonTrivialIndex) {
|
|
418
|
-
ret.push(`@${this.
|
|
574
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${typeof prop.index === 'string' ? `{ name: ${this.quote(prop.index)} }` : ''})`);
|
|
419
575
|
}
|
|
420
576
|
let propIndexIsNonTrivialUnique = false;
|
|
421
577
|
const nonTrivialUnique = this.meta.uniques.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
422
578
|
for (const i of nonTrivialUnique) {
|
|
423
|
-
ret.push(`@${this.
|
|
579
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${this.serializeObject(this.getUniqueOptions(i, false))})`);
|
|
424
580
|
if (prop.unique === i.name) {
|
|
425
581
|
propIndexIsNonTrivialUnique = true;
|
|
426
582
|
delete options.unique;
|
|
427
583
|
}
|
|
428
584
|
}
|
|
429
585
|
if (prop.unique && !options.unique && !propIndexIsNonTrivialUnique) {
|
|
430
|
-
ret.push(`@${this.
|
|
586
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${typeof prop.unique === 'string' ? `{ name: ${this.quote(prop.unique)} }` : ''})`);
|
|
431
587
|
}
|
|
432
588
|
return ret;
|
|
433
589
|
}
|
|
@@ -438,12 +594,10 @@ export class SourceFile {
|
|
|
438
594
|
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
439
595
|
options.primary = true;
|
|
440
596
|
}
|
|
441
|
-
['persist', 'hydrate'
|
|
442
|
-
.filter(key => prop[key] === false)
|
|
443
|
-
.forEach(key => options[key] = false);
|
|
597
|
+
['persist', 'hydrate'].filter(key => prop[key] === false).forEach(key => (options[key] = false));
|
|
444
598
|
['onCreate', 'onUpdate', 'serializer']
|
|
445
599
|
.filter(key => typeof prop[key] === 'function')
|
|
446
|
-
.forEach(key => options[key] = `${prop[key]}`);
|
|
600
|
+
.forEach(key => (options[key] = `${prop[key]}`));
|
|
447
601
|
if (typeof prop.serializedName === 'string') {
|
|
448
602
|
options.serializedName = this.quote(prop.serializedName);
|
|
449
603
|
}
|
|
@@ -452,7 +606,7 @@ export class SourceFile {
|
|
|
452
606
|
}
|
|
453
607
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
454
608
|
.filter(key => prop[key])
|
|
455
|
-
.forEach(key => options[key] = true);
|
|
609
|
+
.forEach(key => (options[key] = true));
|
|
456
610
|
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
457
611
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
458
612
|
}
|
|
@@ -461,11 +615,17 @@ export class SourceFile {
|
|
|
461
615
|
}
|
|
462
616
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
463
617
|
if (prop.fieldNames?.length <= 1) {
|
|
464
|
-
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
618
|
+
if (typeof prop.defaultRaw !== 'undefined' &&
|
|
619
|
+
prop.defaultRaw !== 'null' &&
|
|
620
|
+
prop.defaultRaw !== '' &&
|
|
465
621
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
466
622
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
467
623
|
}
|
|
468
|
-
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')))) {
|
|
469
629
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
470
630
|
}
|
|
471
631
|
}
|
|
@@ -486,11 +646,12 @@ export class SourceFile {
|
|
|
486
646
|
return this.propTypeBreakdowns.get(prop);
|
|
487
647
|
}
|
|
488
648
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
489
|
-
const mappedRawType =
|
|
490
|
-
|
|
491
|
-
|
|
649
|
+
const mappedRawType = prop.customTypes?.[0] ??
|
|
650
|
+
(prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType
|
|
651
|
+
? this.platform.getMappedType(prop.columnTypes[0])
|
|
652
|
+
: mappedDeclaredType);
|
|
492
653
|
const rawType = mappedRawType.runtimeType;
|
|
493
|
-
const mappedSerializedType =
|
|
654
|
+
const mappedSerializedType = prop.customType ?? mappedRawType;
|
|
494
655
|
const serializedType = mappedSerializedType.runtimeType;
|
|
495
656
|
// Add non-lib imports where needed.
|
|
496
657
|
for (const typeSpec of [prop.runtimeType, rawType, serializedType]) {
|
|
@@ -504,10 +665,12 @@ export class SourceFile {
|
|
|
504
665
|
mappedRawType.prop?.nullable ?? prop.nullable ?? false,
|
|
505
666
|
mappedSerializedType.prop?.nullable ?? prop.nullable ?? false,
|
|
506
667
|
];
|
|
507
|
-
const hasMixedNullability =
|
|
668
|
+
const hasMixedNullability = new Set(nullables).size > 1;
|
|
508
669
|
if (prop.runtimeType !== rawType || rawType !== serializedType || hasMixedNullability) {
|
|
509
670
|
const nullType = this.options.forceUndefined ? ' | undefined' : ' | null';
|
|
510
|
-
if (rawType !== serializedType ||
|
|
671
|
+
if (rawType !== serializedType ||
|
|
672
|
+
nullables[1] !== nullables[2] ||
|
|
673
|
+
(prop.hidden && nullables[0] !== nullables[1])) {
|
|
511
674
|
const r = [prop.runtimeType, rawType, serializedType];
|
|
512
675
|
if (hasMixedNullability || prop.hidden) {
|
|
513
676
|
for (let i = r.length - 1; i >= 0; --i) {
|
|
@@ -537,12 +700,23 @@ export class SourceFile {
|
|
|
537
700
|
this.propTypeBreakdowns.set(prop, r);
|
|
538
701
|
return r;
|
|
539
702
|
}
|
|
540
|
-
getScalarPropertyDecoratorOptions(options, prop) {
|
|
703
|
+
getScalarPropertyDecoratorOptions(options, prop, quote = true) {
|
|
541
704
|
if (prop.fieldNames[0] !== this.namingStrategy.propertyToColumnName(prop.name)) {
|
|
542
705
|
options.fieldName = this.quote(prop.fieldNames[0]);
|
|
543
706
|
}
|
|
544
707
|
if (prop.enum) {
|
|
545
|
-
options.
|
|
708
|
+
if (this.options.enumMode === 'union-type') {
|
|
709
|
+
options.items = `[${prop.items.map(item => this.quote(item)).join(', ')}]`;
|
|
710
|
+
}
|
|
711
|
+
else if (prop.nativeEnumName) {
|
|
712
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema);
|
|
713
|
+
options.items = `() => ${enumClassName}`;
|
|
714
|
+
options.nativeEnumName = this.quote(prop.nativeEnumName);
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
718
|
+
options.items = `() => ${enumClassName}`;
|
|
719
|
+
}
|
|
546
720
|
}
|
|
547
721
|
// For enum properties, we don't need a column type
|
|
548
722
|
// or the property length or other information in the decorator.
|
|
@@ -561,30 +735,38 @@ export class SourceFile {
|
|
|
561
735
|
options.type = prop.type;
|
|
562
736
|
}
|
|
563
737
|
else {
|
|
564
|
-
if (this.options.scalarTypeInDecorator // always output type if forced by the generator options
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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;
|
|
570
749
|
const useDefault = hasUsableNullDefault || !(typeof prop.default === 'undefined' || prop.default === null);
|
|
571
|
-
return (
|
|
750
|
+
return (useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable);
|
|
572
751
|
})() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
|
|
573
752
|
) {
|
|
574
|
-
options.type = this.quote(prop.type);
|
|
753
|
+
options.type = quote ? this.quote(prop.type) : prop.type;
|
|
575
754
|
}
|
|
576
755
|
}
|
|
577
756
|
const columnTypeFromMappedRuntimeType = mappedRuntimeType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
578
757
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
579
758
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
580
759
|
const needsExplicitColumnType = () => {
|
|
581
|
-
if (isTypeStringMissingFromMap ||
|
|
760
|
+
if (isTypeStringMissingFromMap ||
|
|
761
|
+
[mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
582
762
|
return true;
|
|
583
763
|
}
|
|
584
|
-
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
764
|
+
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !==
|
|
765
|
+
this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
585
766
|
return prop.columnTypes[0] !== columnTypeFromMappedColumnType;
|
|
586
767
|
}
|
|
587
|
-
return columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
768
|
+
return (columnTypeFromMappedRuntimeType !== columnTypeFromMappedColumnType ||
|
|
769
|
+
columnTypeFromMappedDeclaredType !== columnTypeFromMappedColumnType);
|
|
588
770
|
};
|
|
589
771
|
if (needsExplicitColumnType()) {
|
|
590
772
|
options.columnType = this.quote(prop.columnTypes[0]);
|
|
@@ -594,11 +776,13 @@ export class SourceFile {
|
|
|
594
776
|
options[key] = prop[key];
|
|
595
777
|
}
|
|
596
778
|
};
|
|
597
|
-
if (!options.columnType &&
|
|
779
|
+
if (!options.columnType &&
|
|
780
|
+
(typeof mappedColumnType.getDefaultLength === 'undefined' ||
|
|
781
|
+
mappedColumnType.getDefaultLength(this.platform) !== prop.length)) {
|
|
598
782
|
assign('length');
|
|
599
783
|
}
|
|
600
784
|
// 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
|
|
785
|
+
/* v8 ignore next */
|
|
602
786
|
if (mappedColumnType instanceof DecimalType && !options.columnType) {
|
|
603
787
|
assign('precision');
|
|
604
788
|
assign('scale');
|
|
@@ -609,14 +793,16 @@ export class SourceFile {
|
|
|
609
793
|
assign('unsigned');
|
|
610
794
|
}
|
|
611
795
|
if (prop.autoincrement) {
|
|
612
|
-
if (!prop.primary ||
|
|
796
|
+
if (!prop.primary ||
|
|
797
|
+
!this.platform.isNumericColumn(mappedColumnType) ||
|
|
798
|
+
this.meta.getPrimaryProps().length !== 1) {
|
|
613
799
|
options.autoincrement = true;
|
|
614
800
|
}
|
|
615
801
|
}
|
|
616
|
-
else
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
802
|
+
else if (prop.primary &&
|
|
803
|
+
this.platform.isNumericColumn(mappedColumnType) &&
|
|
804
|
+
this.meta.getPrimaryProps().length === 1) {
|
|
805
|
+
options.autoincrement = false;
|
|
620
806
|
}
|
|
621
807
|
if (prop.generated) {
|
|
622
808
|
options.generated = typeof prop.generated === 'string' ? this.quote(prop.generated) : `${prop.generated}`;
|
|
@@ -632,24 +818,25 @@ export class SourceFile {
|
|
|
632
818
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
633
819
|
return;
|
|
634
820
|
}
|
|
635
|
-
if (prop.pivotTable !==
|
|
821
|
+
if (prop.pivotTable !==
|
|
822
|
+
this.namingStrategy.joinTableName(this.meta.collection, prop.type, prop.name, this.meta.tableName)) {
|
|
636
823
|
options.pivotTable = this.quote(prop.pivotTable);
|
|
637
824
|
}
|
|
638
|
-
if (prop.pivotEntity && prop.pivotEntity !== prop.pivotTable) {
|
|
639
|
-
this.entityImports.add(prop.pivotEntity);
|
|
640
|
-
options.pivotEntity = `() => ${prop.pivotEntity}`;
|
|
825
|
+
if (prop.pivotEntity && Utils.className(prop.pivotEntity) !== prop.pivotTable) {
|
|
826
|
+
this.entityImports.add(Utils.className(prop.pivotEntity));
|
|
827
|
+
options.pivotEntity = `() => ${Utils.className(prop.pivotEntity)}`;
|
|
641
828
|
}
|
|
642
829
|
if (prop.joinColumns.length === 1) {
|
|
643
830
|
options.joinColumn = this.quote(prop.joinColumns[0]);
|
|
644
831
|
}
|
|
645
832
|
else {
|
|
646
|
-
options.joinColumns = `[${prop.joinColumns.map(this.quote).join(', ')}]`;
|
|
833
|
+
options.joinColumns = `[${prop.joinColumns.map(c => this.quote(c)).join(', ')}]`;
|
|
647
834
|
}
|
|
648
835
|
if (prop.inverseJoinColumns.length === 1) {
|
|
649
836
|
options.inverseJoinColumn = this.quote(prop.inverseJoinColumns[0]);
|
|
650
837
|
}
|
|
651
838
|
else {
|
|
652
|
-
options.inverseJoinColumns = `[${prop.inverseJoinColumns.map(this.quote).join(', ')}]`;
|
|
839
|
+
options.inverseJoinColumns = `[${prop.inverseJoinColumns.map(c => this.quote(c)).join(', ')}]`;
|
|
653
840
|
}
|
|
654
841
|
if (prop.fixedOrder) {
|
|
655
842
|
options.fixedOrder = true;
|
|
@@ -672,7 +859,7 @@ export class SourceFile {
|
|
|
672
859
|
if (prop.array) {
|
|
673
860
|
options.array = true;
|
|
674
861
|
}
|
|
675
|
-
if (prop.object) {
|
|
862
|
+
if (prop.object && !prop.array) {
|
|
676
863
|
options.object = true;
|
|
677
864
|
}
|
|
678
865
|
if (prop.prefix === false || typeof prop.prefix === 'string') {
|
|
@@ -698,17 +885,18 @@ export class SourceFile {
|
|
|
698
885
|
}
|
|
699
886
|
}
|
|
700
887
|
else {
|
|
701
|
-
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]))) {
|
|
702
890
|
options.fieldNames = prop.fieldNames.map(fieldName => this.quote(fieldName));
|
|
703
891
|
}
|
|
704
892
|
}
|
|
705
893
|
if (prop.ownColumns && prop.ownColumns.length !== prop.fieldNames.length) {
|
|
706
894
|
options.referencedColumnNames = prop.referencedColumnNames.map(fieldName => this.quote(fieldName));
|
|
707
895
|
}
|
|
708
|
-
if (
|
|
896
|
+
if (prop.updateRule) {
|
|
709
897
|
options.updateRule = this.quote(prop.updateRule);
|
|
710
898
|
}
|
|
711
|
-
if (
|
|
899
|
+
if (prop.deleteRule) {
|
|
712
900
|
options.deleteRule = this.quote(prop.deleteRule);
|
|
713
901
|
}
|
|
714
902
|
if (prop.primary) {
|
|
@@ -751,8 +939,10 @@ export class SourceFile {
|
|
|
751
939
|
}
|
|
752
940
|
referenceCoreImport(identifier) {
|
|
753
941
|
this.coreImports.add(identifier);
|
|
754
|
-
return this.options.coreImportsPrefix
|
|
755
|
-
|
|
756
|
-
|
|
942
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
943
|
+
}
|
|
944
|
+
referenceDecoratorImport(identifier) {
|
|
945
|
+
this.decoratorImports.add(identifier);
|
|
946
|
+
return this.options.coreImportsPrefix ? `${this.options.coreImportsPrefix}${identifier}` : identifier;
|
|
757
947
|
}
|
|
758
948
|
}
|