@mikro-orm/entity-generator 6.5.10-dev.9 → 6.6.0

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.
@@ -0,0 +1,5 @@
1
+ import { EntitySchemaSourceFile } from './EntitySchemaSourceFile';
2
+ export declare class DefineEntitySourceFile extends EntitySchemaSourceFile {
3
+ generate(): string;
4
+ private getPropertyBuilder;
5
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefineEntitySourceFile = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ const EntitySchemaSourceFile_1 = require("./EntitySchemaSourceFile");
6
+ class DefineEntitySourceFile extends EntitySchemaSourceFile_1.EntitySchemaSourceFile {
7
+ generate() {
8
+ const enumDefinitions = [];
9
+ for (const prop of Object.values(this.meta.properties)) {
10
+ if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR)) {
11
+ const def = this.getEnumClassDefinition(prop, 2);
12
+ if (def.length) {
13
+ enumDefinitions.push(def);
14
+ }
15
+ }
16
+ }
17
+ let ret = '';
18
+ if (!this.options.inferEntityType) {
19
+ ret += this.generateClassDefinition() + '\n';
20
+ }
21
+ if (enumDefinitions.length) {
22
+ ret += enumDefinitions.join('\n') + '\n';
23
+ }
24
+ const entitySchemaOptions = {};
25
+ if (this.options.inferEntityType) {
26
+ entitySchemaOptions.name = this.quote(this.meta.className);
27
+ if (this.meta.compositePK) {
28
+ entitySchemaOptions.primaryKeys = this.meta.getPrimaryProps().map(p => this.quote(p.name));
29
+ }
30
+ }
31
+ else {
32
+ entitySchemaOptions.class = this.meta.className;
33
+ }
34
+ Object.assign(entitySchemaOptions, (this.meta.embeddable ? this.getEmbeddableDeclOptions() : (this.meta.collection ? this.getEntityDeclOptions() : {})));
35
+ const nameSuffix = this.options.inferEntityType ? '' : 'Schema';
36
+ const declLine = `export const ${this.meta.className + nameSuffix} = ${this.referenceCoreImport('defineEntity')}(`;
37
+ ret += declLine;
38
+ if (this.meta.indexes.length > 0) {
39
+ entitySchemaOptions.indexes = this.meta.indexes.map(index => this.getIndexOptions(index));
40
+ }
41
+ if (this.meta.uniques.length > 0) {
42
+ entitySchemaOptions.uniques = this.meta.uniques.map(index => this.getUniqueOptions(index));
43
+ }
44
+ entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyBuilder(prop)]));
45
+ // Force top level and properties to be indented, regardless of line length
46
+ entitySchemaOptions[core_1.Config] = true;
47
+ entitySchemaOptions.properties[core_1.Config] = true;
48
+ ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
49
+ ret += ');\n';
50
+ if (this.options.inferEntityType) {
51
+ ret += `\nexport interface I${this.meta.className} extends ${this.referenceCoreImport('InferEntity')}<typeof ${this.meta.className}> {}\n`;
52
+ }
53
+ ret = `${this.generateImports()}\n\n${ret}`;
54
+ return ret;
55
+ }
56
+ getPropertyBuilder(prop) {
57
+ const options = this.getPropertyOptions(prop, false);
58
+ const p = this.referenceCoreImport('p');
59
+ let builder = '';
60
+ switch (prop.kind) {
61
+ case core_1.ReferenceKind.ONE_TO_ONE:
62
+ builder += `() => ${p}.oneToOne(${prop.type})`;
63
+ break;
64
+ case core_1.ReferenceKind.ONE_TO_MANY:
65
+ builder += `() => ${p}.oneToMany(${prop.type})`;
66
+ break;
67
+ case core_1.ReferenceKind.MANY_TO_ONE:
68
+ builder += `() => ${p}.manyToOne(${prop.type})`;
69
+ break;
70
+ case core_1.ReferenceKind.MANY_TO_MANY:
71
+ builder += `() => ${p}.manyToMany(${prop.type})`;
72
+ break;
73
+ case core_1.ReferenceKind.EMBEDDED:
74
+ builder += `() => ${p}.embedded(${prop.type})`;
75
+ break;
76
+ case core_1.ReferenceKind.SCALAR:
77
+ default: {
78
+ if (options.type && !(options.type in core_1.types)) {
79
+ builder += `${p}.type(${options.type})`;
80
+ }
81
+ else {
82
+ builder += options.type ? `${p}.${options.type}()` : p;
83
+ }
84
+ }
85
+ }
86
+ const simpleOptions = new Set([
87
+ 'primary', 'ref', 'nullable', 'array', 'object', 'mapToPk', 'hidden', 'concurrencyCheck', 'lazy', 'eager',
88
+ 'orphanRemoval', 'version', 'unsigned', 'returning', 'createForeignKeyConstraint', 'fixedOrder', 'owner',
89
+ 'getter', 'setter', 'unique', 'index', 'hydrate', 'persist', 'autoincrement',
90
+ ]);
91
+ const skipOptions = new Set(['entity', 'kind', 'type', 'items']);
92
+ const spreadOptions = new Set([
93
+ 'fieldNames', 'joinColumns', 'inverseJoinColumns', 'referencedColumnNames', 'ownColumns', 'columnTypes',
94
+ 'cascade', 'ignoreSchemaChanges', 'customOrder', 'groups', 'where', 'orderBy',
95
+ ]);
96
+ const rename = {
97
+ fieldName: 'name',
98
+ };
99
+ for (const key of Object.keys(options)) {
100
+ if (typeof options[key] === 'undefined' || skipOptions.has(key)) {
101
+ continue;
102
+ }
103
+ const method = rename[key] ?? key;
104
+ const params = simpleOptions.has(key) && options[key] === true ? '' : options[key];
105
+ builder += `.${method}`;
106
+ if (key === 'enum') {
107
+ builder += `(${options.items})`;
108
+ }
109
+ else if (spreadOptions.has(key) && typeof params === 'string' && params.startsWith('[')) {
110
+ builder += `(${params.slice(1, -1)})`;
111
+ }
112
+ else {
113
+ builder += `(${params})`;
114
+ }
115
+ }
116
+ return builder;
117
+ }
118
+ }
119
+ exports.DefineEntitySourceFile = DefineEntitySourceFile;
@@ -5,7 +5,9 @@ const core_1 = require("@mikro-orm/core");
5
5
  const knex_1 = require("@mikro-orm/knex");
6
6
  const node_path_1 = require("node:path");
7
7
  const fs_extra_1 = require("fs-extra");
8
+ const DefineEntitySourceFile_1 = require("./DefineEntitySourceFile");
8
9
  const EntitySchemaSourceFile_1 = require("./EntitySchemaSourceFile");
10
+ const NativeEnumSourceFile_1 = require("./NativeEnumSourceFile");
9
11
  const SourceFile_1 = require("./SourceFile");
10
12
  class EntityGenerator {
11
13
  em;
@@ -35,28 +37,43 @@ class EntityGenerator {
35
37
  const metadata = await this.getEntityMetadata(schema, options);
36
38
  const defaultPath = `${this.config.get('baseDir')}/generated-entities`;
37
39
  const baseDir = core_1.Utils.normalizePath(options.path ?? defaultPath);
40
+ this.sources.length = 0;
41
+ if (options.entitySchema) {
42
+ options.entityDefinition = 'entitySchema';
43
+ }
44
+ const map = {
45
+ defineEntity: DefineEntitySourceFile_1.DefineEntitySourceFile,
46
+ entitySchema: EntitySchemaSourceFile_1.EntitySchemaSourceFile,
47
+ decorators: SourceFile_1.SourceFile,
48
+ };
49
+ if (options.entityDefinition !== 'decorators') {
50
+ options.scalarTypeInDecorator = true;
51
+ }
38
52
  for (const meta of metadata) {
39
- if (!meta.pivotTable || options.outputPurePivotTables || this.referencedEntities.has(meta)) {
40
- if (options.entitySchema) {
41
- this.sources.push(new EntitySchemaSourceFile_1.EntitySchemaSourceFile(meta, this.namingStrategy, this.platform, { ...options, scalarTypeInDecorator: true }));
42
- }
43
- else {
44
- this.sources.push(new SourceFile_1.SourceFile(meta, this.namingStrategy, this.platform, options));
45
- }
53
+ if (meta.pivotTable && !options.outputPurePivotTables && !this.referencedEntities.has(meta)) {
54
+ continue;
46
55
  }
56
+ this.sources.push(new map[options.entityDefinition](meta, this.namingStrategy, this.platform, options));
47
57
  }
58
+ for (const nativeEnum of Object.values(schema.getNativeEnums())) {
59
+ this.sources.push(new NativeEnumSourceFile_1.NativeEnumSourceFile({}, this.namingStrategy, this.platform, options, nativeEnum));
60
+ }
61
+ const files = this.sources.map(file => [file.getBaseName(), file.generate()]);
48
62
  if (options.save) {
49
63
  await (0, fs_extra_1.ensureDir)(baseDir);
50
- await Promise.all(this.sources.map(async (file) => {
51
- const fileName = file.getBaseName();
52
- const fileDir = (0, node_path_1.dirname)(fileName);
53
- if (fileDir !== '.') {
54
- await (0, fs_extra_1.ensureDir)((0, node_path_1.join)(baseDir, fileDir));
55
- }
56
- return (0, fs_extra_1.writeFile)((0, node_path_1.join)(baseDir, fileName), file.generate(), { flush: true });
57
- }));
64
+ const promises = [];
65
+ for (const [fileName, data] of files) {
66
+ promises.push((async () => {
67
+ const fileDir = (0, node_path_1.dirname)(fileName);
68
+ if (fileDir !== '.') {
69
+ await (0, fs_extra_1.ensureDir)((0, node_path_1.join)(baseDir, fileDir));
70
+ }
71
+ await (0, fs_extra_1.writeFile)((0, node_path_1.join)(baseDir, fileName), data, { flush: true });
72
+ })());
73
+ }
74
+ await Promise.all(promises);
58
75
  }
59
- return this.sources.map(file => file.generate());
76
+ return files.map(([, data]) => data);
60
77
  }
61
78
  async getEntityMetadata(schema, options) {
62
79
  const metadata = schema.getTables()
@@ -2,7 +2,8 @@ import { type Dictionary, type EntityProperty } from '@mikro-orm/core';
2
2
  import { SourceFile } from './SourceFile';
3
3
  export declare class EntitySchemaSourceFile extends SourceFile {
4
4
  generate(): string;
5
- private getPropertyOptions;
5
+ protected generateClassDefinition(): string;
6
+ protected getPropertyOptions(prop: EntityProperty, quote?: boolean): Dictionary;
6
7
  protected getPropertyIndexesOptions(prop: EntityProperty, options: Dictionary): void;
7
- protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
8
+ protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty, quote?: boolean): void;
8
9
  }
@@ -5,21 +5,56 @@ const core_1 = require("@mikro-orm/core");
5
5
  const SourceFile_1 = require("./SourceFile");
6
6
  class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
7
7
  generate() {
8
+ const classDefinition = this.generateClassDefinition();
9
+ const enumDefinitions = [];
10
+ for (const prop of Object.values(this.meta.properties)) {
11
+ if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR)) {
12
+ const def = this.getEnumClassDefinition(prop, 2);
13
+ if (def.length) {
14
+ enumDefinitions.push(def);
15
+ }
16
+ }
17
+ }
18
+ let ret = classDefinition;
19
+ if (enumDefinitions.length) {
20
+ ret += '\n' + enumDefinitions.join('\n');
21
+ }
22
+ ret += `\n`;
23
+ const entitySchemaOptions = {
24
+ class: this.meta.className,
25
+ ...(this.meta.embeddable ? this.getEmbeddableDeclOptions() : (this.meta.collection ? this.getEntityDeclOptions() : {})),
26
+ };
27
+ const declLine = `export const ${this.meta.className}Schema = new ${this.referenceCoreImport('EntitySchema')}(`;
28
+ ret += declLine;
29
+ if (this.meta.indexes.length > 0) {
30
+ entitySchemaOptions.indexes = this.meta.indexes.map(index => this.getIndexOptions(index));
31
+ }
32
+ if (this.meta.uniques.length > 0) {
33
+ entitySchemaOptions.uniques = this.meta.uniques.map(index => this.getUniqueOptions(index));
34
+ }
35
+ entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyOptions(prop)]));
36
+ // Force top level and properties to be indented, regardless of line length
37
+ entitySchemaOptions[core_1.Config] = true;
38
+ entitySchemaOptions.properties[core_1.Config] = true;
39
+ ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
40
+ ret += ');\n';
41
+ ret = `${this.generateImports()}\n\n${ret}`;
42
+ return ret;
43
+ }
44
+ generateClassDefinition() {
8
45
  let classBody = '';
9
- if (this.meta.className === this.options.customBaseEntityName) {
46
+ if (!this.options.customBaseEntityName || this.meta.className === this.options.customBaseEntityName) {
10
47
  const defineConfigTypeSettings = {};
11
48
  defineConfigTypeSettings.forceObject = this.platform.getConfig().get('serialization').forceObject ?? false;
12
- classBody += `${' '.repeat(2)}[${this.referenceCoreImport('Config')}]?: ${this.referenceCoreImport('DefineConfig')}<${this.serializeObject(defineConfigTypeSettings)}>;\n`;
49
+ if (defineConfigTypeSettings.forceObject) {
50
+ classBody += `${' '.repeat(2)}[${this.referenceCoreImport('Config')}]?: ${this.referenceCoreImport('DefineConfig')}<${this.serializeObject(defineConfigTypeSettings)}>;\n`;
51
+ }
13
52
  }
14
- const enumDefinitions = [];
15
53
  const eagerProperties = [];
16
54
  const primaryProps = [];
17
55
  const props = [];
18
56
  for (const prop of Object.values(this.meta.properties)) {
19
57
  props.push(this.getPropertyDefinition(prop, 2));
20
- if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === core_1.ReferenceKind.SCALAR)) {
21
- enumDefinitions.push(this.getEnumClassDefinition(prop, 2));
22
- }
23
58
  if (prop.eager) {
24
59
  eagerProperties.push(prop);
25
60
  }
@@ -41,33 +76,9 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
41
76
  classBody += `${' '.repeat(2)}[${this.referenceCoreImport('EagerProps')}]?: ${eagerPropertyNames.join(' | ')};\n`;
42
77
  }
43
78
  classBody += `${props.join('')}`;
44
- let ret = this.getEntityClass(classBody);
45
- if (enumDefinitions.length) {
46
- ret += '\n' + enumDefinitions.join('\n');
47
- }
48
- ret += `\n`;
49
- const entitySchemaOptions = {
50
- class: this.meta.className,
51
- ...(this.meta.embeddable ? this.getEmbeddableDeclOptions() : (this.meta.collection ? this.getEntityDeclOptions() : {})),
52
- };
53
- const declLine = `export const ${this.meta.className}Schema = new ${this.referenceCoreImport('EntitySchema')}(`;
54
- ret += declLine;
55
- if (this.meta.indexes.length > 0) {
56
- entitySchemaOptions.indexes = this.meta.indexes.map(index => this.getIndexOptions(index));
57
- }
58
- if (this.meta.uniques.length > 0) {
59
- entitySchemaOptions.uniques = this.meta.uniques.map(index => this.getUniqueOptions(index));
60
- }
61
- entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyOptions(prop)]));
62
- // Force top level and properties to be indented, regardless of line length
63
- entitySchemaOptions[core_1.Config] = true;
64
- entitySchemaOptions.properties[core_1.Config] = true;
65
- ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
66
- ret += ');\n';
67
- ret = `${this.generateImports()}\n\n${ret}`;
68
- return ret;
79
+ return this.getEntityClass(classBody);
69
80
  }
70
- getPropertyOptions(prop) {
81
+ getPropertyOptions(prop, quote = true) {
71
82
  const options = {};
72
83
  if (prop.primary) {
73
84
  options.primary = true;
@@ -82,7 +93,7 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
82
93
  this.getOneToManyDecoratorOptions(options, prop);
83
94
  }
84
95
  else if (prop.kind === core_1.ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
85
- this.getScalarPropertyDecoratorOptions(options, prop);
96
+ this.getScalarPropertyDecoratorOptions(options, prop, quote);
86
97
  }
87
98
  else if (prop.kind === core_1.ReferenceKind.EMBEDDED) {
88
99
  this.getEmbeddedPropertyDeclarationOptions(options, prop);
@@ -126,15 +137,15 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
126
137
  processIndex('index');
127
138
  processIndex('unique');
128
139
  }
129
- getScalarPropertyDecoratorOptions(options, prop) {
140
+ getScalarPropertyDecoratorOptions(options, prop, quote = true) {
130
141
  if (prop.enum) {
131
142
  options.enum = true;
132
143
  options.items = `() => ${prop.runtimeType}`;
133
144
  }
134
145
  else {
135
- options.type = this.quote(prop.type);
146
+ options.type = quote ? this.quote(prop.type) : prop.type;
136
147
  }
137
- super.getScalarPropertyDecoratorOptions(options, prop);
148
+ super.getScalarPropertyDecoratorOptions(options, prop, quote);
138
149
  }
139
150
  }
140
151
  exports.EntitySchemaSourceFile = EntitySchemaSourceFile;
@@ -0,0 +1,16 @@
1
+ import type { EntityMetadata, GenerateOptions, NamingStrategy, Platform } from '@mikro-orm/core';
2
+ import { SourceFile } from './SourceFile';
3
+ export declare class NativeEnumSourceFile extends SourceFile {
4
+ protected readonly nativeEnum: {
5
+ name: string;
6
+ schema?: string;
7
+ items: string[];
8
+ };
9
+ constructor(meta: EntityMetadata, namingStrategy: NamingStrategy, platform: Platform, options: GenerateOptions, nativeEnum: {
10
+ name: string;
11
+ schema?: string;
12
+ items: string[];
13
+ });
14
+ generate(): string;
15
+ getBaseName(extension?: string): string;
16
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NativeEnumSourceFile = void 0;
4
+ const SourceFile_1 = require("./SourceFile");
5
+ class NativeEnumSourceFile extends SourceFile_1.SourceFile {
6
+ nativeEnum;
7
+ constructor(meta, namingStrategy, platform, options, nativeEnum) {
8
+ super(meta, namingStrategy, platform, options);
9
+ this.nativeEnum = nativeEnum;
10
+ }
11
+ generate() {
12
+ const enumClassName = this.namingStrategy.getEnumClassName(this.nativeEnum.name, undefined, this.nativeEnum.schema);
13
+ const enumTypeName = this.namingStrategy.getEnumTypeName(this.nativeEnum.name, undefined, this.nativeEnum.schema);
14
+ const padding = ' ';
15
+ const enumMode = this.options.enumMode;
16
+ const enumValues = this.nativeEnum.items;
17
+ if (enumMode === 'union-type') {
18
+ return `export type ${enumTypeName} = ${enumValues.map(item => this.quote(item)).join(' | ')};\n`;
19
+ }
20
+ let ret = '';
21
+ if (enumMode === 'dictionary') {
22
+ ret += `export const ${enumClassName} = {\n`;
23
+ }
24
+ else {
25
+ ret += `export enum ${enumClassName} {\n`;
26
+ }
27
+ for (const enumValue of enumValues) {
28
+ const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, this.nativeEnum.name, '', this.nativeEnum.schema);
29
+ if (enumMode === 'dictionary') {
30
+ ret += `${padding}${SourceFile_1.identifierRegex.test(enumName) ? enumName : this.quote(enumName)}: ${this.quote(enumValue)},\n`;
31
+ }
32
+ else {
33
+ ret += `${padding}${SourceFile_1.identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
34
+ }
35
+ }
36
+ if (enumMode === 'dictionary') {
37
+ ret += '} as const;\n';
38
+ }
39
+ else {
40
+ ret += '}\n';
41
+ }
42
+ if (enumMode === 'dictionary') {
43
+ ret += `\nexport type ${enumTypeName} = (typeof ${enumClassName})[keyof typeof ${enumClassName}];\n`;
44
+ }
45
+ return ret;
46
+ }
47
+ getBaseName(extension = '.ts') {
48
+ return `${this.options.fileName(this.nativeEnum.name)}${extension}`;
49
+ }
50
+ }
51
+ exports.NativeEnumSourceFile = NativeEnumSourceFile;
package/SourceFile.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare class SourceFile {
10
10
  protected readonly options: GenerateOptions;
11
11
  protected readonly coreImports: Set<string>;
12
12
  protected readonly entityImports: Set<string>;
13
+ protected readonly enumImports: Map<string, string[]>;
13
14
  constructor(meta: EntityMetadata, namingStrategy: NamingStrategy, platform: Platform, options: GenerateOptions);
14
15
  generate(): string;
15
16
  protected getIndexOptions(index: EntityMetadata['indexes'][number], isAtEntityLevel?: boolean): IndexOptions<Dictionary, string>;
@@ -30,7 +31,7 @@ export declare class SourceFile {
30
31
  protected getCommonDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
31
32
  private propTypeBreakdowns;
32
33
  private breakdownOfIType;
33
- protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
34
+ protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty, quote?: boolean): void;
34
35
  protected getManyToManyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
35
36
  protected getOneToManyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
36
37
  protected getEmbeddedPropertyDeclarationOptions(options: Dictionary, prop: EntityProperty): void;
package/SourceFile.js CHANGED
@@ -17,6 +17,7 @@ class SourceFile {
17
17
  options;
18
18
  coreImports = new Set();
19
19
  entityImports = new Set();
20
+ enumImports = new Map();
20
21
  constructor(meta, namingStrategy, platform, options) {
21
22
  this.meta = meta;
22
23
  this.namingStrategy = namingStrategy;
@@ -68,7 +69,10 @@ class SourceFile {
68
69
  classBody += definition;
69
70
  classBody += '\n';
70
71
  if (prop.enum) {
71
- enumDefinitions.push(this.getEnumClassDefinition(prop, 2));
72
+ const def = this.getEnumClassDefinition(prop, 2);
73
+ if (def.length) {
74
+ enumDefinitions.push(def);
75
+ }
72
76
  }
73
77
  if (prop.eager) {
74
78
  eagerProperties.push(prop);
@@ -149,32 +153,45 @@ class SourceFile {
149
153
  const basePath = (0, node_path_1.relative)(dir, this.options.path ?? '.') || '.';
150
154
  (this.options.extraImports?.(basePath, base) ?? []).forEach(v => this.entityImports.add(v));
151
155
  const entityImports = [...this.entityImports].filter(e => e !== this.meta.className);
152
- entityImports.sort().forEach(entity => {
156
+ const importMap = new Map();
157
+ for (const entity of entityImports) {
153
158
  const file = this.options.onImport?.(entity, basePath, extension, base) ?? {
154
159
  path: `${basePath}/${this.options.fileName(entity)}${extension}`,
155
160
  name: entity,
156
161
  };
157
162
  if (file.path === '') {
158
163
  if (file.name === '') {
159
- return;
164
+ continue;
160
165
  }
161
- imports.add(`import ${this.quote(file.name)};`);
162
- return;
166
+ importMap.set(file.path, `import ${this.quote(file.name)};`);
167
+ continue;
163
168
  }
164
169
  if (file.name === '') {
165
- imports.add(`import * as ${entity} from ${this.quote(file.path)};`);
166
- return;
170
+ importMap.set(file.path, `import * as ${entity} from ${this.quote(file.path)};`);
171
+ continue;
167
172
  }
168
173
  if (file.name === 'default') {
169
- imports.add(`import ${entity} from ${this.quote(file.path)};`);
170
- return;
174
+ importMap.set(file.path, `import ${entity} from ${this.quote(file.path)};`);
175
+ continue;
171
176
  }
172
177
  if (file.name === entity) {
173
- imports.add(`import { ${entity} } from ${this.quote(file.path)};`);
174
- return;
178
+ importMap.set(file.path, `import { ${entity} } from ${this.quote(file.path)};`);
179
+ continue;
175
180
  }
176
- imports.add(`import { ${exports.identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
177
- });
181
+ importMap.set(file.path, `import { ${exports.identifierRegex.test(file.name) ? file.name : this.quote(file.name)} as ${entity} } from ${this.quote(file.path)};`);
182
+ }
183
+ if (this.enumImports.size) {
184
+ for (const [name, exports] of this.enumImports.entries()) {
185
+ const file = this.options.onImport?.(name, basePath, extension, base) ?? {
186
+ path: `${basePath}/${this.options.fileName(name)}${extension}`,
187
+ name,
188
+ };
189
+ importMap.set(file.path, `import { ${exports.join(', ')} } from ${this.quote(file.path)};`);
190
+ }
191
+ }
192
+ for (const key of [...importMap.keys()].sort()) {
193
+ imports.add(importMap.get(key));
194
+ }
178
195
  return Array.from(imports.values()).join('\n');
179
196
  }
180
197
  getEntityClass(classBody) {
@@ -204,6 +221,7 @@ class SourceFile {
204
221
  getPropertyDefinition(prop, padLeft) {
205
222
  const padding = ' '.repeat(padLeft);
206
223
  const propName = exports.identifierRegex.test(prop.name) ? prop.name : this.quote(prop.name);
224
+ const enumMode = this.options.enumMode;
207
225
  let hiddenType = '';
208
226
  if (prop.hidden) {
209
227
  hiddenType += ` & ${this.referenceCoreImport('Hidden')}`;
@@ -221,7 +239,11 @@ class SourceFile {
221
239
  : (() => {
222
240
  if (isScalar) {
223
241
  if (prop.enum) {
224
- return prop.runtimeType;
242
+ const method = enumMode === 'ts-enum' ? 'getEnumClassName' : 'getEnumTypeName';
243
+ if (prop.nativeEnumName) {
244
+ return this.namingStrategy[method](prop.nativeEnumName, undefined, this.meta.schema);
245
+ }
246
+ return this.namingStrategy[method](prop.fieldNames[0], this.meta.collection, this.meta.schema);
225
247
  }
226
248
  breakdownOfIType = this.breakdownOfIType(prop);
227
249
  if (typeof breakdownOfIType !== 'undefined') {
@@ -256,8 +278,14 @@ class SourceFile {
256
278
  return `${padding}${ret};\n`;
257
279
  }
258
280
  if (prop.enum && typeof prop.default === 'string') {
281
+ if (enumMode === 'union-type') {
282
+ return `${padding}${ret} = ${this.quote(prop.default)};\n`;
283
+ }
284
+ const enumClassName = prop.nativeEnumName
285
+ ? this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema)
286
+ : this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
259
287
  const enumVal = this.namingStrategy.enumValueToEnumProperty(prop.default, prop.fieldNames[0], this.meta.collection, this.meta.schema);
260
- return `${padding}${ret} = ${propType}${exports.identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
288
+ return `${padding}${ret} = ${enumClassName}${exports.identifierRegex.test(enumVal) ? `.${enumVal}` : `[${this.quote(enumVal)}]`};\n`;
261
289
  }
262
290
  if (prop.fieldNames?.length > 1) {
263
291
  // TODO: Composite FKs with default values require additions to default/defaultRaw that are not yet supported.
@@ -273,15 +301,51 @@ class SourceFile {
273
301
  return `${padding}${ret} = ${prop.ref ? this.referenceCoreImport('ref') : this.referenceCoreImport('rel')}(${propType}, ${defaultVal});\n`;
274
302
  }
275
303
  getEnumClassDefinition(prop, padLeft) {
304
+ const enumMode = this.options.enumMode;
305
+ if (prop.nativeEnumName) {
306
+ const imports = [];
307
+ if (enumMode !== 'union-type') {
308
+ imports.push(prop.runtimeType);
309
+ }
310
+ if (!this.options.inferEntityType && enumMode !== 'ts-enum') {
311
+ const enumTypeName = this.namingStrategy.getEnumTypeName(prop.nativeEnumName, undefined, this.meta.schema);
312
+ imports.push(enumTypeName);
313
+ }
314
+ this.enumImports.set(prop.runtimeType, imports);
315
+ return '';
316
+ }
276
317
  const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
318
+ const enumTypeName = this.namingStrategy.getEnumTypeName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
277
319
  const padding = ' '.repeat(padLeft);
278
- let ret = `export enum ${enumClassName} {\n`;
279
320
  const enumValues = prop.items;
321
+ if (enumMode === 'union-type') {
322
+ return `export type ${enumTypeName} = ${enumValues.map(item => this.quote(item)).join(' | ')};\n`;
323
+ }
324
+ let ret = '';
325
+ if (enumMode === 'dictionary') {
326
+ ret += `export const ${enumClassName} = {\n`;
327
+ }
328
+ else {
329
+ ret += `export enum ${enumClassName} {\n`;
330
+ }
280
331
  for (const enumValue of enumValues) {
281
332
  const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, prop.fieldNames[0], this.meta.collection, this.meta.schema);
282
- ret += `${padding}${exports.identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
333
+ if (enumMode === 'dictionary') {
334
+ ret += `${padding}${exports.identifierRegex.test(enumName) ? enumName : this.quote(enumName)}: ${this.quote(enumValue)},\n`;
335
+ }
336
+ else {
337
+ ret += `${padding}${exports.identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
338
+ }
339
+ }
340
+ if (enumMode === 'dictionary') {
341
+ ret += '} as const;\n';
342
+ }
343
+ else {
344
+ ret += '}\n';
345
+ }
346
+ if (enumMode === 'dictionary') {
347
+ ret += `\nexport type ${enumTypeName} = (typeof ${enumClassName})[keyof typeof ${enumClassName}];\n`;
283
348
  }
284
- ret += '}\n';
285
349
  return ret;
286
350
  }
287
351
  serializeObject(options, wordwrap, spaces, level = 0) {
@@ -540,12 +604,23 @@ class SourceFile {
540
604
  this.propTypeBreakdowns.set(prop, r);
541
605
  return r;
542
606
  }
543
- getScalarPropertyDecoratorOptions(options, prop) {
607
+ getScalarPropertyDecoratorOptions(options, prop, quote = true) {
544
608
  if (prop.fieldNames[0] !== this.namingStrategy.propertyToColumnName(prop.name)) {
545
609
  options.fieldName = this.quote(prop.fieldNames[0]);
546
610
  }
547
611
  if (prop.enum) {
548
- options.items = `() => ${prop.runtimeType}`;
612
+ if (this.options.enumMode === 'union-type') {
613
+ options.items = `[${prop.items.map(item => this.quote(item)).join(', ')}]`;
614
+ }
615
+ else if (prop.nativeEnumName) {
616
+ const enumClassName = this.namingStrategy.getEnumClassName(prop.nativeEnumName, undefined, this.meta.schema);
617
+ options.items = `() => ${enumClassName}`;
618
+ options.nativeEnumName = this.quote(prop.nativeEnumName);
619
+ }
620
+ else {
621
+ const enumClassName = this.namingStrategy.getEnumClassName(prop.fieldNames[0], this.meta.collection, this.meta.schema);
622
+ options.items = `() => ${enumClassName}`;
623
+ }
549
624
  }
550
625
  // For enum properties, we don't need a column type
551
626
  // or the property length or other information in the decorator.
@@ -574,7 +649,7 @@ class SourceFile {
574
649
  return ((useDefault && !hasUsableNullDefault) || (prop.optional && !prop.nullable));
575
650
  })() // also when there is the "| Opt" type modifier (because reflect-metadata can't extract the base)
576
651
  ) {
577
- options.type = this.quote(prop.type);
652
+ options.type = quote ? this.quote(prop.type) : prop.type;
578
653
  }
579
654
  }
580
655
  const columnTypeFromMappedRuntimeType = mappedRuntimeType.getColumnType({ ...prop, autoincrement: false }, this.platform);
@@ -675,7 +750,7 @@ class SourceFile {
675
750
  if (prop.array) {
676
751
  options.array = true;
677
752
  }
678
- if (prop.object) {
753
+ if (prop.object && !prop.array) {
679
754
  options.object = true;
680
755
  }
681
756
  if (prop.prefix === false || typeof prop.prefix === 'string') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/entity-generator",
3
- "version": "6.5.10-dev.9",
3
+ "version": "6.6.0",
4
4
  "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
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -58,13 +58,13 @@
58
58
  "access": "public"
59
59
  },
60
60
  "dependencies": {
61
- "@mikro-orm/knex": "6.5.10-dev.9",
61
+ "@mikro-orm/knex": "6.6.0",
62
62
  "fs-extra": "11.3.2"
63
63
  },
64
64
  "devDependencies": {
65
- "@mikro-orm/core": "^6.5.9"
65
+ "@mikro-orm/core": "^6.6.0"
66
66
  },
67
67
  "peerDependencies": {
68
- "@mikro-orm/core": "6.5.10-dev.9"
68
+ "@mikro-orm/core": "^6.0.0"
69
69
  }
70
70
  }