Skip to content

Commit

Permalink
feat(entity-generator): allow generating identified references
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed Jun 8, 2022
1 parent 5203ee7 commit 1fbf5ac
Show file tree
Hide file tree
Showing 6 changed files with 606 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/docs/entity-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ $ ts-node generate-entities

## Advanced

By default, the `EntityGenerator` generates only owning sides of relations (e.g. M:1). We can configure it via `entityGenerator: { bidirectionalRelations: true }` to generate also the inverse sides for them.
By default, the `EntityGenerator` generates only owning sides of relations (e.g. M:1). We can configure it via `entityGenerator: { bidirectionalRelations: true }` to generate also the inverse sides for them. To generate M:1 and 1:1 relations as wrapped references, use `entityGenerator: { identifiedReferences: true }`.

## Current limitations

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/utils/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export class Configuration<D extends IDatabaseDriver = IDatabaseDriver> {
},
entityGenerator: {
bidirectionalRelations: false,
identifiedReferences: false,
},
cache: {
pretty: false,
Expand Down Expand Up @@ -481,6 +482,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver> ex
};
entityGenerator: {
bidirectionalRelations?: boolean;
identifiedReferences?: boolean;
};
cache: {
enabled?: boolean;
Expand Down
14 changes: 14 additions & 0 deletions packages/entity-generator/src/EntityGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export class EntityGenerator {
this.generateBidirectionalRelations(metadata);
}

if (this.config.get('entityGenerator').identifiedReferences) {
this.generateIdentifiedReferences(metadata);
}

for (const meta of metadata) {
if (!meta.pivotTable) {
this.sources.push(new SourceFile(meta, this.namingStrategy, this.platform));
Expand Down Expand Up @@ -98,4 +102,14 @@ export class EntityGenerator {
}
}

private generateIdentifiedReferences(metadata: EntityMetadata[]): void {
for (const meta of metadata.filter(m => !m.pivotTable)) {
for (const prop of meta.relations) {
if ([ReferenceType.MANY_TO_ONE, ReferenceType.ONE_TO_ONE].includes(prop.reference)) {
prop.wrappedReference = true;
}
}
}
}

}
10 changes: 10 additions & 0 deletions packages/entity-generator/src/SourceFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ export class SourceFile {
const isEnumOrNonStringDefault = prop.enum || typeof prop.default !== 'string';
const useDefault = prop.default != null && isEnumOrNonStringDefault;
const optional = prop.nullable ? '?' : (useDefault ? '' : '!');

if (prop.wrappedReference) {
this.coreImports.add('IdentifiedReference');
return `${padding}${prop.name}${optional}: IdentifiedReference<${prop.type}>;\n`;
}

const ret = `${prop.name}${optional}: ${prop.type}`;

if (!useDefault) {
Expand Down Expand Up @@ -284,6 +290,10 @@ export class SourceFile {
this.entityImports.add(className);
options.entity = `() => ${className}`;

if (prop.wrappedReference) {
options.wrappedReference = true;
}

if (prop.mappedBy) {
options.mappedBy = this.quote(prop.mappedBy);
return;
Expand Down
16 changes: 16 additions & 0 deletions tests/features/entity-generator/EntityGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ describe('EntityGenerator', () => {
await orm.close(true);
});

test('generate entities with bidirectional relations and reference wrappers [mysql]', async () => {
const orm = await initORMMySql('mysql', {
entityGenerator: {
bidirectionalRelations: true,
identifiedReferences: true,
},
}, true);
const generator = orm.getEntityGenerator();
const dump = await generator.generate({ save: true, baseDir: './temp/entities' });
expect(dump).toMatchSnapshot('mysql-entity-bidirectional-dump');
await expect(pathExists('./temp/entities/Author2.ts')).resolves.toBe(true);
await remove('./temp/entities');

await orm.close(true);
});

test('generate entities from schema [sqlite]', async () => {
const orm = await initORMSqlite();
const generator = new EntityGenerator(orm.em);
Expand Down
Loading

0 comments on commit 1fbf5ac

Please sign in to comment.