@mikro-orm/entity-generator 7.0.0-dev.1 → 7.0.0-dev.100
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/CoreImportsHelper.js +1 -4
- package/DefineEntitySourceFile.d.ts +5 -0
- package/DefineEntitySourceFile.js +115 -0
- package/EntityGenerator.d.ts +1 -1
- package/EntityGenerator.js +57 -46
- package/EntitySchemaSourceFile.d.ts +4 -3
- package/EntitySchemaSourceFile.js +58 -51
- package/NativeEnumSourceFile.d.ts +16 -0
- package/NativeEnumSourceFile.js +47 -0
- package/README.md +3 -2
- package/SourceFile.d.ts +7 -4
- package/SourceFile.js +178 -77
- package/index.d.ts +1 -1
- package/index.js +1 -17
- package/package.json +8 -17
- package/index.mjs +0 -4
package/SourceFile.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const core_1 = require("@mikro-orm/core");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
|
-
const CoreImportsHelper_1 = require("./CoreImportsHelper");
|
|
1
|
+
import { Cascade, Config, DecimalType, ReferenceKind, SCALAR_TYPES, UnknownType, Utils, inspect, } from '@mikro-orm/core';
|
|
2
|
+
import { parse, relative } from 'node:path';
|
|
3
|
+
import { POSSIBLE_TYPE_IMPORTS } from './CoreImportsHelper.js';
|
|
7
4
|
/**
|
|
8
5
|
* @see https://github.com/tc39/proposal-regexp-unicode-property-escapes#other-examples
|
|
9
6
|
*/
|
|
10
|
-
|
|
11
|
-
const primitivesAndLibs = [...
|
|
12
|
-
class SourceFile {
|
|
7
|
+
export const identifierRegex = /^(?:[$_\p{ID_Start}])(?:[$\u200C\u200D\p{ID_Continue}])*$/u;
|
|
8
|
+
const primitivesAndLibs = [...SCALAR_TYPES, 'unknown', 'object', 'any'];
|
|
9
|
+
export class SourceFile {
|
|
13
10
|
meta;
|
|
14
11
|
namingStrategy;
|
|
15
12
|
platform;
|
|
16
13
|
options;
|
|
17
14
|
coreImports = new Set();
|
|
15
|
+
decoratorImports = new Set();
|
|
18
16
|
entityImports = new Set();
|
|
17
|
+
enumImports = new Map();
|
|
19
18
|
constructor(meta, namingStrategy, platform, options) {
|
|
20
19
|
this.meta = meta;
|
|
21
20
|
this.namingStrategy = namingStrategy;
|
|
@@ -27,24 +26,24 @@ class SourceFile {
|
|
|
27
26
|
if (this.meta.embeddable || this.meta.collection) {
|
|
28
27
|
if (this.meta.embeddable) {
|
|
29
28
|
const options = this.getEmbeddableDeclOptions();
|
|
30
|
-
ret += `@${this.
|
|
29
|
+
ret += `@${this.referenceDecoratorImport('Embeddable')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
31
30
|
}
|
|
32
31
|
else {
|
|
33
32
|
const options = this.getEntityDeclOptions();
|
|
34
|
-
ret += `@${this.
|
|
33
|
+
ret += `@${this.referenceDecoratorImport('Entity')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
for (const index of this.meta.indexes) {
|
|
38
37
|
if (index.properties?.length === 1 && typeof this.meta.properties[index.properties[0]] !== 'undefined') {
|
|
39
38
|
continue;
|
|
40
39
|
}
|
|
41
|
-
ret += `@${this.
|
|
40
|
+
ret += `@${this.referenceDecoratorImport('Index')}(${this.serializeObject(this.getIndexOptions(index))})\n`;
|
|
42
41
|
}
|
|
43
42
|
for (const index of this.meta.uniques) {
|
|
44
43
|
if (index.properties?.length === 1 && typeof this.meta.properties[index.properties[0]] !== 'undefined') {
|
|
45
44
|
continue;
|
|
46
45
|
}
|
|
47
|
-
ret += `@${this.
|
|
46
|
+
ret += `@${this.referenceDecoratorImport('Unique')}(${this.serializeObject(this.getUniqueOptions(index))})\n`;
|
|
48
47
|
}
|
|
49
48
|
let classHead = '';
|
|
50
49
|
if (this.meta.className === this.options.customBaseEntityName) {
|
|
@@ -67,7 +66,10 @@ class SourceFile {
|
|
|
67
66
|
classBody += definition;
|
|
68
67
|
classBody += '\n';
|
|
69
68
|
if (prop.enum) {
|
|
70
|
-
|
|
69
|
+
const def = this.getEnumClassDefinition(prop, 2);
|
|
70
|
+
if (def.length) {
|
|
71
|
+
enumDefinitions.push(def);
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
74
|
if (prop.eager) {
|
|
73
75
|
eagerProperties.push(prop);
|
|
@@ -101,11 +103,14 @@ class SourceFile {
|
|
|
101
103
|
if (typeof index.name === 'string') {
|
|
102
104
|
indexOpt.name = this.quote(index.name);
|
|
103
105
|
}
|
|
104
|
-
if (index.expression) {
|
|
106
|
+
if (typeof index.expression === 'string') {
|
|
105
107
|
indexOpt.expression = this.quote(index.expression);
|
|
106
108
|
}
|
|
109
|
+
else if (typeof index.expression === 'function') {
|
|
110
|
+
indexOpt.expression = `${index.expression}`.replace(')=>`', ') => `');
|
|
111
|
+
}
|
|
107
112
|
if (isAtEntityLevel && index.properties) {
|
|
108
|
-
indexOpt.properties =
|
|
113
|
+
indexOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
109
114
|
}
|
|
110
115
|
return indexOpt;
|
|
111
116
|
}
|
|
@@ -114,11 +119,14 @@ class SourceFile {
|
|
|
114
119
|
if (typeof index.name === 'string') {
|
|
115
120
|
uniqueOpt.name = this.quote(index.name);
|
|
116
121
|
}
|
|
117
|
-
if (index.expression) {
|
|
122
|
+
if (typeof index.expression === 'string') {
|
|
118
123
|
uniqueOpt.expression = this.quote(index.expression);
|
|
119
124
|
}
|
|
125
|
+
else if (typeof index.expression === 'function') {
|
|
126
|
+
uniqueOpt.expression = `${index.expression}`.replace(')=>`', ') => `');
|
|
127
|
+
}
|
|
120
128
|
if (isAtEntityLevel && index.properties) {
|
|
121
|
-
uniqueOpt.properties =
|
|
129
|
+
uniqueOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
122
130
|
}
|
|
123
131
|
if (index.deferMode) {
|
|
124
132
|
uniqueOpt.deferMode = `${this.referenceCoreImport('DeferMode')}.INITIALLY_${index.deferMode.toUpperCase()}`;
|
|
@@ -129,7 +137,7 @@ class SourceFile {
|
|
|
129
137
|
const imports = new Set();
|
|
130
138
|
if (this.coreImports.size > 0) {
|
|
131
139
|
imports.add(`import { ${([...this.coreImports].sort().map(t => {
|
|
132
|
-
let ret =
|
|
140
|
+
let ret = POSSIBLE_TYPE_IMPORTS.includes(t) ? `type ${t}` : t;
|
|
133
141
|
if (this.options.coreImportsPrefix) {
|
|
134
142
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
135
143
|
ret += ` as ${resolvedIdentifier}`;
|
|
@@ -137,37 +145,61 @@ class SourceFile {
|
|
|
137
145
|
return ret;
|
|
138
146
|
}).join(', '))} } from '@mikro-orm/core';`);
|
|
139
147
|
}
|
|
148
|
+
if (this.decoratorImports.size > 0) {
|
|
149
|
+
const type = this.options.decorators;
|
|
150
|
+
imports.add(`import { ${([...this.decoratorImports].sort().map(t => {
|
|
151
|
+
let ret = t;
|
|
152
|
+
if (this.options.coreImportsPrefix) {
|
|
153
|
+
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
154
|
+
ret += ` as ${resolvedIdentifier}`;
|
|
155
|
+
}
|
|
156
|
+
return ret;
|
|
157
|
+
}).join(', '))} } from '@mikro-orm/decorators/${type}';`);
|
|
158
|
+
}
|
|
140
159
|
const extension = this.options.esmImport ? '.js' : '';
|
|
141
|
-
const { dir, base } =
|
|
142
|
-
const basePath =
|
|
160
|
+
const { dir, base } = parse(`${this.options.path ?? '.'}/${this.getBaseName()}`);
|
|
161
|
+
const basePath = relative(dir, this.options.path ?? '.') || '.';
|
|
143
162
|
(this.options.extraImports?.(basePath, base) ?? []).forEach(v => this.entityImports.add(v));
|
|
144
163
|
const entityImports = [...this.entityImports].filter(e => e !== this.meta.className);
|
|
145
|
-
|
|
164
|
+
const importMap = new Map();
|
|
165
|
+
for (const entity of entityImports) {
|
|
146
166
|
const file = this.options.onImport?.(entity, basePath, extension, base) ?? {
|
|
147
167
|
path: `${basePath}/${this.options.fileName(entity)}${extension}`,
|
|
148
168
|
name: entity,
|
|
149
169
|
};
|
|
150
170
|
if (file.path === '') {
|
|
151
171
|
if (file.name === '') {
|
|
152
|
-
|
|
172
|
+
continue;
|
|
153
173
|
}
|
|
154
|
-
|
|
155
|
-
|
|
174
|
+
importMap.set(file.path, `import ${this.quote(file.name)};`);
|
|
175
|
+
continue;
|
|
156
176
|
}
|
|
157
177
|
if (file.name === '') {
|
|
158
|
-
|
|
159
|
-
|
|
178
|
+
importMap.set(file.path, `import * as ${entity} from ${this.quote(file.path)};`);
|
|
179
|
+
continue;
|
|
160
180
|
}
|
|
161
181
|
if (file.name === 'default') {
|
|
162
|
-
|
|
163
|
-
|
|
182
|
+
importMap.set(file.path, `import ${entity} from ${this.quote(file.path)};`);
|
|
183
|
+
continue;
|
|
164
184
|
}
|
|
165
185
|
if (file.name === entity) {
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
importMap.set(file.path, `import { ${entity} } from ${this.quote(file.path)};`);
|
|
187
|
+
continue;
|
|
168
188
|
}
|
|
169
|
-
|
|
170
|
-
}
|
|
189
|
+
importMap.set(file.path, `import { ${identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
|
|
190
|
+
}
|
|
191
|
+
if (this.enumImports.size) {
|
|
192
|
+
for (const [name, exports] of this.enumImports.entries()) {
|
|
193
|
+
const file = this.options.onImport?.(name, basePath, extension, base) ?? {
|
|
194
|
+
path: `${basePath}/${this.options.fileName(name)}${extension}`,
|
|
195
|
+
name,
|
|
196
|
+
};
|
|
197
|
+
importMap.set(file.path, `import { ${exports.join(', ')} } from ${this.quote(file.path)};`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const key of [...importMap.keys()].sort()) {
|
|
201
|
+
imports.add(importMap.get(key));
|
|
202
|
+
}
|
|
171
203
|
return Array.from(imports.values()).join('\n');
|
|
172
204
|
}
|
|
173
205
|
getEntityClass(classBody) {
|
|
@@ -191,20 +223,21 @@ class SourceFile {
|
|
|
191
223
|
}
|
|
192
224
|
quote(val) {
|
|
193
225
|
const backtick = val.startsWith(`'`) || val.includes('\n');
|
|
194
|
-
/*
|
|
226
|
+
/* v8 ignore next */
|
|
195
227
|
return backtick ? `\`${val.replaceAll('`', '\\``')}\`` : `'${val.replaceAll(`'`, `\\'`)}'`;
|
|
196
228
|
}
|
|
197
229
|
getPropertyDefinition(prop, padLeft) {
|
|
198
230
|
const padding = ' '.repeat(padLeft);
|
|
199
|
-
const propName =
|
|
231
|
+
const propName = identifierRegex.test(prop.name) ? prop.name : this.quote(prop.name);
|
|
232
|
+
const enumMode = this.options.enumMode;
|
|
200
233
|
let hiddenType = '';
|
|
201
234
|
if (prop.hidden) {
|
|
202
235
|
hiddenType += ` & ${this.referenceCoreImport('Hidden')}`;
|
|
203
236
|
}
|
|
204
|
-
if ([
|
|
237
|
+
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
205
238
|
return `${padding}${propName}${hiddenType ? `: ${this.referenceCoreImport('Collection')}<${prop.type}>${hiddenType}` : ''} = new ${this.referenceCoreImport('Collection')}<${prop.type}>(this);\n`;
|
|
206
239
|
}
|
|
207
|
-
const isScalar = typeof prop.kind === 'undefined' || prop.kind ===
|
|
240
|
+
const isScalar = typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR;
|
|
208
241
|
let breakdownOfIType;
|
|
209
242
|
const propType = prop.mapToPk
|
|
210
243
|
? (() => {
|
|
@@ -214,7 +247,11 @@ class SourceFile {
|
|
|
214
247
|
: (() => {
|
|
215
248
|
if (isScalar) {
|
|
216
249
|
if (prop.enum) {
|
|
217
|
-
|
|
250
|
+
const method = enumMode === 'ts-enum' ? 'getEnumClassName' : 'getEnumTypeName';
|
|
251
|
+
if (prop.nativeEnumName) {
|
|
252
|
+
return this.namingStrategy[method](prop.nativeEnumName, undefined, this.meta.schema);
|
|
253
|
+
}
|
|
254
|
+
return this.namingStrategy[method](prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
218
255
|
}
|
|
219
256
|
breakdownOfIType = this.breakdownOfIType(prop);
|
|
220
257
|
if (typeof breakdownOfIType !== 'undefined') {
|
|
@@ -231,7 +268,7 @@ class SourceFile {
|
|
|
231
268
|
const useDefault = hasUsableNullDefault || (!(typeof prop.default === 'undefined' || prop.default === null) && propType !== 'unknown' && typeof breakdownOfIType === 'undefined');
|
|
232
269
|
const optional = (prop.nullable && (this.options.forceUndefined || prop.optional)) ? '?' : (useDefault ? '' : '!');
|
|
233
270
|
let ret = `${propName}${optional}: `;
|
|
234
|
-
const isArray = prop.array && (prop.kind ===
|
|
271
|
+
const isArray = prop.array && (prop.kind === ReferenceKind.EMBEDDED || prop.enum);
|
|
235
272
|
const complexType = isArray ? `${propType}[]` : propType;
|
|
236
273
|
let wrappedType = prop.ref
|
|
237
274
|
? `${this.referenceCoreImport('Ref')}<${complexType}${(isScalar && prop.nullable && !this.options.forceUndefined) ? ' | null' : ''}>`
|
|
@@ -249,8 +286,14 @@ class SourceFile {
|
|
|
249
286
|
return `${padding}${ret};\n`;
|
|
250
287
|
}
|
|
251
288
|
if (prop.enum && typeof prop.default === 'string') {
|
|
289
|
+
if (enumMode === 'union-type') {
|
|
290
|
+
return `${padding}${ret} = ${this.quote(prop.default)};\n`;
|
|
291
|
+
}
|
|
292
|
+
const enumClassName = prop.nativeEnumName
|
|
293
|
+
? this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema)
|
|
294
|
+
: this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
252
295
|
const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
253
|
-
return `${padding}${ret} = ${
|
|
296
|
+
return `${padding}${ret} = ${enumClassName}${identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
|
|
254
297
|
}
|
|
255
298
|
if (prop.fieldNames?.length > 1) {
|
|
256
299
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
@@ -266,19 +309,55 @@ class SourceFile {
|
|
|
266
309
|
return `${padding}${ret} = ${prop.ref ? this.referenceCoreImport('ref') : this.referenceCoreImport('rel')}(${propType}, ${defaultVal});\n`;
|
|
267
310
|
}
|
|
268
311
|
getEnumClassDefinition(prop, padLeft) {
|
|
312
|
+
const enumMode = this.options.enumMode;
|
|
313
|
+
if (prop.nativeEnumName) {
|
|
314
|
+
const imports = [];
|
|
315
|
+
if (enumMode !== 'union-type') {
|
|
316
|
+
imports.push(prop.runtimeType);
|
|
317
|
+
}
|
|
318
|
+
if (!this.options.inferEntityType && enumMode !== 'ts-enum') {
|
|
319
|
+
const enumTypeName = this.namingStrategy.getEnumTypeName(prop.nativeEnumName, undefined, this.meta.schema);
|
|
320
|
+
imports.push(enumTypeName);
|
|
321
|
+
}
|
|
322
|
+
this.enumImports.set(prop.runtimeType, imports);
|
|
323
|
+
return '';
|
|
324
|
+
}
|
|
269
325
|
const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
326
|
+
const enumTypeName = this.namingStrategy.getEnumTypeName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
270
327
|
const padding = ' '.repeat(padLeft);
|
|
271
|
-
let ret = `export enum ${enumClassName} {\n`;
|
|
272
328
|
const enumValues = prop.items;
|
|
329
|
+
if (enumMode === 'union-type') {
|
|
330
|
+
return `export type ${enumTypeName} = ${enumValues.map(item => this.quote(item)).join(' | ')};\n`;
|
|
331
|
+
}
|
|
332
|
+
let ret = '';
|
|
333
|
+
if (enumMode === 'dictionary') {
|
|
334
|
+
ret += `export const ${enumClassName} = {\n`;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
ret += `export enum ${enumClassName} {\n`;
|
|
338
|
+
}
|
|
273
339
|
for (const enumValue of enumValues) {
|
|
274
340
|
const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
275
|
-
|
|
341
|
+
if (enumMode === 'dictionary') {
|
|
342
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)}: ${this.quote(enumValue)},\n`;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (enumMode === 'dictionary') {
|
|
349
|
+
ret += '} as const;\n';
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
ret += '}\n';
|
|
353
|
+
}
|
|
354
|
+
if (enumMode === 'dictionary') {
|
|
355
|
+
ret += `\nexport type ${enumTypeName} = (typeof ${enumClassName})[keyof typeof ${enumClassName}];\n`;
|
|
276
356
|
}
|
|
277
|
-
ret += '}\n';
|
|
278
357
|
return ret;
|
|
279
358
|
}
|
|
280
359
|
serializeObject(options, wordwrap, spaces, level = 0) {
|
|
281
|
-
if (typeof wordwrap === 'number' && !Object.hasOwn(options,
|
|
360
|
+
if (typeof wordwrap === 'number' && !Object.hasOwn(options, Config)) {
|
|
282
361
|
const res = this.serializeObject(options, undefined, undefined, level);
|
|
283
362
|
if (res.length <= wordwrap) {
|
|
284
363
|
return res;
|
|
@@ -292,7 +371,7 @@ class SourceFile {
|
|
|
292
371
|
}
|
|
293
372
|
const entries = Object.entries(options);
|
|
294
373
|
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries.map(([opt, val]) => {
|
|
295
|
-
const key =
|
|
374
|
+
const key = identifierRegex.test(opt) ? opt : this.quote(opt);
|
|
296
375
|
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)}`;
|
|
297
376
|
}).join(sep)}${doIndent ? `${entries.length > 0 ? ',\n' : ''}${' '.repeat(spaces + (level * 2))}` : ' '}}`;
|
|
298
377
|
}
|
|
@@ -314,7 +393,7 @@ class SourceFile {
|
|
|
314
393
|
options.expression = this.quote(this.meta.expression);
|
|
315
394
|
}
|
|
316
395
|
else if (typeof this.meta.expression === 'function') {
|
|
317
|
-
options.expression =
|
|
396
|
+
options.expression = this.meta.expression.toString();
|
|
318
397
|
}
|
|
319
398
|
if (this.meta.repositoryClass) {
|
|
320
399
|
this.entityImports.add(this.meta.repositoryClass);
|
|
@@ -354,17 +433,17 @@ class SourceFile {
|
|
|
354
433
|
getPropertyDecorator(prop, padLeft) {
|
|
355
434
|
const padding = ' '.repeat(padLeft);
|
|
356
435
|
const options = {};
|
|
357
|
-
let decorator = `@${this.
|
|
358
|
-
if (prop.kind ===
|
|
436
|
+
let decorator = `@${this.referenceDecoratorImport(this.getDecoratorType(prop))}`;
|
|
437
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
359
438
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
360
439
|
}
|
|
361
|
-
else if (prop.kind ===
|
|
440
|
+
else if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
362
441
|
this.getOneToManyDecoratorOptions(options, prop);
|
|
363
442
|
}
|
|
364
|
-
else if (prop.kind ===
|
|
443
|
+
else if (prop.kind === ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
|
|
365
444
|
this.getScalarPropertyDecoratorOptions(options, prop);
|
|
366
445
|
}
|
|
367
|
-
else if (prop.kind ===
|
|
446
|
+
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
368
447
|
this.getEmbeddedPropertyDeclarationOptions(options, prop);
|
|
369
448
|
}
|
|
370
449
|
else {
|
|
@@ -375,9 +454,9 @@ class SourceFile {
|
|
|
375
454
|
decorator = [...indexes.sort(), decorator].map(d => padding + d).join('\n');
|
|
376
455
|
const decoratorArgs = [];
|
|
377
456
|
if (prop.formula) {
|
|
378
|
-
decoratorArgs.push(
|
|
457
|
+
decoratorArgs.push(prop.formula.toString());
|
|
379
458
|
}
|
|
380
|
-
if (
|
|
459
|
+
if (Utils.hasObjectKeys(options)) {
|
|
381
460
|
decoratorArgs.push(`${this.serializeObject(options)}`);
|
|
382
461
|
}
|
|
383
462
|
return `${decorator}(${decoratorArgs.join(', ')})\n`;
|
|
@@ -392,7 +471,7 @@ class SourceFile {
|
|
|
392
471
|
options[type] = (propType === true || defaultName === propType) ? 'true' : this.quote(propType);
|
|
393
472
|
const expected = {
|
|
394
473
|
index: this.platform.indexForeignKeys(),
|
|
395
|
-
unique: prop.kind ===
|
|
474
|
+
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
396
475
|
};
|
|
397
476
|
if (expected[type] && options[type] === 'true') {
|
|
398
477
|
delete options[type];
|
|
@@ -404,26 +483,26 @@ class SourceFile {
|
|
|
404
483
|
let propIndexIsNonTrivialIndex = false;
|
|
405
484
|
const nonTrivialIndexes = this.meta.indexes.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
406
485
|
for (const i of nonTrivialIndexes) {
|
|
407
|
-
ret.push(`@${this.
|
|
486
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${this.serializeObject(this.getIndexOptions(i, false))})`);
|
|
408
487
|
if (prop.index === i.name) {
|
|
409
488
|
propIndexIsNonTrivialIndex = true;
|
|
410
489
|
delete options.index;
|
|
411
490
|
}
|
|
412
491
|
}
|
|
413
492
|
if (prop.index && !options.index && !propIndexIsNonTrivialIndex) {
|
|
414
|
-
ret.push(`@${this.
|
|
493
|
+
ret.push(`@${this.referenceDecoratorImport('Index')}(${typeof prop.index === 'string' ? `{ name: ${this.quote(prop.index)} }` : ''})`);
|
|
415
494
|
}
|
|
416
495
|
let propIndexIsNonTrivialUnique = false;
|
|
417
496
|
const nonTrivialUnique = this.meta.uniques.filter(i => i.properties?.length === 1 && i.properties[0] === prop.name);
|
|
418
497
|
for (const i of nonTrivialUnique) {
|
|
419
|
-
ret.push(`@${this.
|
|
498
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${this.serializeObject(this.getUniqueOptions(i, false))})`);
|
|
420
499
|
if (prop.unique === i.name) {
|
|
421
500
|
propIndexIsNonTrivialUnique = true;
|
|
422
501
|
delete options.unique;
|
|
423
502
|
}
|
|
424
503
|
}
|
|
425
504
|
if (prop.unique && !options.unique && !propIndexIsNonTrivialUnique) {
|
|
426
|
-
ret.push(`@${this.
|
|
505
|
+
ret.push(`@${this.referenceDecoratorImport('Unique')}(${typeof prop.unique === 'string' ? `{ name: ${this.quote(prop.unique)} }` : ''})`);
|
|
427
506
|
}
|
|
428
507
|
return ret;
|
|
429
508
|
}
|
|
@@ -431,10 +510,10 @@ class SourceFile {
|
|
|
431
510
|
if (!prop.mappedBy && (prop.nullable || prop.customTypes?.[0]?.prop?.nullable)) {
|
|
432
511
|
options.nullable = true;
|
|
433
512
|
}
|
|
434
|
-
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind ===
|
|
513
|
+
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
435
514
|
options.primary = true;
|
|
436
515
|
}
|
|
437
|
-
['persist', 'hydrate'
|
|
516
|
+
['persist', 'hydrate']
|
|
438
517
|
.filter(key => prop[key] === false)
|
|
439
518
|
.forEach(key => options[key] = false);
|
|
440
519
|
['onCreate', 'onUpdate', 'serializer']
|
|
@@ -449,7 +528,7 @@ class SourceFile {
|
|
|
449
528
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
450
529
|
.filter(key => prop[key])
|
|
451
530
|
.forEach(key => options[key] = true);
|
|
452
|
-
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !==
|
|
531
|
+
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
453
532
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
454
533
|
}
|
|
455
534
|
if (typeof prop.comment === 'string') {
|
|
@@ -461,7 +540,7 @@ class SourceFile {
|
|
|
461
540
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
462
541
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
463
542
|
}
|
|
464
|
-
else if (!(typeof prop.default === 'undefined' || prop.default === null) && (prop.ref || (!prop.enum && (typeof prop.kind === 'undefined' || prop.kind ===
|
|
543
|
+
else if (!(typeof prop.default === 'undefined' || prop.default === null) && (prop.ref || (!prop.enum && (typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR) && (prop.type === 'unknown' || typeof this.breakdownOfIType(prop) !== 'undefined')))) {
|
|
465
544
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
466
545
|
}
|
|
467
546
|
}
|
|
@@ -482,7 +561,7 @@ class SourceFile {
|
|
|
482
561
|
return this.propTypeBreakdowns.get(prop);
|
|
483
562
|
}
|
|
484
563
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
485
|
-
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
564
|
+
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType)
|
|
486
565
|
? this.platform.getMappedType(prop.columnTypes[0])
|
|
487
566
|
: mappedDeclaredType));
|
|
488
567
|
const rawType = mappedRawType.runtimeType;
|
|
@@ -533,12 +612,23 @@ class SourceFile {
|
|
|
533
612
|
this.propTypeBreakdowns.set(prop, r);
|
|
534
613
|
return r;
|
|
535
614
|
}
|
|
536
|
-
getScalarPropertyDecoratorOptions(options, prop) {
|
|
615
|
+
getScalarPropertyDecoratorOptions(options, prop, quote = true) {
|
|
537
616
|
if (prop.fieldNames[0] !== this.namingStrategy.propertyToColumnName(prop.name)) {
|
|
538
617
|
options.fieldName = this.quote(prop.fieldNames[0]);
|
|
539
618
|
}
|
|
540
619
|
if (prop.enum) {
|
|
541
|
-
options.
|
|
620
|
+
if (this.options.enumMode === 'union-type') {
|
|
621
|
+
options.items = `[${prop.items.map(item => this.quote(item)).join(', ')}]`;
|
|
622
|
+
}
|
|
623
|
+
else if (prop.nativeEnumName) {
|
|
624
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema);
|
|
625
|
+
options.items = `() => ${enumClassName}`;
|
|
626
|
+
options.nativeEnumName = this.quote(prop.nativeEnumName);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
630
|
+
options.items = `() => ${enumClassName}`;
|
|
631
|
+
}
|
|
542
632
|
}
|
|
543
633
|
// For enum properties, we don't need a column type
|
|
544
634
|
// or the property length or other information in the decorator.
|
|
@@ -551,7 +641,7 @@ class SourceFile {
|
|
|
551
641
|
? mappedColumnType
|
|
552
642
|
: this.platform.getMappedType(prop.runtimeType);
|
|
553
643
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
554
|
-
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
644
|
+
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType;
|
|
555
645
|
if (isTypeStringMissingFromMap) {
|
|
556
646
|
this.entityImports.add(prop.type);
|
|
557
647
|
options.type = prop.type;
|
|
@@ -567,14 +657,14 @@ class SourceFile {
|
|
|
567
657
|
return ((useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable));
|
|
568
658
|
})() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
|
|
569
659
|
) {
|
|
570
|
-
options.type = this.quote(prop.type);
|
|
660
|
+
options.type = quote ? this.quote(prop.type) : prop.type;
|
|
571
661
|
}
|
|
572
662
|
}
|
|
573
663
|
const columnTypeFromMappedRuntimeType = mappedRuntimeType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
574
664
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
575
665
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
576
666
|
const needsExplicitColumnType = () => {
|
|
577
|
-
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof
|
|
667
|
+
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
578
668
|
return true;
|
|
579
669
|
}
|
|
580
670
|
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !== this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
@@ -594,8 +684,8 @@ class SourceFile {
|
|
|
594
684
|
assign('length');
|
|
595
685
|
}
|
|
596
686
|
// those are already included in the `columnType` in most cases, and when that option is present, they would be ignored anyway
|
|
597
|
-
/*
|
|
598
|
-
if (mappedColumnType instanceof
|
|
687
|
+
/* v8 ignore next */
|
|
688
|
+
if (mappedColumnType instanceof DecimalType && !options.columnType) {
|
|
599
689
|
assign('precision');
|
|
600
690
|
assign('scale');
|
|
601
691
|
}
|
|
@@ -621,6 +711,9 @@ class SourceFile {
|
|
|
621
711
|
getManyToManyDecoratorOptions(options, prop) {
|
|
622
712
|
this.entityImports.add(prop.type);
|
|
623
713
|
options.entity = `() => ${prop.type}`;
|
|
714
|
+
if (prop.orderBy) {
|
|
715
|
+
options.orderBy = inspect(prop.orderBy);
|
|
716
|
+
}
|
|
624
717
|
if (prop.mappedBy) {
|
|
625
718
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
626
719
|
return;
|
|
@@ -655,6 +748,9 @@ class SourceFile {
|
|
|
655
748
|
this.entityImports.add(prop.type);
|
|
656
749
|
options.entity = `() => ${prop.type}`;
|
|
657
750
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
751
|
+
if (prop.orderBy) {
|
|
752
|
+
options.orderBy = inspect(prop.orderBy);
|
|
753
|
+
}
|
|
658
754
|
}
|
|
659
755
|
getEmbeddedPropertyDeclarationOptions(options, prop) {
|
|
660
756
|
this.entityImports.add(prop.type);
|
|
@@ -662,7 +758,7 @@ class SourceFile {
|
|
|
662
758
|
if (prop.array) {
|
|
663
759
|
options.array = true;
|
|
664
760
|
}
|
|
665
|
-
if (prop.object) {
|
|
761
|
+
if (prop.object && !prop.array) {
|
|
666
762
|
options.object = true;
|
|
667
763
|
}
|
|
668
764
|
if (prop.prefix === false || typeof prop.prefix === 'string') {
|
|
@@ -713,19 +809,19 @@ class SourceFile {
|
|
|
713
809
|
}
|
|
714
810
|
}
|
|
715
811
|
getDecoratorType(prop) {
|
|
716
|
-
if (prop.kind ===
|
|
812
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
717
813
|
return 'OneToOne';
|
|
718
814
|
}
|
|
719
|
-
if (prop.kind ===
|
|
815
|
+
if (prop.kind === ReferenceKind.MANY_TO_ONE) {
|
|
720
816
|
return 'ManyToOne';
|
|
721
817
|
}
|
|
722
|
-
if (prop.kind ===
|
|
818
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
723
819
|
return 'OneToMany';
|
|
724
820
|
}
|
|
725
|
-
if (prop.kind ===
|
|
821
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
726
822
|
return 'ManyToMany';
|
|
727
823
|
}
|
|
728
|
-
if (prop.kind ===
|
|
824
|
+
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
729
825
|
return 'Embedded';
|
|
730
826
|
}
|
|
731
827
|
if (prop.enum) {
|
|
@@ -745,5 +841,10 @@ class SourceFile {
|
|
|
745
841
|
? `${this.options.coreImportsPrefix}${identifier}`
|
|
746
842
|
: identifier;
|
|
747
843
|
}
|
|
844
|
+
referenceDecoratorImport(identifier) {
|
|
845
|
+
this.decoratorImports.add(identifier);
|
|
846
|
+
return this.options.coreImportsPrefix
|
|
847
|
+
? `${this.options.coreImportsPrefix}${identifier}`
|
|
848
|
+
: identifier;
|
|
849
|
+
}
|
|
748
850
|
}
|
|
749
|
-
exports.SourceFile = SourceFile;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
1
|
/**
|
|
18
2
|
* @packageDocumentation
|
|
19
3
|
* @module entity-generator
|
|
20
4
|
*/
|
|
21
|
-
|
|
5
|
+
export * from './EntityGenerator.js';
|
package/package.json
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/entity-generator",
|
|
3
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "7.0.0-dev.100",
|
|
4
5
|
"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
|
-
"main": "index.js",
|
|
6
|
-
"module": "index.mjs",
|
|
7
|
-
"typings": "index.d.ts",
|
|
8
6
|
"exports": {
|
|
9
7
|
"./package.json": "./package.json",
|
|
10
|
-
".":
|
|
11
|
-
"import": {
|
|
12
|
-
"types": "./index.d.ts",
|
|
13
|
-
"default": "./index.mjs"
|
|
14
|
-
},
|
|
15
|
-
"require": "./index.js"
|
|
16
|
-
}
|
|
8
|
+
".": "./index.js"
|
|
17
9
|
},
|
|
18
10
|
"repository": {
|
|
19
11
|
"type": "git",
|
|
@@ -46,10 +38,10 @@
|
|
|
46
38
|
},
|
|
47
39
|
"homepage": "https://mikro-orm.io",
|
|
48
40
|
"engines": {
|
|
49
|
-
"node": ">= 22.
|
|
41
|
+
"node": ">= 22.17.0"
|
|
50
42
|
},
|
|
51
43
|
"scripts": {
|
|
52
|
-
"build": "yarn clean && yarn compile && yarn copy
|
|
44
|
+
"build": "yarn clean && yarn compile && yarn copy",
|
|
53
45
|
"clean": "yarn run -T rimraf ./dist",
|
|
54
46
|
"compile": "yarn run -T tsc -p tsconfig.build.json",
|
|
55
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
@@ -58,13 +50,12 @@
|
|
|
58
50
|
"access": "public"
|
|
59
51
|
},
|
|
60
52
|
"dependencies": {
|
|
61
|
-
"@mikro-orm/
|
|
62
|
-
"fs-extra": "11.3.0"
|
|
53
|
+
"@mikro-orm/sql": "7.0.0-dev.100"
|
|
63
54
|
},
|
|
64
55
|
"devDependencies": {
|
|
65
|
-
"@mikro-orm/core": "^6.
|
|
56
|
+
"@mikro-orm/core": "^6.6.2"
|
|
66
57
|
},
|
|
67
58
|
"peerDependencies": {
|
|
68
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.100"
|
|
69
60
|
}
|
|
70
61
|
}
|
package/index.mjs
DELETED