@mikro-orm/entity-generator 7.0.0-dev.1 → 7.0.0-dev.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.POSSIBLE_TYPE_IMPORTS = void 0;
4
- exports.POSSIBLE_TYPE_IMPORTS = [
1
+ export const POSSIBLE_TYPE_IMPORTS = [
5
2
  'DefineConfig',
6
3
  'Hidden',
7
4
  'IType',
@@ -0,0 +1,5 @@
1
+ import { EntitySchemaSourceFile } from './EntitySchemaSourceFile.js';
2
+ export declare class DefineEntitySourceFile extends EntitySchemaSourceFile {
3
+ generate(): string;
4
+ private getPropertyBuilder;
5
+ }
@@ -0,0 +1,115 @@
1
+ import { Config, ReferenceKind, types, } from '@mikro-orm/core';
2
+ import { EntitySchemaSourceFile } from './EntitySchemaSourceFile.js';
3
+ export class DefineEntitySourceFile extends EntitySchemaSourceFile {
4
+ generate() {
5
+ const enumDefinitions = [];
6
+ for (const prop of Object.values(this.meta.properties)) {
7
+ if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR)) {
8
+ const def = this.getEnumClassDefinition(prop, 2);
9
+ if (def.length) {
10
+ enumDefinitions.push(def);
11
+ }
12
+ }
13
+ }
14
+ let ret = '';
15
+ if (!this.options.inferEntityType) {
16
+ ret += this.generateClassDefinition() + '\n';
17
+ }
18
+ if (enumDefinitions.length) {
19
+ ret += enumDefinitions.join('\n') + '\n';
20
+ }
21
+ const entitySchemaOptions = {};
22
+ if (this.options.inferEntityType) {
23
+ entitySchemaOptions.name = this.quote(this.meta.className);
24
+ if (this.meta.compositePK) {
25
+ entitySchemaOptions.primaryKeys = this.meta.getPrimaryProps().map(p => this.quote(p.name));
26
+ }
27
+ }
28
+ else {
29
+ entitySchemaOptions.class = this.meta.className;
30
+ }
31
+ Object.assign(entitySchemaOptions, (this.meta.embeddable ? this.getEmbeddableDeclOptions() : (this.meta.collection ? this.getEntityDeclOptions() : {})));
32
+ const nameSuffix = this.options.inferEntityType ? '' : 'Schema';
33
+ const declLine = `export const ${this.meta.className + nameSuffix} = ${this.referenceCoreImport('defineEntity')}(`;
34
+ ret += declLine;
35
+ if (this.meta.indexes.length > 0) {
36
+ entitySchemaOptions.indexes = this.meta.indexes.map(index => this.getIndexOptions(index));
37
+ }
38
+ if (this.meta.uniques.length > 0) {
39
+ entitySchemaOptions.uniques = this.meta.uniques.map(index => this.getUniqueOptions(index));
40
+ }
41
+ entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyBuilder(prop)]));
42
+ // Force top level and properties to be indented, regardless of line length
43
+ entitySchemaOptions[Config] = true;
44
+ entitySchemaOptions.properties[Config] = true;
45
+ ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
46
+ ret += ');\n';
47
+ if (this.options.inferEntityType) {
48
+ ret += `\nexport interface I${this.meta.className} extends ${this.referenceCoreImport('InferEntity')}<typeof ${this.meta.className}> {}\n`;
49
+ }
50
+ ret = `${this.generateImports()}\n\n${ret}`;
51
+ return ret;
52
+ }
53
+ getPropertyBuilder(prop) {
54
+ const options = this.getPropertyOptions(prop, false);
55
+ const p = this.referenceCoreImport('p');
56
+ let builder = '';
57
+ switch (prop.kind) {
58
+ case ReferenceKind.ONE_TO_ONE:
59
+ builder += `() => ${p}.oneToOne(${prop.type})`;
60
+ break;
61
+ case ReferenceKind.ONE_TO_MANY:
62
+ builder += `() => ${p}.oneToMany(${prop.type})`;
63
+ break;
64
+ case ReferenceKind.MANY_TO_ONE:
65
+ builder += `() => ${p}.manyToOne(${prop.type})`;
66
+ break;
67
+ case ReferenceKind.MANY_TO_MANY:
68
+ builder += `() => ${p}.manyToMany(${prop.type})`;
69
+ break;
70
+ case ReferenceKind.EMBEDDED:
71
+ builder += `() => ${p}.embedded(${prop.type})`;
72
+ break;
73
+ case ReferenceKind.SCALAR:
74
+ default: {
75
+ if (options.type && !(options.type in types)) {
76
+ builder += `${p}.type(${options.type})`;
77
+ }
78
+ else {
79
+ builder += options.type ? `${p}.${options.type}()` : p;
80
+ }
81
+ }
82
+ }
83
+ const simpleOptions = new Set([
84
+ 'primary', 'ref', 'nullable', 'array', 'object', 'mapToPk', 'hidden', 'concurrencyCheck', 'lazy', 'eager',
85
+ 'orphanRemoval', 'version', 'unsigned', 'returning', 'createForeignKeyConstraint', 'fixedOrder', 'owner',
86
+ 'getter', 'setter', 'unique', 'index', 'hydrate', 'persist', 'autoincrement',
87
+ ]);
88
+ const skipOptions = new Set(['entity', 'kind', 'type', 'items']);
89
+ const spreadOptions = new Set([
90
+ 'fieldNames', 'joinColumns', 'inverseJoinColumns', 'referencedColumnNames', 'ownColumns', 'columnTypes',
91
+ 'cascade', 'ignoreSchemaChanges', 'customOrder', 'groups', 'where', 'orderBy',
92
+ ]);
93
+ const rename = {
94
+ fieldName: 'name',
95
+ };
96
+ for (const key of Object.keys(options)) {
97
+ if (typeof options[key] === 'undefined' || skipOptions.has(key)) {
98
+ continue;
99
+ }
100
+ const method = rename[key] ?? key;
101
+ const params = simpleOptions.has(key) && options[key] === true ? '' : options[key];
102
+ builder += `.${method}`;
103
+ if (key === 'enum') {
104
+ builder += `(${options.items})`;
105
+ }
106
+ else if (spreadOptions.has(key) && typeof params === 'string' && params.startsWith('[')) {
107
+ builder += `(${params.slice(1, -1)})`;
108
+ }
109
+ else {
110
+ builder += `(${params})`;
111
+ }
112
+ }
113
+ return builder;
114
+ }
115
+ }
@@ -1,5 +1,5 @@
1
1
  import { type GenerateOptions, type MikroORM } from '@mikro-orm/core';
2
- import { type EntityManager } from '@mikro-orm/knex';
2
+ import { type EntityManager } from '@mikro-orm/sql';
3
3
  export declare class EntityGenerator {
4
4
  private readonly em;
5
5
  private readonly config;
@@ -1,13 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EntityGenerator = void 0;
4
- const core_1 = require("@mikro-orm/core");
5
- const knex_1 = require("@mikro-orm/knex");
6
- const node_path_1 = require("node:path");
7
- const fs_extra_1 = require("fs-extra");
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/sql';
3
+ import { fs } from '@mikro-orm/core/fs-utils';
4
+ import { dirname, join } from 'node:path';
5
+ import { writeFile } from 'node:fs/promises';
6
+ import { DefineEntitySourceFile } from './DefineEntitySourceFile.js';
7
+ import { EntitySchemaSourceFile } from './EntitySchemaSourceFile.js';
8
+ import { NativeEnumSourceFile } from './NativeEnumSourceFile.js';
9
+ import { SourceFile } from './SourceFile.js';
10
+ export class EntityGenerator {
11
11
  em;
12
12
  config;
13
13
  driver;
@@ -30,33 +30,45 @@ class EntityGenerator {
30
30
  orm.config.registerExtension('@mikro-orm/entity-generator', () => new EntityGenerator(orm.em));
31
31
  }
32
32
  async generate(options = {}) {
33
- options = core_1.Utils.mergeConfig({}, this.config.get('entityGenerator'), options);
34
- const schema = await knex_1.DatabaseSchema.create(this.connection, this.platform, this.config, undefined, undefined, options.takeTables, options.skipTables);
33
+ options = Utils.mergeConfig({}, this.config.get('entityGenerator'), options);
34
+ const schema = await DatabaseSchema.create(this.connection, this.platform, this.config, undefined, undefined, options.takeTables, options.skipTables);
35
35
  const metadata = await this.getEntityMetadata(schema, options);
36
36
  const defaultPath = `${this.config.get('baseDir')}/generated-entities`;
37
- const baseDir = core_1.Utils.normalizePath(options.path ?? defaultPath);
37
+ const baseDir = Utils.normalizePath(options.path ?? defaultPath);
38
+ this.sources.length = 0;
39
+ const map = {
40
+ defineEntity: DefineEntitySourceFile,
41
+ entitySchema: EntitySchemaSourceFile,
42
+ decorators: SourceFile,
43
+ };
44
+ if (options.entityDefinition !== 'decorators') {
45
+ options.scalarTypeInDecorator = true;
46
+ }
38
47
  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
- }
48
+ if (meta.pivotTable && !options.outputPurePivotTables && !this.referencedEntities.has(meta)) {
49
+ continue;
46
50
  }
51
+ this.sources.push(new map[options.entityDefinition](meta, this.namingStrategy, this.platform, options));
47
52
  }
53
+ for (const nativeEnum of Object.values(schema.getNativeEnums())) {
54
+ this.sources.push(new NativeEnumSourceFile({}, this.namingStrategy, this.platform, options, nativeEnum));
55
+ }
56
+ const files = this.sources.map(file => [file.getBaseName(), file.generate()]);
48
57
  if (options.save) {
49
- 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
- }));
58
+ fs.ensureDir(baseDir);
59
+ const promises = [];
60
+ for (const [fileName, data] of files) {
61
+ promises.push((async () => {
62
+ const fileDir = dirname(fileName);
63
+ if (fileDir !== '.') {
64
+ fs.ensureDir(join(baseDir, fileDir));
65
+ }
66
+ await writeFile(join(baseDir, fileName), data, { flush: true });
67
+ })());
68
+ }
69
+ await Promise.all(promises);
58
70
  }
59
- return this.sources.map(file => file.generate());
71
+ return files.map(([, data]) => data);
60
72
  }
61
73
  async getEntityMetadata(schema, options) {
62
74
  const metadata = schema.getTables()
@@ -76,11 +88,11 @@ class EntityGenerator {
76
88
  for (const meta of metadata) {
77
89
  for (const prop of meta.relations) {
78
90
  if (!metadata.some(otherMeta => prop.referencedTableName === otherMeta.collection || prop.referencedTableName === `${otherMeta.schema ?? schema.name}.${otherMeta.collection}`)) {
79
- prop.kind = core_1.ReferenceKind.SCALAR;
91
+ prop.kind = ReferenceKind.SCALAR;
80
92
  const mappedTypes = prop.columnTypes.map((t, i) => this.platform.getMappedType(t));
81
93
  const runtimeTypes = mappedTypes.map(t => t.runtimeType);
82
94
  prop.runtimeType = (runtimeTypes.length === 1 ? runtimeTypes[0] : `[${runtimeTypes.join(', ')}]`);
83
- prop.type = mappedTypes.length === 1 ? (core_1.Utils.entries(core_1.types).find(([k, v]) => Object.getPrototypeOf(mappedTypes[0]) === v.prototype)?.[0] ?? mappedTypes[0].name) : 'unknown';
95
+ prop.type = mappedTypes.length === 1 ? (Utils.entries(types).find(([k, v]) => Object.getPrototypeOf(mappedTypes[0]) === v.prototype)?.[0] ?? mappedTypes[0].name) : 'unknown';
84
96
  }
85
97
  const meta2 = metadata.find(meta2 => meta2.className === prop.type);
86
98
  const targetPrimaryColumns = meta2?.getPrimaryProps().flatMap(p => p.fieldNames);
@@ -93,7 +105,7 @@ class EntityGenerator {
93
105
  }
94
106
  await options.onInitialMetadata?.(metadata, this.platform);
95
107
  // enforce schema usage in class names only on duplicates
96
- const duplicates = core_1.Utils.findDuplicates(metadata.map(meta => meta.className));
108
+ const duplicates = Utils.findDuplicates(metadata.map(meta => meta.className));
97
109
  for (const duplicate of duplicates) {
98
110
  for (const meta of metadata.filter(meta => meta.className === duplicate)) {
99
111
  meta.className = this.namingStrategy.getEntityName(`${meta.schema ?? schema.name}_${meta.className}`);
@@ -131,7 +143,7 @@ class EntityGenerator {
131
143
  for (const meta of metadata) {
132
144
  const isReferenced = metadata.some(m => {
133
145
  return m.tableName !== meta.tableName && m.relations.some(r => {
134
- return r.referencedTableName === meta.tableName && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(r.kind);
146
+ return r.referencedTableName === meta.tableName && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(r.kind);
135
147
  });
136
148
  });
137
149
  if (isReferenced) {
@@ -144,7 +156,7 @@ class EntityGenerator {
144
156
  // Entities where there are not exactly 2 PK relations that are both ManyToOne are never pivot tables. Skip.
145
157
  const pkRelations = meta.relations.filter(rel => rel.primary);
146
158
  if (pkRelations.length !== 2 ||
147
- pkRelations.some(rel => rel.kind !== core_1.ReferenceKind.MANY_TO_ONE)) {
159
+ pkRelations.some(rel => rel.kind !== ReferenceKind.MANY_TO_ONE)) {
148
160
  continue;
149
161
  }
150
162
  const pkRelationFields = new Set(pkRelations.flatMap(rel => rel.fieldNames));
@@ -196,7 +208,7 @@ class EntityGenerator {
196
208
  const name = this.namingStrategy.columnNameToProperty(meta.tableName.replace(new RegExp('^' + owner.tableName + '_'), ''));
197
209
  const ownerProp = {
198
210
  name,
199
- kind: core_1.ReferenceKind.MANY_TO_MANY,
211
+ kind: ReferenceKind.MANY_TO_MANY,
200
212
  pivotTable: meta.tableName,
201
213
  type: meta.relations[1].type,
202
214
  joinColumns: meta.relations[0].fieldNames,
@@ -229,21 +241,21 @@ class EntityGenerator {
229
241
  type: meta.className,
230
242
  joinColumns: prop.fieldNames,
231
243
  referencedTableName: meta.tableName,
232
- referencedColumnNames: core_1.Utils.flatten(targetMeta.getPrimaryProps().map(pk => pk.fieldNames)),
244
+ referencedColumnNames: Utils.flatten(targetMeta.getPrimaryProps().map(pk => pk.fieldNames)),
233
245
  mappedBy: prop.name,
234
246
  persist: prop.persist,
235
247
  };
236
- if (prop.kind === core_1.ReferenceKind.MANY_TO_ONE) {
237
- newProp.kind = core_1.ReferenceKind.ONE_TO_MANY;
248
+ if (prop.kind === ReferenceKind.MANY_TO_ONE) {
249
+ newProp.kind = ReferenceKind.ONE_TO_MANY;
238
250
  }
239
- else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.mappedBy) {
240
- newProp.kind = core_1.ReferenceKind.ONE_TO_ONE;
251
+ else if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.mappedBy) {
252
+ newProp.kind = ReferenceKind.ONE_TO_ONE;
241
253
  newProp.nullable = true;
242
254
  newProp.default = null;
243
255
  newProp.defaultRaw = 'null';
244
256
  }
245
- else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && !prop.mappedBy) {
246
- newProp.kind = core_1.ReferenceKind.MANY_TO_MANY;
257
+ else if (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.mappedBy) {
258
+ newProp.kind = ReferenceKind.MANY_TO_MANY;
247
259
  }
248
260
  else {
249
261
  continue;
@@ -260,7 +272,7 @@ class EntityGenerator {
260
272
  generateIdentifiedReferences(metadata) {
261
273
  for (const meta of metadata.filter(m => !m.pivotTable || this.referencedEntities.has(m))) {
262
274
  for (const prop of Object.values(meta.properties)) {
263
- if ([core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind) || prop.lazy) {
275
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) || prop.lazy) {
264
276
  prop.ref = true;
265
277
  }
266
278
  }
@@ -276,7 +288,7 @@ class EntityGenerator {
276
288
  meta.extends ??= customBaseEntityName;
277
289
  }
278
290
  if (!baseClassExists) {
279
- metadata.push(new core_1.EntityMetadata({
291
+ metadata.push(new EntityMetadata({
280
292
  className: customBaseEntityName,
281
293
  abstract: true,
282
294
  relations: [],
@@ -294,4 +306,3 @@ class EntityGenerator {
294
306
  }
295
307
  }
296
308
  }
297
- exports.EntityGenerator = EntityGenerator;
@@ -1,8 +1,9 @@
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
- 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
  }
@@ -1,25 +1,57 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EntitySchemaSourceFile = void 0;
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() {
5
+ const classDefinition = this.generateClassDefinition();
6
+ const enumDefinitions = [];
7
+ for (const prop of Object.values(this.meta.properties)) {
8
+ if (prop.enum && (typeof prop.kind === 'undefined' || prop.kind === ReferenceKind.SCALAR)) {
9
+ const def = this.getEnumClassDefinition(prop, 2);
10
+ if (def.length) {
11
+ enumDefinitions.push(def);
12
+ }
13
+ }
14
+ }
15
+ let ret = classDefinition;
16
+ if (enumDefinitions.length) {
17
+ ret += '\n' + enumDefinitions.join('\n');
18
+ }
19
+ ret += `\n`;
20
+ const entitySchemaOptions = {
21
+ class: this.meta.className,
22
+ ...(this.meta.embeddable ? this.getEmbeddableDeclOptions() : (this.meta.collection ? this.getEntityDeclOptions() : {})),
23
+ };
24
+ const declLine = `export const ${this.meta.className}Schema = new ${this.referenceCoreImport('EntitySchema')}(`;
25
+ ret += declLine;
26
+ if (this.meta.indexes.length > 0) {
27
+ entitySchemaOptions.indexes = this.meta.indexes.map(index => this.getIndexOptions(index));
28
+ }
29
+ if (this.meta.uniques.length > 0) {
30
+ entitySchemaOptions.uniques = this.meta.uniques.map(index => this.getUniqueOptions(index));
31
+ }
32
+ entitySchemaOptions.properties = Object.fromEntries(Object.entries(this.meta.properties).map(([name, prop]) => [name, this.getPropertyOptions(prop)]));
33
+ // Force top level and properties to be indented, regardless of line length
34
+ entitySchemaOptions[Config] = true;
35
+ entitySchemaOptions.properties[Config] = true;
36
+ ret += this.serializeObject(entitySchemaOptions, declLine.length > 80 ? undefined : 80 - declLine.length, 0);
37
+ ret += ');\n';
38
+ ret = `${this.generateImports()}\n\n${ret}`;
39
+ return ret;
40
+ }
41
+ generateClassDefinition() {
8
42
  let classBody = '';
9
- if (this.meta.className === this.options.customBaseEntityName) {
43
+ if (!this.options.customBaseEntityName || this.meta.className === this.options.customBaseEntityName) {
10
44
  const defineConfigTypeSettings = {};
11
45
  defineConfigTypeSettings.forceObject = this.platform.getConfig().get('serialization').forceObject ?? false;
12
- classBody += `${' '.repeat(2)}[${this.referenceCoreImport('Config')}]?: ${this.referenceCoreImport('DefineConfig')}<${this.serializeObject(defineConfigTypeSettings)}>;\n`;
46
+ if (defineConfigTypeSettings.forceObject) {
47
+ classBody += `${' '.repeat(2)}[${this.referenceCoreImport('Config')}]?: ${this.referenceCoreImport('DefineConfig')}<${this.serializeObject(defineConfigTypeSettings)}>;\n`;
48
+ }
13
49
  }
14
- const enumDefinitions = [];
15
50
  const eagerProperties = [];
16
51
  const primaryProps = [];
17
52
  const props = [];
18
53
  for (const prop of Object.values(this.meta.properties)) {
19
54
  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
55
  if (prop.eager) {
24
56
  eagerProperties.push(prop);
25
57
  }
@@ -41,50 +73,26 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
41
73
  classBody += `${' '.repeat(2)}[${this.referenceCoreImport('EagerProps')}]?: ${eagerPropertyNames.join(' | ')};\n`;
42
74
  }
43
75
  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;
76
+ return this.getEntityClass(classBody);
69
77
  }
70
- getPropertyOptions(prop) {
78
+ getPropertyOptions(prop, quote = true) {
71
79
  const options = {};
72
80
  if (prop.primary) {
73
81
  options.primary = true;
74
82
  }
75
- if (typeof prop.kind !== 'undefined' && prop.kind !== core_1.ReferenceKind.SCALAR) {
83
+ if (typeof prop.kind !== 'undefined' && prop.kind !== ReferenceKind.SCALAR) {
76
84
  options.kind = this.quote(prop.kind);
77
85
  }
78
- if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
86
+ if (prop.kind === ReferenceKind.MANY_TO_MANY) {
79
87
  this.getManyToManyDecoratorOptions(options, prop);
80
88
  }
81
- else if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY) {
89
+ else if (prop.kind === ReferenceKind.ONE_TO_MANY) {
82
90
  this.getOneToManyDecoratorOptions(options, prop);
83
91
  }
84
- else if (prop.kind === core_1.ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
85
- this.getScalarPropertyDecoratorOptions(options, prop);
92
+ else if (prop.kind === ReferenceKind.SCALAR || typeof prop.kind === 'undefined') {
93
+ this.getScalarPropertyDecoratorOptions(options, prop, quote);
86
94
  }
87
- else if (prop.kind === core_1.ReferenceKind.EMBEDDED) {
95
+ else if (prop.kind === ReferenceKind.EMBEDDED) {
88
96
  this.getEmbeddedPropertyDeclarationOptions(options, prop);
89
97
  }
90
98
  else {
@@ -98,7 +106,7 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
98
106
  return options;
99
107
  }
100
108
  getPropertyIndexesOptions(prop, options) {
101
- if (prop.kind === core_1.ReferenceKind.SCALAR) {
109
+ if (prop.kind === ReferenceKind.SCALAR) {
102
110
  if (prop.index) {
103
111
  options.index = this.quote(prop.index);
104
112
  }
@@ -113,11 +121,11 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
113
121
  return;
114
122
  }
115
123
  const defaultName = this.platform.getIndexName(this.meta.collection, prop.fieldNames, type);
116
- /* istanbul ignore next */
124
+ /* v8 ignore next */
117
125
  options[type] = (propType === true || defaultName === propType) ? 'true' : this.quote(propType);
118
126
  const expected = {
119
127
  index: this.platform.indexForeignKeys(),
120
- unique: prop.kind === core_1.ReferenceKind.ONE_TO_ONE,
128
+ unique: prop.kind === ReferenceKind.ONE_TO_ONE,
121
129
  };
122
130
  if (expected[type] && options[type] === 'true') {
123
131
  delete options[type];
@@ -126,15 +134,14 @@ class EntitySchemaSourceFile extends SourceFile_1.SourceFile {
126
134
  processIndex('index');
127
135
  processIndex('unique');
128
136
  }
129
- getScalarPropertyDecoratorOptions(options, prop) {
137
+ getScalarPropertyDecoratorOptions(options, prop, quote = true) {
130
138
  if (prop.enum) {
131
139
  options.enum = true;
132
140
  options.items = `() => ${prop.runtimeType}`;
133
141
  }
134
142
  else {
135
- options.type = this.quote(prop.type);
143
+ options.type = quote ? this.quote(prop.type) : prop.type;
136
144
  }
137
- super.getScalarPropertyDecoratorOptions(options, prop);
145
+ super.getScalarPropertyDecoratorOptions(options, prop, quote);
138
146
  }
139
147
  }
140
- exports.EntitySchemaSourceFile = EntitySchemaSourceFile;
@@ -0,0 +1,16 @@
1
+ import type { EntityMetadata, GenerateOptions, NamingStrategy, Platform } from '@mikro-orm/core';
2
+ import { SourceFile } from './SourceFile.js';
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,47 @@
1
+ import { identifierRegex, SourceFile } from './SourceFile.js';
2
+ export class NativeEnumSourceFile extends SourceFile {
3
+ nativeEnum;
4
+ constructor(meta, namingStrategy, platform, options, nativeEnum) {
5
+ super(meta, namingStrategy, platform, options);
6
+ this.nativeEnum = nativeEnum;
7
+ }
8
+ generate() {
9
+ const enumClassName = this.namingStrategy.getEnumClassName(this.nativeEnum.name, undefined, this.nativeEnum.schema);
10
+ const enumTypeName = this.namingStrategy.getEnumTypeName(this.nativeEnum.name, undefined, this.nativeEnum.schema);
11
+ const padding = ' ';
12
+ const enumMode = this.options.enumMode;
13
+ const enumValues = this.nativeEnum.items;
14
+ if (enumMode === 'union-type') {
15
+ return `export type ${enumTypeName} = ${enumValues.map(item => this.quote(item)).join(' | ')};\n`;
16
+ }
17
+ let ret = '';
18
+ if (enumMode === 'dictionary') {
19
+ ret += `export const ${enumClassName} = {\n`;
20
+ }
21
+ else {
22
+ ret += `export enum ${enumClassName} {\n`;
23
+ }
24
+ for (const enumValue of enumValues) {
25
+ const enumName = this.namingStrategy.enumValueToEnumProperty(enumValue, this.nativeEnum.name, '', this.nativeEnum.schema);
26
+ if (enumMode === 'dictionary') {
27
+ ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)}: ${this.quote(enumValue)},\n`;
28
+ }
29
+ else {
30
+ ret += `${padding}${identifierRegex.test(enumName) ? enumName : this.quote(enumName)} = ${this.quote(enumValue)},\n`;
31
+ }
32
+ }
33
+ if (enumMode === 'dictionary') {
34
+ ret += '} as const;\n';
35
+ }
36
+ else {
37
+ ret += '}\n';
38
+ }
39
+ if (enumMode === 'dictionary') {
40
+ ret += `\nexport type ${enumTypeName} = (typeof ${enumClassName})[keyof typeof ${enumClassName}];\n`;
41
+ }
42
+ return ret;
43
+ }
44
+ getBaseName(extension = '.ts') {
45
+ return `${this.options.fileName(this.nativeEnum.name)}${extension}`;
46
+ }
47
+ }
package/README.md CHANGED
@@ -11,7 +11,6 @@ TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-or
11
11
  [![Chat on discord](https://img.shields.io/discord/1214904142443839538?label=discord&color=blue)](https://discord.gg/w8bjxFHS7X)
12
12
  [![Downloads](https://img.shields.io/npm/dm/@mikro-orm/core.svg)](https://www.npmjs.com/package/@mikro-orm/core)
13
13
  [![Coverage Status](https://img.shields.io/coveralls/mikro-orm/mikro-orm.svg)](https://coveralls.io/r/mikro-orm/mikro-orm?branch=master)
14
- [![Maintainability](https://api.codeclimate.com/v1/badges/27999651d3adc47cfa40/maintainability)](https://codeclimate.com/github/mikro-orm/mikro-orm/maintainability)
15
14
  [![Build Status](https://github.com/mikro-orm/mikro-orm/workflows/tests/badge.svg?branch=master)](https://github.com/mikro-orm/mikro-orm/actions?workflow=tests)
16
15
 
17
16
  ## 🤔 Unit of What?
@@ -141,7 +140,7 @@ There is also auto-generated [CHANGELOG.md](CHANGELOG.md) file based on commit m
141
140
  - [Composite and Foreign Keys as Primary Key](https://mikro-orm.io/docs/composite-keys)
142
141
  - [Filters](https://mikro-orm.io/docs/filters)
143
142
  - [Using `QueryBuilder`](https://mikro-orm.io/docs/query-builder)
144
- - [Preloading Deeply Nested Structures via populate](https://mikro-orm.io/docs/nested-populate)
143
+ - [Populating relations](https://mikro-orm.io/docs/populating-relations)
145
144
  - [Property Validation](https://mikro-orm.io/docs/property-validation)
146
145
  - [Lifecycle Hooks](https://mikro-orm.io/docs/events#hooks)
147
146
  - [Vanilla JS Support](https://mikro-orm.io/docs/usage-with-js)
@@ -382,6 +381,8 @@ See also the list of contributors who [participated](https://github.com/mikro-or
382
381
 
383
382
  Please ⭐️ this repository if this project helped you!
384
383
 
384
+ > If you'd like to support my open-source work, consider sponsoring me directly at [github.com/sponsors/b4nan](https://github.com/sponsors/b4nan).
385
+
385
386
  ## 📝 License
386
387
 
387
388
  Copyright © 2018 [Martin Adámek](https://github.com/b4nan).
package/SourceFile.d.ts CHANGED
@@ -9,11 +9,13 @@ export declare class SourceFile {
9
9
  protected readonly platform: Platform;
10
10
  protected readonly options: GenerateOptions;
11
11
  protected readonly coreImports: Set<string>;
12
+ protected readonly decoratorImports: Set<string>;
12
13
  protected readonly entityImports: Set<string>;
14
+ protected readonly enumImports: Map<string, string[]>;
13
15
  constructor(meta: EntityMetadata, namingStrategy: NamingStrategy, platform: Platform, options: GenerateOptions);
14
16
  generate(): string;
15
- protected getIndexOptions(index: EntityMetadata['indexes'][number], isAtEntityLevel?: boolean): IndexOptions<Dictionary>;
16
- protected getUniqueOptions(index: EntityMetadata['uniques'][number], isAtEntityLevel?: boolean): UniqueOptions<Dictionary>;
17
+ protected getIndexOptions(index: EntityMetadata['indexes'][number], isAtEntityLevel?: boolean): IndexOptions<Dictionary, string>;
18
+ protected getUniqueOptions(index: EntityMetadata['uniques'][number], isAtEntityLevel?: boolean): UniqueOptions<Dictionary, string>;
17
19
  protected generateImports(): string;
18
20
  protected getEntityClass(classBody: string): string;
19
21
  getBaseName(extension?: string): string;
@@ -23,18 +25,19 @@ export declare class SourceFile {
23
25
  protected serializeObject(options: {}, wordwrap?: number, spaces?: number, level?: number): string;
24
26
  protected serializeValue(val: unknown, wordwrap?: number, spaces?: number, level?: number): unknown;
25
27
  protected getEntityDeclOptions(): EntityOptions<unknown>;
26
- protected getEmbeddableDeclOptions(): EmbeddableOptions;
28
+ protected getEmbeddableDeclOptions(): EmbeddableOptions<unknown>;
27
29
  private getCollectionDecl;
28
30
  private getPropertyDecorator;
29
31
  protected getPropertyIndexes(prop: EntityProperty, options: Dictionary): string[];
30
32
  protected getCommonDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
31
33
  private propTypeBreakdowns;
32
34
  private breakdownOfIType;
33
- protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
35
+ protected getScalarPropertyDecoratorOptions(options: Dictionary, prop: EntityProperty, quote?: boolean): void;
34
36
  protected getManyToManyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
35
37
  protected getOneToManyDecoratorOptions(options: Dictionary, prop: EntityProperty): void;
36
38
  protected getEmbeddedPropertyDeclarationOptions(options: Dictionary, prop: EntityProperty): void;
37
39
  protected getForeignKeyDecoratorOptions(options: OneToOneOptions<any, any>, prop: EntityProperty): void;
38
40
  protected getDecoratorType(prop: EntityProperty): string;
39
41
  protected referenceCoreImport(identifier: string): string;
42
+ protected referenceDecoratorImport(identifier: string): string;
40
43
  }