@mikro-orm/entity-generator 7.0.0-dev.1 → 7.0.0-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CoreImportsHelper.js +1 -4
- package/EntityGenerator.js +31 -35
- package/EntitySchemaSourceFile.d.ts +1 -1
- package/EntitySchemaSourceFile.js +14 -18
- package/SourceFile.js +42 -46
- package/index.d.ts +1 -1
- package/index.js +1 -17
- package/package.json +6 -15
- package/index.mjs +0 -4
package/CoreImportsHelper.js
CHANGED
package/EntityGenerator.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const EntitySchemaSourceFile_1 = require("./EntitySchemaSourceFile");
|
|
9
|
-
const SourceFile_1 = require("./SourceFile");
|
|
10
|
-
class EntityGenerator {
|
|
1
|
+
import { EntityMetadata, ReferenceKind, types, Utils, } from '@mikro-orm/core';
|
|
2
|
+
import { DatabaseSchema, } from '@mikro-orm/knex';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { writeFile } from 'node:fs/promises';
|
|
5
|
+
import { EntitySchemaSourceFile } from './EntitySchemaSourceFile.js';
|
|
6
|
+
import { SourceFile } from './SourceFile.js';
|
|
7
|
+
export class EntityGenerator {
|
|
11
8
|
em;
|
|
12
9
|
config;
|
|
13
10
|
driver;
|
|
@@ -30,30 +27,30 @@ class EntityGenerator {
|
|
|
30
27
|
orm.config.registerExtension('@mikro-orm/entity-generator', () => new EntityGenerator(orm.em));
|
|
31
28
|
}
|
|
32
29
|
async generate(options = {}) {
|
|
33
|
-
options =
|
|
34
|
-
const schema = await
|
|
30
|
+
options = Utils.mergeConfig({}, this.config.get('entityGenerator'), options);
|
|
31
|
+
const schema = await DatabaseSchema.create(this.connection, this.platform, this.config, undefined, undefined, options.takeTables, options.skipTables);
|
|
35
32
|
const metadata = await this.getEntityMetadata(schema, options);
|
|
36
33
|
const defaultPath = `${this.config.get('baseDir')}/generated-entities`;
|
|
37
|
-
const baseDir =
|
|
34
|
+
const baseDir = Utils.normalizePath(options.path ?? defaultPath);
|
|
38
35
|
for (const meta of metadata) {
|
|
39
36
|
if (!meta.pivotTable || options.outputPurePivotTables || this.referencedEntities.has(meta)) {
|
|
40
37
|
if (options.entitySchema) {
|
|
41
|
-
this.sources.push(new
|
|
38
|
+
this.sources.push(new EntitySchemaSourceFile(meta, this.namingStrategy, this.platform, { ...options, scalarTypeInDecorator: true }));
|
|
42
39
|
}
|
|
43
40
|
else {
|
|
44
|
-
this.sources.push(new
|
|
41
|
+
this.sources.push(new SourceFile(meta, this.namingStrategy, this.platform, options));
|
|
45
42
|
}
|
|
46
43
|
}
|
|
47
44
|
}
|
|
48
45
|
if (options.save) {
|
|
49
|
-
|
|
46
|
+
Utils.ensureDir(baseDir);
|
|
50
47
|
await Promise.all(this.sources.map(async (file) => {
|
|
51
48
|
const fileName = file.getBaseName();
|
|
52
|
-
const fileDir =
|
|
49
|
+
const fileDir = dirname(fileName);
|
|
53
50
|
if (fileDir !== '.') {
|
|
54
|
-
|
|
51
|
+
Utils.ensureDir(join(baseDir, fileDir));
|
|
55
52
|
}
|
|
56
|
-
return
|
|
53
|
+
return writeFile(join(baseDir, fileName), file.generate(), { flush: true });
|
|
57
54
|
}));
|
|
58
55
|
}
|
|
59
56
|
return this.sources.map(file => file.generate());
|
|
@@ -76,11 +73,11 @@ class EntityGenerator {
|
|
|
76
73
|
for (const meta of metadata) {
|
|
77
74
|
for (const prop of meta.relations) {
|
|
78
75
|
if (!metadata.some(otherMeta => prop.referencedTableName === otherMeta.collection || prop.referencedTableName === `${otherMeta.schema ?? schema.name}.${otherMeta.collection}`)) {
|
|
79
|
-
prop.kind =
|
|
76
|
+
prop.kind = ReferenceKind.SCALAR;
|
|
80
77
|
const mappedTypes = prop.columnTypes.map((t, i) => this.platform.getMappedType(t));
|
|
81
78
|
const runtimeTypes = mappedTypes.map(t => t.runtimeType);
|
|
82
79
|
prop.runtimeType = (runtimeTypes.length === 1 ? runtimeTypes[0] : `[${runtimeTypes.join(', ')}]`);
|
|
83
|
-
prop.type = mappedTypes.length === 1 ? (
|
|
80
|
+
prop.type = mappedTypes.length === 1 ? (Utils.entries(types).find(([k, v]) => Object.getPrototypeOf(mappedTypes[0]) === v.prototype)?.[0] ?? mappedTypes[0].name) : 'unknown';
|
|
84
81
|
}
|
|
85
82
|
const meta2 = metadata.find(meta2 => meta2.className === prop.type);
|
|
86
83
|
const targetPrimaryColumns = meta2?.getPrimaryProps().flatMap(p => p.fieldNames);
|
|
@@ -93,7 +90,7 @@ class EntityGenerator {
|
|
|
93
90
|
}
|
|
94
91
|
await options.onInitialMetadata?.(metadata, this.platform);
|
|
95
92
|
// enforce schema usage in class names only on duplicates
|
|
96
|
-
const duplicates =
|
|
93
|
+
const duplicates = Utils.findDuplicates(metadata.map(meta => meta.className));
|
|
97
94
|
for (const duplicate of duplicates) {
|
|
98
95
|
for (const meta of metadata.filter(meta => meta.className === duplicate)) {
|
|
99
96
|
meta.className = this.namingStrategy.getEntityName(`${meta.schema ?? schema.name}_${meta.className}`);
|
|
@@ -131,7 +128,7 @@ class EntityGenerator {
|
|
|
131
128
|
for (const meta of metadata) {
|
|
132
129
|
const isReferenced = metadata.some(m => {
|
|
133
130
|
return m.tableName !== meta.tableName && m.relations.some(r => {
|
|
134
|
-
return r.referencedTableName === meta.tableName && [
|
|
131
|
+
return r.referencedTableName === meta.tableName && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(r.kind);
|
|
135
132
|
});
|
|
136
133
|
});
|
|
137
134
|
if (isReferenced) {
|
|
@@ -144,7 +141,7 @@ class EntityGenerator {
|
|
|
144
141
|
// Entities where there are not exactly 2 PK relations that are both ManyToOne are never pivot tables. Skip.
|
|
145
142
|
const pkRelations = meta.relations.filter(rel => rel.primary);
|
|
146
143
|
if (pkRelations.length !== 2 ||
|
|
147
|
-
pkRelations.some(rel => rel.kind !==
|
|
144
|
+
pkRelations.some(rel => rel.kind !== ReferenceKind.MANY_TO_ONE)) {
|
|
148
145
|
continue;
|
|
149
146
|
}
|
|
150
147
|
const pkRelationFields = new Set(pkRelations.flatMap(rel => rel.fieldNames));
|
|
@@ -196,7 +193,7 @@ class EntityGenerator {
|
|
|
196
193
|
const name = this.namingStrategy.columnNameToProperty(meta.tableName.replace(new RegExp('^' + owner.tableName + '_'), ''));
|
|
197
194
|
const ownerProp = {
|
|
198
195
|
name,
|
|
199
|
-
kind:
|
|
196
|
+
kind: ReferenceKind.MANY_TO_MANY,
|
|
200
197
|
pivotTable: meta.tableName,
|
|
201
198
|
type: meta.relations[1].type,
|
|
202
199
|
joinColumns: meta.relations[0].fieldNames,
|
|
@@ -229,21 +226,21 @@ class EntityGenerator {
|
|
|
229
226
|
type: meta.className,
|
|
230
227
|
joinColumns: prop.fieldNames,
|
|
231
228
|
referencedTableName: meta.tableName,
|
|
232
|
-
referencedColumnNames:
|
|
229
|
+
referencedColumnNames: Utils.flatten(targetMeta.getPrimaryProps().map(pk => pk.fieldNames)),
|
|
233
230
|
mappedBy: prop.name,
|
|
234
231
|
persist: prop.persist,
|
|
235
232
|
};
|
|
236
|
-
if (prop.kind ===
|
|
237
|
-
newProp.kind =
|
|
233
|
+
if (prop.kind === ReferenceKind.MANY_TO_ONE) {
|
|
234
|
+
newProp.kind = ReferenceKind.ONE_TO_MANY;
|
|
238
235
|
}
|
|
239
|
-
else if (prop.kind ===
|
|
240
|
-
newProp.kind =
|
|
236
|
+
else if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.mappedBy) {
|
|
237
|
+
newProp.kind = ReferenceKind.ONE_TO_ONE;
|
|
241
238
|
newProp.nullable = true;
|
|
242
239
|
newProp.default = null;
|
|
243
240
|
newProp.defaultRaw = 'null';
|
|
244
241
|
}
|
|
245
|
-
else if (prop.kind ===
|
|
246
|
-
newProp.kind =
|
|
242
|
+
else if (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.mappedBy) {
|
|
243
|
+
newProp.kind = ReferenceKind.MANY_TO_MANY;
|
|
247
244
|
}
|
|
248
245
|
else {
|
|
249
246
|
continue;
|
|
@@ -260,7 +257,7 @@ class EntityGenerator {
|
|
|
260
257
|
generateIdentifiedReferences(metadata) {
|
|
261
258
|
for (const meta of metadata.filter(m => !m.pivotTable || this.referencedEntities.has(m))) {
|
|
262
259
|
for (const prop of Object.values(meta.properties)) {
|
|
263
|
-
if ([
|
|
260
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) || prop.lazy) {
|
|
264
261
|
prop.ref = true;
|
|
265
262
|
}
|
|
266
263
|
}
|
|
@@ -276,7 +273,7 @@ class EntityGenerator {
|
|
|
276
273
|
meta.extends ??= customBaseEntityName;
|
|
277
274
|
}
|
|
278
275
|
if (!baseClassExists) {
|
|
279
|
-
metadata.push(new
|
|
276
|
+
metadata.push(new EntityMetadata({
|
|
280
277
|
className: customBaseEntityName,
|
|
281
278
|
abstract: true,
|
|
282
279
|
relations: [],
|
|
@@ -294,4 +291,3 @@ class EntityGenerator {
|
|
|
294
291
|
}
|
|
295
292
|
}
|
|
296
293
|
}
|
|
297
|
-
exports.EntityGenerator = EntityGenerator;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Dictionary, type EntityProperty } from '@mikro-orm/core';
|
|
2
|
-
import { SourceFile } from './SourceFile';
|
|
2
|
+
import { SourceFile } from './SourceFile.js';
|
|
3
3
|
export declare class EntitySchemaSourceFile extends SourceFile {
|
|
4
4
|
generate(): string;
|
|
5
5
|
private getPropertyOptions;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const core_1 = require("@mikro-orm/core");
|
|
5
|
-
const SourceFile_1 = require("./SourceFile");
|
|
6
|
-
class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
1
|
+
import { Config, ReferenceKind, } from '@mikro-orm/core';
|
|
2
|
+
import { SourceFile } from './SourceFile.js';
|
|
3
|
+
export class EntitySchemaSourceFile extends SourceFile {
|
|
7
4
|
generate() {
|
|
8
5
|
let classBody = '';
|
|
9
6
|
if (this.meta.className === this.options.customBaseEntityName) {
|
|
@@ -17,7 +14,7 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
17
14
|
const props = [];
|
|
18
15
|
for (const prop of Object.values(this.meta.properties)) {
|
|
19
16
|
props.push(this.getPropertyDefinition(prop, 2));
|
|
20
|
-
if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind ===
|
|
17
|
+
if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR)) {
|
|
21
18
|
enumDefinitions.push(this.getEnumClassDefinition(prop, 2));
|
|
22
19
|
}
|
|
23
20
|
if (prop.eager) {
|
|
@@ -60,8 +57,8 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
60
57
|
}
|
|
61
58
|
entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyOptions(prop)]));
|
|
62
59
|
// Force top level and properties to be indented, regardless of line length
|
|
63
|
-
entitySchemaOptions[
|
|
64
|
-
entitySchemaOptions.properties[
|
|
60
|
+
entitySchemaOptions[Config] = true;
|
|
61
|
+
entitySchemaOptions.properties[Config] = true;
|
|
65
62
|
ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
|
|
66
63
|
ret += ');\n';
|
|
67
64
|
ret = `${this.generateImports()}\n\n${ret}`;
|
|
@@ -72,19 +69,19 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
72
69
|
if (prop.primary) {
|
|
73
70
|
options.primary = true;
|
|
74
71
|
}
|
|
75
|
-
if (typeof prop.kind !== 'undefined' && prop.kind !==
|
|
72
|
+
if (typeof prop.kind !== 'undefined' && prop.kind !== ReferenceKind.SCALAR) {
|
|
76
73
|
options.kind = this.quote(prop.kind);
|
|
77
74
|
}
|
|
78
|
-
if (prop.kind ===
|
|
75
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
79
76
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
80
77
|
}
|
|
81
|
-
else if (prop.kind ===
|
|
78
|
+
else if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
82
79
|
this.getOneToManyDecoratorOptions(options, prop);
|
|
83
80
|
}
|
|
84
|
-
else if (prop.kind ===
|
|
81
|
+
else if (prop.kind === ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
|
|
85
82
|
this.getScalarPropertyDecoratorOptions(options, prop);
|
|
86
83
|
}
|
|
87
|
-
else if (prop.kind ===
|
|
84
|
+
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
88
85
|
this.getEmbeddedPropertyDeclarationOptions(options, prop);
|
|
89
86
|
}
|
|
90
87
|
else {
|
|
@@ -98,7 +95,7 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
98
95
|
return options;
|
|
99
96
|
}
|
|
100
97
|
getPropertyIndexesOptions(prop, options) {
|
|
101
|
-
if (prop.kind ===
|
|
98
|
+
if (prop.kind === ReferenceKind.SCALAR) {
|
|
102
99
|
if (prop.index) {
|
|
103
100
|
options.index = this.quote(prop.index);
|
|
104
101
|
}
|
|
@@ -113,11 +110,11 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
113
110
|
return;
|
|
114
111
|
}
|
|
115
112
|
const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
|
|
116
|
-
/*
|
|
113
|
+
/* v8 ignore next */
|
|
117
114
|
options[type] = (propType === true || defaultName === propType) ? 'true' : this.quote(propType);
|
|
118
115
|
const expected = {
|
|
119
116
|
index: this.platform.indexForeignKeys(),
|
|
120
|
-
unique: prop.kind ===
|
|
117
|
+
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
121
118
|
};
|
|
122
119
|
if (expected[type] && options[type] === 'true') {
|
|
123
120
|
delete options[type];
|
|
@@ -137,4 +134,3 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
|
|
|
137
134
|
super.getScalarPropertyDecoratorOptions(options, prop);
|
|
138
135
|
}
|
|
139
136
|
}
|
|
140
|
-
exports.EntitySchemaSourceFile = EntitySchemaSourceFile;
|
package/SourceFile.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
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, } 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, 'bigint', 'Uint8Array', 'unknown', 'object', 'any'];
|
|
9
|
+
export class SourceFile {
|
|
13
10
|
meta;
|
|
14
11
|
namingStrategy;
|
|
15
12
|
platform;
|
|
@@ -27,11 +24,11 @@ class SourceFile {
|
|
|
27
24
|
if (this.meta.embeddable || this.meta.collection) {
|
|
28
25
|
if (this.meta.embeddable) {
|
|
29
26
|
const options = this.getEmbeddableDeclOptions();
|
|
30
|
-
ret += `@${this.referenceCoreImport('Embeddable')}(${
|
|
27
|
+
ret += `@${this.referenceCoreImport('Embeddable')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
31
28
|
}
|
|
32
29
|
else {
|
|
33
30
|
const options = this.getEntityDeclOptions();
|
|
34
|
-
ret += `@${this.referenceCoreImport('Entity')}(${
|
|
31
|
+
ret += `@${this.referenceCoreImport('Entity')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
for (const index of this.meta.indexes) {
|
|
@@ -105,7 +102,7 @@ class SourceFile {
|
|
|
105
102
|
indexOpt.expression = this.quote(index.expression);
|
|
106
103
|
}
|
|
107
104
|
if (isAtEntityLevel && index.properties) {
|
|
108
|
-
indexOpt.properties =
|
|
105
|
+
indexOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
109
106
|
}
|
|
110
107
|
return indexOpt;
|
|
111
108
|
}
|
|
@@ -118,7 +115,7 @@ class SourceFile {
|
|
|
118
115
|
uniqueOpt.expression = this.quote(index.expression);
|
|
119
116
|
}
|
|
120
117
|
if (isAtEntityLevel && index.properties) {
|
|
121
|
-
uniqueOpt.properties =
|
|
118
|
+
uniqueOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
122
119
|
}
|
|
123
120
|
if (index.deferMode) {
|
|
124
121
|
uniqueOpt.deferMode = `${this.referenceCoreImport('DeferMode')}.INITIALLY_${index.deferMode.toUpperCase()}`;
|
|
@@ -129,7 +126,7 @@ class SourceFile {
|
|
|
129
126
|
const imports = new Set();
|
|
130
127
|
if (this.coreImports.size > 0) {
|
|
131
128
|
imports.add(`import { ${([...this.coreImports].sort().map(t => {
|
|
132
|
-
let ret =
|
|
129
|
+
let ret = POSSIBLE_TYPE_IMPORTS.includes(t) ? `type ${t}` : t;
|
|
133
130
|
if (this.options.coreImportsPrefix) {
|
|
134
131
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
135
132
|
ret += ` as ${resolvedIdentifier}`;
|
|
@@ -138,8 +135,8 @@ class SourceFile {
|
|
|
138
135
|
}).join(', '))} } from '@mikro-orm/core';`);
|
|
139
136
|
}
|
|
140
137
|
const extension = this.options.esmImport ? '.js' : '';
|
|
141
|
-
const { dir, base } =
|
|
142
|
-
const basePath =
|
|
138
|
+
const { dir, base } = parse(`${this.options.path ?? '.'}/${this.getBaseName()}`);
|
|
139
|
+
const basePath = relative(dir, this.options.path ?? '.') || '.';
|
|
143
140
|
(this.options.extraImports?.(basePath, base) ?? []).forEach(v => this.entityImports.add(v));
|
|
144
141
|
const entityImports = [...this.entityImports].filter(e => e !== this.meta.className);
|
|
145
142
|
entityImports.sort().forEach(entity => {
|
|
@@ -166,7 +163,7 @@ class SourceFile {
|
|
|
166
163
|
imports.add(`import { ${entity} } from ${this.quote(file.path)};`);
|
|
167
164
|
return;
|
|
168
165
|
}
|
|
169
|
-
imports.add(`import { ${
|
|
166
|
+
imports.add(`import { ${identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
|
|
170
167
|
});
|
|
171
168
|
return Array.from(imports.values()).join('\n');
|
|
172
169
|
}
|
|
@@ -191,20 +188,20 @@ class SourceFile {
|
|
|
191
188
|
}
|
|
192
189
|
quote(val) {
|
|
193
190
|
const backtick = val.startsWith(`'`) || val.includes('\n');
|
|
194
|
-
/*
|
|
191
|
+
/* v8 ignore next */
|
|
195
192
|
return backtick ? `\`${val.replaceAll('`', '\\``')}\`` : `'${val.replaceAll(`'`, `\\'`)}'`;
|
|
196
193
|
}
|
|
197
194
|
getPropertyDefinition(prop, padLeft) {
|
|
198
195
|
const padding = ' '.repeat(padLeft);
|
|
199
|
-
const propName =
|
|
196
|
+
const propName = identifierRegex.test(prop.name) ? prop.name : this.quote(prop.name);
|
|
200
197
|
let hiddenType = '';
|
|
201
198
|
if (prop.hidden) {
|
|
202
199
|
hiddenType += ` & ${this.referenceCoreImport('Hidden')}`;
|
|
203
200
|
}
|
|
204
|
-
if ([
|
|
201
|
+
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
205
202
|
return `${padding}${propName}${hiddenType ? `: ${this.referenceCoreImport('Collection')}<${prop.type}>${hiddenType}` : ''} = new ${this.referenceCoreImport('Collection')}<${prop.type}>(this);\n`;
|
|
206
203
|
}
|
|
207
|
-
const isScalar = typeof prop.kind === 'undefined' || prop.kind ===
|
|
204
|
+
const isScalar = typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR;
|
|
208
205
|
let breakdownOfIType;
|
|
209
206
|
const propType = prop.mapToPk
|
|
210
207
|
? (() => {
|
|
@@ -231,7 +228,7 @@ class SourceFile {
|
|
|
231
228
|
const useDefault = hasUsableNullDefault || (!(typeof prop.default === 'undefined' || prop.default === null) && propType !== 'unknown' && typeof breakdownOfIType === 'undefined');
|
|
232
229
|
const optional = (prop.nullable && (this.options.forceUndefined || prop.optional)) ? '?' : (useDefault ? '' : '!');
|
|
233
230
|
let ret = `${propName}${optional}: `;
|
|
234
|
-
const isArray = prop.array && (prop.kind ===
|
|
231
|
+
const isArray = prop.array && (prop.kind === ReferenceKind.EMBEDDED || prop.enum);
|
|
235
232
|
const complexType = isArray ? `${propType}[]` : propType;
|
|
236
233
|
let wrappedType = prop.ref
|
|
237
234
|
? `${this.referenceCoreImport('Ref')}<${complexType}${(isScalar && prop.nullable && !this.options.forceUndefined) ? ' | null' : ''}>`
|
|
@@ -250,7 +247,7 @@ class SourceFile {
|
|
|
250
247
|
}
|
|
251
248
|
if (prop.enum && typeof prop.default === 'string') {
|
|
252
249
|
const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
253
|
-
return `${padding}${ret} = ${propType}${
|
|
250
|
+
return `${padding}${ret} = ${propType}${identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
|
|
254
251
|
}
|
|
255
252
|
if (prop.fieldNames?.length > 1) {
|
|
256
253
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
@@ -272,13 +269,13 @@ class SourceFile {
|
|
|
272
269
|
const enumValues = prop.items;
|
|
273
270
|
for (const enumValue of enumValues) {
|
|
274
271
|
const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
275
|
-
ret += `${padding}${
|
|
272
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
|
|
276
273
|
}
|
|
277
274
|
ret += '}\n';
|
|
278
275
|
return ret;
|
|
279
276
|
}
|
|
280
277
|
serializeObject(options, wordwrap, spaces, level = 0) {
|
|
281
|
-
if (typeof wordwrap === 'number' && !Object.hasOwn(options,
|
|
278
|
+
if (typeof wordwrap === 'number' && !Object.hasOwn(options, Config)) {
|
|
282
279
|
const res = this.serializeObject(options, undefined, undefined, level);
|
|
283
280
|
if (res.length <= wordwrap) {
|
|
284
281
|
return res;
|
|
@@ -292,7 +289,7 @@ class SourceFile {
|
|
|
292
289
|
}
|
|
293
290
|
const entries = Object.entries(options);
|
|
294
291
|
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries.map(([opt, val]) => {
|
|
295
|
-
const key =
|
|
292
|
+
const key = identifierRegex.test(opt) ? opt : this.quote(opt);
|
|
296
293
|
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
294
|
}).join(sep)}${doIndent ? `${entries.length > 0 ? ',\n' : ''}${' '.repeat(spaces + (level * 2))}` : ' '}}`;
|
|
298
295
|
}
|
|
@@ -355,16 +352,16 @@ class SourceFile {
|
|
|
355
352
|
const padding = ' '.repeat(padLeft);
|
|
356
353
|
const options = {};
|
|
357
354
|
let decorator = `@${this.referenceCoreImport(this.getDecoratorType(prop))}`;
|
|
358
|
-
if (prop.kind ===
|
|
355
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
359
356
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
360
357
|
}
|
|
361
|
-
else if (prop.kind ===
|
|
358
|
+
else if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
362
359
|
this.getOneToManyDecoratorOptions(options, prop);
|
|
363
360
|
}
|
|
364
|
-
else if (prop.kind ===
|
|
361
|
+
else if (prop.kind === ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
|
|
365
362
|
this.getScalarPropertyDecoratorOptions(options, prop);
|
|
366
363
|
}
|
|
367
|
-
else if (prop.kind ===
|
|
364
|
+
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
368
365
|
this.getEmbeddedPropertyDeclarationOptions(options, prop);
|
|
369
366
|
}
|
|
370
367
|
else {
|
|
@@ -377,7 +374,7 @@ class SourceFile {
|
|
|
377
374
|
if (prop.formula) {
|
|
378
375
|
decoratorArgs.push(`${prop.formula}`);
|
|
379
376
|
}
|
|
380
|
-
if (
|
|
377
|
+
if (Utils.hasObjectKeys(options)) {
|
|
381
378
|
decoratorArgs.push(`${this.serializeObject(options)}`);
|
|
382
379
|
}
|
|
383
380
|
return `${decorator}(${decoratorArgs.join(', ')})\n`;
|
|
@@ -392,7 +389,7 @@ class SourceFile {
|
|
|
392
389
|
options[type] = (propType === true || defaultName === propType) ? 'true' : this.quote(propType);
|
|
393
390
|
const expected = {
|
|
394
391
|
index: this.platform.indexForeignKeys(),
|
|
395
|
-
unique: prop.kind ===
|
|
392
|
+
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
396
393
|
};
|
|
397
394
|
if (expected[type] && options[type] === 'true') {
|
|
398
395
|
delete options[type];
|
|
@@ -431,7 +428,7 @@ class SourceFile {
|
|
|
431
428
|
if (!prop.mappedBy && (prop.nullable || prop.customTypes?.[0]?.prop?.nullable)) {
|
|
432
429
|
options.nullable = true;
|
|
433
430
|
}
|
|
434
|
-
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind ===
|
|
431
|
+
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
435
432
|
options.primary = true;
|
|
436
433
|
}
|
|
437
434
|
['persist', 'hydrate', 'trackChanges']
|
|
@@ -449,7 +446,7 @@ class SourceFile {
|
|
|
449
446
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
450
447
|
.filter(key => prop[key])
|
|
451
448
|
.forEach(key => options[key] = true);
|
|
452
|
-
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !==
|
|
449
|
+
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
453
450
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
454
451
|
}
|
|
455
452
|
if (typeof prop.comment === 'string') {
|
|
@@ -461,7 +458,7 @@ class SourceFile {
|
|
|
461
458
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
462
459
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
463
460
|
}
|
|
464
|
-
else if (!(typeof prop.default === 'undefined' || prop.default === null) && (prop.ref || (!prop.enum && (typeof prop.kind === 'undefined' || prop.kind ===
|
|
461
|
+
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
462
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
466
463
|
}
|
|
467
464
|
}
|
|
@@ -482,7 +479,7 @@ class SourceFile {
|
|
|
482
479
|
return this.propTypeBreakdowns.get(prop);
|
|
483
480
|
}
|
|
484
481
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
485
|
-
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
482
|
+
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType)
|
|
486
483
|
? this.platform.getMappedType(prop.columnTypes[0])
|
|
487
484
|
: mappedDeclaredType));
|
|
488
485
|
const rawType = mappedRawType.runtimeType;
|
|
@@ -551,7 +548,7 @@ class SourceFile {
|
|
|
551
548
|
? mappedColumnType
|
|
552
549
|
: this.platform.getMappedType(prop.runtimeType);
|
|
553
550
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
554
|
-
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
551
|
+
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType;
|
|
555
552
|
if (isTypeStringMissingFromMap) {
|
|
556
553
|
this.entityImports.add(prop.type);
|
|
557
554
|
options.type = prop.type;
|
|
@@ -574,7 +571,7 @@ class SourceFile {
|
|
|
574
571
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
575
572
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
576
573
|
const needsExplicitColumnType = () => {
|
|
577
|
-
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof
|
|
574
|
+
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
578
575
|
return true;
|
|
579
576
|
}
|
|
580
577
|
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !== this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
@@ -594,8 +591,8 @@ class SourceFile {
|
|
|
594
591
|
assign('length');
|
|
595
592
|
}
|
|
596
593
|
// 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
|
|
594
|
+
/* v8 ignore next 4 */
|
|
595
|
+
if (mappedColumnType instanceof DecimalType && !options.columnType) {
|
|
599
596
|
assign('precision');
|
|
600
597
|
assign('scale');
|
|
601
598
|
}
|
|
@@ -713,19 +710,19 @@ class SourceFile {
|
|
|
713
710
|
}
|
|
714
711
|
}
|
|
715
712
|
getDecoratorType(prop) {
|
|
716
|
-
if (prop.kind ===
|
|
713
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
717
714
|
return 'OneToOne';
|
|
718
715
|
}
|
|
719
|
-
if (prop.kind ===
|
|
716
|
+
if (prop.kind === ReferenceKind.MANY_TO_ONE) {
|
|
720
717
|
return 'ManyToOne';
|
|
721
718
|
}
|
|
722
|
-
if (prop.kind ===
|
|
719
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
723
720
|
return 'OneToMany';
|
|
724
721
|
}
|
|
725
|
-
if (prop.kind ===
|
|
722
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
726
723
|
return 'ManyToMany';
|
|
727
724
|
}
|
|
728
|
-
if (prop.kind ===
|
|
725
|
+
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
729
726
|
return 'Embedded';
|
|
730
727
|
}
|
|
731
728
|
if (prop.enum) {
|
|
@@ -746,4 +743,3 @@ class SourceFile {
|
|
|
746
743
|
: identifier;
|
|
747
744
|
}
|
|
748
745
|
}
|
|
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.3",
|
|
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",
|
|
@@ -49,7 +41,7 @@
|
|
|
49
41
|
"node": ">= 22.11.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/knex": "7.0.0-dev.
|
|
62
|
-
"fs-extra": "11.3.0"
|
|
53
|
+
"@mikro-orm/knex": "7.0.0-dev.3"
|
|
63
54
|
},
|
|
64
55
|
"devDependencies": {
|
|
65
56
|
"@mikro-orm/core": "^6.4.5"
|
|
66
57
|
},
|
|
67
58
|
"peerDependencies": {
|
|
68
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.3"
|
|
69
60
|
}
|
|
70
61
|
}
|
package/index.mjs
DELETED