@mikro-orm/entity-generator 7.0.0-dev.0 → 7.0.0-dev.10
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.d.ts +3 -3
- package/SourceFile.js +49 -46
- package/index.d.ts +1 -1
- package/index.js +1 -17
- package/package.json +7 -16
- 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.d.ts
CHANGED
|
@@ -12,8 +12,8 @@ export declare class SourceFile {
|
|
|
12
12
|
protected readonly entityImports: Set<string>;
|
|
13
13
|
constructor(meta: EntityMetadata, namingStrategy: NamingStrategy, platform: Platform, options: GenerateOptions);
|
|
14
14
|
generate(): string;
|
|
15
|
-
protected getIndexOptions(index: EntityMetadata['indexes'][number], isAtEntityLevel?: boolean): IndexOptions<Dictionary>;
|
|
16
|
-
protected getUniqueOptions(index: EntityMetadata['uniques'][number], isAtEntityLevel?: boolean): UniqueOptions<Dictionary>;
|
|
15
|
+
protected getIndexOptions(index: EntityMetadata['indexes'][number], isAtEntityLevel?: boolean): IndexOptions<Dictionary, string>;
|
|
16
|
+
protected getUniqueOptions(index: EntityMetadata['uniques'][number], isAtEntityLevel?: boolean): UniqueOptions<Dictionary, string>;
|
|
17
17
|
protected generateImports(): string;
|
|
18
18
|
protected getEntityClass(classBody: string): string;
|
|
19
19
|
getBaseName(extension?: string): string;
|
|
@@ -23,7 +23,7 @@ export declare class SourceFile {
|
|
|
23
23
|
protected serializeObject(options: {}, wordwrap?: number, spaces?: number, level?: number): string;
|
|
24
24
|
protected serializeValue(val: unknown, wordwrap?: number, spaces?: number, level?: number): unknown;
|
|
25
25
|
protected getEntityDeclOptions(): EntityOptions<unknown>;
|
|
26
|
-
protected getEmbeddableDeclOptions(): EmbeddableOptions
|
|
26
|
+
protected getEmbeddableDeclOptions(): EmbeddableOptions<unknown>;
|
|
27
27
|
private getCollectionDecl;
|
|
28
28
|
private getPropertyDecorator;
|
|
29
29
|
protected getPropertyIndexes(prop: EntityProperty, options: Dictionary): string[];
|
package/SourceFile.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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 { inspect } from 'node:util';
|
|
4
|
+
import { POSSIBLE_TYPE_IMPORTS } from './CoreImportsHelper.js';
|
|
7
5
|
/**
|
|
8
6
|
* @see https://github.com/tc39/proposal-regexp-unicode-property-escapes#other-examples
|
|
9
7
|
*/
|
|
10
|
-
|
|
11
|
-
const primitivesAndLibs = [...
|
|
12
|
-
class SourceFile {
|
|
8
|
+
export const identifierRegex = /^(?:[$_\p{ID_Start}])(?:[$\u200C\u200D\p{ID_Continue}])*$/u;
|
|
9
|
+
const primitivesAndLibs = [...SCALAR_TYPES, 'bigint', 'Uint8Array', 'unknown', 'object', 'any'];
|
|
10
|
+
export class SourceFile {
|
|
13
11
|
meta;
|
|
14
12
|
namingStrategy;
|
|
15
13
|
platform;
|
|
@@ -27,11 +25,11 @@ class SourceFile {
|
|
|
27
25
|
if (this.meta.embeddable || this.meta.collection) {
|
|
28
26
|
if (this.meta.embeddable) {
|
|
29
27
|
const options = this.getEmbeddableDeclOptions();
|
|
30
|
-
ret += `@${this.referenceCoreImport('Embeddable')}(${
|
|
28
|
+
ret += `@${this.referenceCoreImport('Embeddable')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
31
29
|
}
|
|
32
30
|
else {
|
|
33
31
|
const options = this.getEntityDeclOptions();
|
|
34
|
-
ret += `@${this.referenceCoreImport('Entity')}(${
|
|
32
|
+
ret += `@${this.referenceCoreImport('Entity')}(${Utils.hasObjectKeys(options) ? this.serializeObject(options) : ''})\n`;
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
for (const index of this.meta.indexes) {
|
|
@@ -105,7 +103,7 @@ class SourceFile {
|
|
|
105
103
|
indexOpt.expression = this.quote(index.expression);
|
|
106
104
|
}
|
|
107
105
|
if (isAtEntityLevel && index.properties) {
|
|
108
|
-
indexOpt.properties =
|
|
106
|
+
indexOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
109
107
|
}
|
|
110
108
|
return indexOpt;
|
|
111
109
|
}
|
|
@@ -118,7 +116,7 @@ class SourceFile {
|
|
|
118
116
|
uniqueOpt.expression = this.quote(index.expression);
|
|
119
117
|
}
|
|
120
118
|
if (isAtEntityLevel && index.properties) {
|
|
121
|
-
uniqueOpt.properties =
|
|
119
|
+
uniqueOpt.properties = Utils.asArray(index.properties).map(prop => this.quote('' + prop));
|
|
122
120
|
}
|
|
123
121
|
if (index.deferMode) {
|
|
124
122
|
uniqueOpt.deferMode = `${this.referenceCoreImport('DeferMode')}.INITIALLY_${index.deferMode.toUpperCase()}`;
|
|
@@ -129,7 +127,7 @@ class SourceFile {
|
|
|
129
127
|
const imports = new Set();
|
|
130
128
|
if (this.coreImports.size > 0) {
|
|
131
129
|
imports.add(`import { ${([...this.coreImports].sort().map(t => {
|
|
132
|
-
let ret =
|
|
130
|
+
let ret = POSSIBLE_TYPE_IMPORTS.includes(t) ? `type ${t}` : t;
|
|
133
131
|
if (this.options.coreImportsPrefix) {
|
|
134
132
|
const resolvedIdentifier = `${this.options.coreImportsPrefix}${t}`;
|
|
135
133
|
ret += ` as ${resolvedIdentifier}`;
|
|
@@ -138,8 +136,8 @@ class SourceFile {
|
|
|
138
136
|
}).join(', '))} } from '@mikro-orm/core';`);
|
|
139
137
|
}
|
|
140
138
|
const extension = this.options.esmImport ? '.js' : '';
|
|
141
|
-
const { dir, base } =
|
|
142
|
-
const basePath =
|
|
139
|
+
const { dir, base } = parse(`${this.options.path ?? '.'}/${this.getBaseName()}`);
|
|
140
|
+
const basePath = relative(dir, this.options.path ?? '.') || '.';
|
|
143
141
|
(this.options.extraImports?.(basePath, base) ?? []).forEach(v => this.entityImports.add(v));
|
|
144
142
|
const entityImports = [...this.entityImports].filter(e => e !== this.meta.className);
|
|
145
143
|
entityImports.sort().forEach(entity => {
|
|
@@ -166,7 +164,7 @@ class SourceFile {
|
|
|
166
164
|
imports.add(`import { ${entity} } from ${this.quote(file.path)};`);
|
|
167
165
|
return;
|
|
168
166
|
}
|
|
169
|
-
imports.add(`import { ${
|
|
167
|
+
imports.add(`import { ${identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
|
|
170
168
|
});
|
|
171
169
|
return Array.from(imports.values()).join('\n');
|
|
172
170
|
}
|
|
@@ -191,20 +189,20 @@ class SourceFile {
|
|
|
191
189
|
}
|
|
192
190
|
quote(val) {
|
|
193
191
|
const backtick = val.startsWith(`'`) || val.includes('\n');
|
|
194
|
-
/*
|
|
192
|
+
/* v8 ignore next */
|
|
195
193
|
return backtick ? `\`${val.replaceAll('`', '\\``')}\`` : `'${val.replaceAll(`'`, `\\'`)}'`;
|
|
196
194
|
}
|
|
197
195
|
getPropertyDefinition(prop, padLeft) {
|
|
198
196
|
const padding = ' '.repeat(padLeft);
|
|
199
|
-
const propName =
|
|
197
|
+
const propName = identifierRegex.test(prop.name) ? prop.name : this.quote(prop.name);
|
|
200
198
|
let hiddenType = '';
|
|
201
199
|
if (prop.hidden) {
|
|
202
200
|
hiddenType += ` & ${this.referenceCoreImport('Hidden')}`;
|
|
203
201
|
}
|
|
204
|
-
if ([
|
|
202
|
+
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
205
203
|
return `${padding}${propName}${hiddenType ? `: ${this.referenceCoreImport('Collection')}<${prop.type}>${hiddenType}` : ''} = new ${this.referenceCoreImport('Collection')}<${prop.type}>(this);\n`;
|
|
206
204
|
}
|
|
207
|
-
const isScalar = typeof prop.kind === 'undefined' || prop.kind ===
|
|
205
|
+
const isScalar = typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR;
|
|
208
206
|
let breakdownOfIType;
|
|
209
207
|
const propType = prop.mapToPk
|
|
210
208
|
? (() => {
|
|
@@ -231,7 +229,7 @@ class SourceFile {
|
|
|
231
229
|
const useDefault = hasUsableNullDefault || (!(typeof prop.default === 'undefined' || prop.default === null) && propType !== 'unknown' && typeof breakdownOfIType === 'undefined');
|
|
232
230
|
const optional = (prop.nullable && (this.options.forceUndefined || prop.optional)) ? '?' : (useDefault ? '' : '!');
|
|
233
231
|
let ret = `${propName}${optional}: `;
|
|
234
|
-
const isArray = prop.array && (prop.kind ===
|
|
232
|
+
const isArray = prop.array && (prop.kind === ReferenceKind.EMBEDDED || prop.enum);
|
|
235
233
|
const complexType = isArray ? `${propType}[]` : propType;
|
|
236
234
|
let wrappedType = prop.ref
|
|
237
235
|
? `${this.referenceCoreImport('Ref')}<${complexType}${(isScalar && prop.nullable && !this.options.forceUndefined) ? ' | null' : ''}>`
|
|
@@ -250,7 +248,7 @@ class SourceFile {
|
|
|
250
248
|
}
|
|
251
249
|
if (prop.enum && typeof prop.default === 'string') {
|
|
252
250
|
const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
253
|
-
return `${padding}${ret} = ${propType}${
|
|
251
|
+
return `${padding}${ret} = ${propType}${identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
|
|
254
252
|
}
|
|
255
253
|
if (prop.fieldNames?.length > 1) {
|
|
256
254
|
// TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
|
|
@@ -272,13 +270,13 @@ class SourceFile {
|
|
|
272
270
|
const enumValues = prop.items;
|
|
273
271
|
for (const enumValue of enumValues) {
|
|
274
272
|
const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, prop.fieldNames[0], this.meta.collection, this.meta.schema);
|
|
275
|
-
ret += `${padding}${
|
|
273
|
+
ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
|
|
276
274
|
}
|
|
277
275
|
ret += '}\n';
|
|
278
276
|
return ret;
|
|
279
277
|
}
|
|
280
278
|
serializeObject(options, wordwrap, spaces, level = 0) {
|
|
281
|
-
if (typeof wordwrap === 'number' && !Object.hasOwn(options,
|
|
279
|
+
if (typeof wordwrap === 'number' && !Object.hasOwn(options, Config)) {
|
|
282
280
|
const res = this.serializeObject(options, undefined, undefined, level);
|
|
283
281
|
if (res.length <= wordwrap) {
|
|
284
282
|
return res;
|
|
@@ -292,7 +290,7 @@ class SourceFile {
|
|
|
292
290
|
}
|
|
293
291
|
const entries = Object.entries(options);
|
|
294
292
|
return `{${doIndent ? `\n${' '.repeat(spaces)}` : ' '}${entries.map(([opt, val]) => {
|
|
295
|
-
const key =
|
|
293
|
+
const key = identifierRegex.test(opt) ? opt : this.quote(opt);
|
|
296
294
|
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
295
|
}).join(sep)}${doIndent ? `${entries.length > 0 ? ',\n' : ''}${' '.repeat(spaces + (level * 2))}` : ' '}}`;
|
|
298
296
|
}
|
|
@@ -355,16 +353,16 @@ class SourceFile {
|
|
|
355
353
|
const padding = ' '.repeat(padLeft);
|
|
356
354
|
const options = {};
|
|
357
355
|
let decorator = `@${this.referenceCoreImport(this.getDecoratorType(prop))}`;
|
|
358
|
-
if (prop.kind ===
|
|
356
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
359
357
|
this.getManyToManyDecoratorOptions(options, prop);
|
|
360
358
|
}
|
|
361
|
-
else if (prop.kind ===
|
|
359
|
+
else if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
362
360
|
this.getOneToManyDecoratorOptions(options, prop);
|
|
363
361
|
}
|
|
364
|
-
else if (prop.kind ===
|
|
362
|
+
else if (prop.kind === ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
|
|
365
363
|
this.getScalarPropertyDecoratorOptions(options, prop);
|
|
366
364
|
}
|
|
367
|
-
else if (prop.kind ===
|
|
365
|
+
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
368
366
|
this.getEmbeddedPropertyDeclarationOptions(options, prop);
|
|
369
367
|
}
|
|
370
368
|
else {
|
|
@@ -377,7 +375,7 @@ class SourceFile {
|
|
|
377
375
|
if (prop.formula) {
|
|
378
376
|
decoratorArgs.push(`${prop.formula}`);
|
|
379
377
|
}
|
|
380
|
-
if (
|
|
378
|
+
if (Utils.hasObjectKeys(options)) {
|
|
381
379
|
decoratorArgs.push(`${this.serializeObject(options)}`);
|
|
382
380
|
}
|
|
383
381
|
return `${decorator}(${decoratorArgs.join(', ')})\n`;
|
|
@@ -392,7 +390,7 @@ class SourceFile {
|
|
|
392
390
|
options[type] = (propType === true || defaultName === propType) ? 'true' : this.quote(propType);
|
|
393
391
|
const expected = {
|
|
394
392
|
index: this.platform.indexForeignKeys(),
|
|
395
|
-
unique: prop.kind ===
|
|
393
|
+
unique: prop.kind === ReferenceKind.ONE_TO_ONE,
|
|
396
394
|
};
|
|
397
395
|
if (expected[type] && options[type] === 'true') {
|
|
398
396
|
delete options[type];
|
|
@@ -431,7 +429,7 @@ class SourceFile {
|
|
|
431
429
|
if (!prop.mappedBy && (prop.nullable || prop.customTypes?.[0]?.prop?.nullable)) {
|
|
432
430
|
options.nullable = true;
|
|
433
431
|
}
|
|
434
|
-
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind ===
|
|
432
|
+
if (prop.primary && (prop.enum || !(typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR))) {
|
|
435
433
|
options.primary = true;
|
|
436
434
|
}
|
|
437
435
|
['persist', 'hydrate', 'trackChanges']
|
|
@@ -449,7 +447,7 @@ class SourceFile {
|
|
|
449
447
|
['hidden', 'version', 'concurrencyCheck', 'eager', 'lazy', 'orphanRemoval']
|
|
450
448
|
.filter(key => prop[key])
|
|
451
449
|
.forEach(key => options[key] = true);
|
|
452
|
-
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !==
|
|
450
|
+
if (prop.cascade && (prop.cascade.length !== 1 || prop.cascade[0] !== Cascade.PERSIST)) {
|
|
453
451
|
options.cascade = `[${prop.cascade.map(value => `${this.referenceCoreImport('Cascade')}.${value.toUpperCase()}`).join(', ')}]`;
|
|
454
452
|
}
|
|
455
453
|
if (typeof prop.comment === 'string') {
|
|
@@ -461,7 +459,7 @@ class SourceFile {
|
|
|
461
459
|
prop.defaultRaw !== (typeof prop.default === 'string' ? this.quote(prop.default) : `${prop.default}`)) {
|
|
462
460
|
options.defaultRaw = `\`${prop.defaultRaw}\``;
|
|
463
461
|
}
|
|
464
|
-
else if (!(typeof prop.default === 'undefined' || prop.default === null) && (prop.ref || (!prop.enum && (typeof prop.kind === 'undefined' || prop.kind ===
|
|
462
|
+
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
463
|
options.default = typeof prop.default === 'string' ? this.quote(prop.default) : prop.default;
|
|
466
464
|
}
|
|
467
465
|
}
|
|
@@ -482,7 +480,7 @@ class SourceFile {
|
|
|
482
480
|
return this.propTypeBreakdowns.get(prop);
|
|
483
481
|
}
|
|
484
482
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
485
|
-
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
483
|
+
const mappedRawType = (prop.customTypes?.[0] ?? ((prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType)
|
|
486
484
|
? this.platform.getMappedType(prop.columnTypes[0])
|
|
487
485
|
: mappedDeclaredType));
|
|
488
486
|
const rawType = mappedRawType.runtimeType;
|
|
@@ -551,7 +549,7 @@ class SourceFile {
|
|
|
551
549
|
? mappedColumnType
|
|
552
550
|
: this.platform.getMappedType(prop.runtimeType);
|
|
553
551
|
const mappedDeclaredType = this.platform.getMappedType(prop.type);
|
|
554
|
-
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof
|
|
552
|
+
const isTypeStringMissingFromMap = prop.type !== 'unknown' && mappedDeclaredType instanceof UnknownType;
|
|
555
553
|
if (isTypeStringMissingFromMap) {
|
|
556
554
|
this.entityImports.add(prop.type);
|
|
557
555
|
options.type = prop.type;
|
|
@@ -574,7 +572,7 @@ class SourceFile {
|
|
|
574
572
|
const columnTypeFromMappedColumnType = mappedColumnType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
575
573
|
const columnTypeFromMappedDeclaredType = mappedDeclaredType.getColumnType({ ...prop, autoincrement: false }, this.platform);
|
|
576
574
|
const needsExplicitColumnType = () => {
|
|
577
|
-
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof
|
|
575
|
+
if (isTypeStringMissingFromMap || [mappedRuntimeType, mappedColumnType, columnTypeFromMappedDeclaredType].some(t => t instanceof UnknownType)) {
|
|
578
576
|
return true;
|
|
579
577
|
}
|
|
580
578
|
if (this.platform.normalizeColumnType(prop.columnTypes[0], prop) !== this.platform.normalizeColumnType(columnTypeFromMappedColumnType, prop)) {
|
|
@@ -594,8 +592,8 @@ class SourceFile {
|
|
|
594
592
|
assign('length');
|
|
595
593
|
}
|
|
596
594
|
// 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
|
|
595
|
+
/* v8 ignore next 4 */
|
|
596
|
+
if (mappedColumnType instanceof DecimalType && !options.columnType) {
|
|
599
597
|
assign('precision');
|
|
600
598
|
assign('scale');
|
|
601
599
|
}
|
|
@@ -621,6 +619,9 @@ class SourceFile {
|
|
|
621
619
|
getManyToManyDecoratorOptions(options, prop) {
|
|
622
620
|
this.entityImports.add(prop.type);
|
|
623
621
|
options.entity = `() => ${prop.type}`;
|
|
622
|
+
if (prop.orderBy) {
|
|
623
|
+
options.orderBy = inspect(prop.orderBy);
|
|
624
|
+
}
|
|
624
625
|
if (prop.mappedBy) {
|
|
625
626
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
626
627
|
return;
|
|
@@ -655,6 +656,9 @@ class SourceFile {
|
|
|
655
656
|
this.entityImports.add(prop.type);
|
|
656
657
|
options.entity = `() => ${prop.type}`;
|
|
657
658
|
options.mappedBy = this.quote(prop.mappedBy);
|
|
659
|
+
if (prop.orderBy) {
|
|
660
|
+
options.orderBy = inspect(prop.orderBy);
|
|
661
|
+
}
|
|
658
662
|
}
|
|
659
663
|
getEmbeddedPropertyDeclarationOptions(options, prop) {
|
|
660
664
|
this.entityImports.add(prop.type);
|
|
@@ -713,19 +717,19 @@ class SourceFile {
|
|
|
713
717
|
}
|
|
714
718
|
}
|
|
715
719
|
getDecoratorType(prop) {
|
|
716
|
-
if (prop.kind ===
|
|
720
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
717
721
|
return 'OneToOne';
|
|
718
722
|
}
|
|
719
|
-
if (prop.kind ===
|
|
723
|
+
if (prop.kind === ReferenceKind.MANY_TO_ONE) {
|
|
720
724
|
return 'ManyToOne';
|
|
721
725
|
}
|
|
722
|
-
if (prop.kind ===
|
|
726
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
723
727
|
return 'OneToMany';
|
|
724
728
|
}
|
|
725
|
-
if (prop.kind ===
|
|
729
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
726
730
|
return 'ManyToMany';
|
|
727
731
|
}
|
|
728
|
-
if (prop.kind ===
|
|
732
|
+
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
729
733
|
return 'Embedded';
|
|
730
734
|
}
|
|
731
735
|
if (prop.enum) {
|
|
@@ -746,4 +750,3 @@ class SourceFile {
|
|
|
746
750
|
: identifier;
|
|
747
751
|
}
|
|
748
752
|
}
|
|
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.10",
|
|
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.10"
|
|
63
54
|
},
|
|
64
55
|
"devDependencies": {
|
|
65
|
-
"@mikro-orm/core": "^6.4.
|
|
56
|
+
"@mikro-orm/core": "^6.4.13"
|
|
66
57
|
},
|
|
67
58
|
"peerDependencies": {
|
|
68
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.10"
|
|
69
60
|
}
|
|
70
61
|
}
|
package/index.mjs
DELETED