Skip to content

Commit

Permalink
add discriminator support
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrey Klimenko committed Mar 25, 2024
1 parent b5d6b50 commit 5062e2e
Show file tree
Hide file tree
Showing 16 changed files with 292 additions and 93 deletions.
30 changes: 28 additions & 2 deletions .snapshot/all/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ export enum ProductStatus {
UnderTheOrder = 1
}

export interface ICategory {
interface ICategoryBaseInterface {
name: $types.TypeOrUndefinedNullable<string>;
}

export type ICategory = ICategoryBaseInterface & ICategoryBase;

export interface ICategoryBase {
id: $types.TypeOrUndefinedNullable<string>;
}

export interface IProduct {
category: $types.TypeOrUndefinedNullable<ICategory>;
colors: $types.TypeOrUndefined<string[]>;
Expand All @@ -35,24 +41,44 @@ export class ProductIdentityDTO {
this.id = new Guid(id);
}

public static toDTO(id: Guid): IProductIdentityDTO {
public static toDTO(id: Guid): ICategoryBase {
return { id: id.toString() };
}
}

export class Category {
public id: $types.TypeOrUndefinedNullable<string> = undefined;
public name: $types.TypeOrUndefinedNullable<string> = undefined;
private __category!: string;

public static toDTO(model: Partial<Category>): ICategory {
return {
name: model.name,
id: model.id,
};
}

public static fromDTO(dto: ICategory): Category {
const model = new Category();
model.name = dto.name;
model.id = dto.id;
return model;
}
}

export class CategoryBase {
public id: $types.TypeOrUndefinedNullable<string> = undefined;
private __categoryBase!: string;

public static toDTO(model: Partial<CategoryBase>): ICategoryBase {
return {
id: model.id,
};
}

public static fromDTO(dto: ICategoryBase): CategoryBase {
const model = new CategoryBase();
model.id = dto.id;
return model;
}
}
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@luxbss/gengen",
"version": "1.2.6",
"version": "1.2.7",
"description": "Tool for generating models and Angular services based on OpenAPIs and Swagger's JSON",
"bin": {
"gengen": "./bin/index.js"
Expand Down
81 changes: 76 additions & 5 deletions src/generators/ModelsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import {
} from 'ts-morph';
import { IEnumModel } from '../models/EnumModel';
import { IIdentityModel } from '../models/IdentityModel';
import { IInterfaceModel } from '../models/InterfaceModel';
import { IInterfaceModel, IInterfaceUnionModel } from '../models/InterfaceModel';
import { IModelsContainer } from '../models/ModelsContainer';
import { IObjectModel, IObjectPropertyModel } from '../models/ObjectModel';
import { PropertyKind } from '../models/kinds/PropertyKind';
import { IOptions } from '../options';
import { PathBuilder } from '../services/PathBuilder';
import { lowerFirst } from '../utils';
import { getInterfaceName, lowerFirst } from '../utils';
import { InterfacesGenerator } from './models-generator/InterfacesGenerator';
import { TypeSerializer } from './utils/TypeSerializer';
import { ARRAY_STRING, NULL_STRING, TYPES_NAMESPACE, UNDEFINED_STRING } from './utils/consts';
Expand All @@ -37,6 +37,8 @@ export class ModelsGenerator {
...this.getImports(),
...this.getEnums(models.enums),
...this.interfaceGenerator.getCodeStructure(models.interfaces),
...this.interfaceGenerator.getCodeUnionsStructure(models.unionInterfaces),
...this.getUnionObjects(models.unionInterfaces),
...this.getIdentities(models.identities, models.interfaces),
...this.getObjects(models.objects)
];
Expand Down Expand Up @@ -120,6 +122,71 @@ export class ModelsGenerator {
})
);
}
private getUnionObjects(objects: IInterfaceUnionModel[]): ClassDeclarationStructure[] {
return objects.map((z) => ({
kind: StructureKind.Class,
isExported: true,
name: z.name + 'Class',
properties: [],
methods: [
{
scope: Scope.Public,
isStatic: true,
name: FROM_DTO_METHOD,
parameters: [{ name: 'dto', type: getInterfaceName(z.name) }],
returnType: z.name,
statements: (x) => {
z.unionInterfaces.forEach((i) => {
x.writeLine('if (this.is' + i + '(dto)){');
x.writeLine('return ' + i + '.fromDTO(dto);');
x.writeLine('}');
});

x.writeLine('return ' + z.parentInterface + '.fromDTO(dto);');
}
},

{
scope: Scope.Public,
isStatic: true,
name: TO_DTO_METHOD,
parameters: [{ name: 'model', type: z.name }],
returnType: getInterfaceName(z.name),
statements: (x) => {
z.unionInterfaces.forEach((i) => {
x.writeLine('if (this.is' + getInterfaceName(i) + '(model)){');
x.writeLine('return ' + i + '.toDTO(model);');
x.writeLine('}');
});

x.writeLine('return ' + z.parentInterface + '.toDTO(model);');
}
},

...z.unionInterfaces.map((i) => ({
scope: Scope.Private,
isStatic: true,
name: 'is' + i,
parameters: [{ name: 'dto', type: getInterfaceName(z.name) }],
returnType: 'dto is ' + getInterfaceName(i),
statements: (x: CodeBlockWriter) => {
x.writeLine('return dto.type === ' + z.name + 'Types.' + i + ';');
}
})),

...z.unionInterfaces.map((i) => ({
scope: Scope.Private,
isStatic: true,
name: 'is' + getInterfaceName(i),
parameters: [{ name: 'dto', type: z.name }],
returnType: 'dto is ' + i,
statements: (x: CodeBlockWriter) => {
x.writeLine('return dto.type === ' + z.name + 'Types.' + i + ';');
}
}))
]
}));
}

private getObjects(objects: IObjectModel[]): ClassDeclarationStructure[] {
return objects.map((z) => ({
Expand Down Expand Up @@ -191,7 +258,7 @@ export class ModelsGenerator {
scope: Scope.Public,
name: objectProperty.name,
type: new TypeSerializer({
type: { name: objectProperty.type },
type: { name: objectProperty.typeAlias ?? objectProperty.type },
isNullable: objectProperty.isNullable,
isCollection: objectProperty.isCollection
}).toString(),
Expand Down Expand Up @@ -239,7 +306,9 @@ export class ModelsGenerator {

case PropertyKind.Object:
if (property.isCollection) {
return `${modelProperty} ? ${modelProperty}.map(x => ${property.type}.${TO_DTO_METHOD}(x)) : ${UNDEFINED_STRING}`;
return `${modelProperty} ? ${modelProperty}.map(x => ${
property.dtoTypeAlias ?? property.type
}.${TO_DTO_METHOD}(x)) : ${UNDEFINED_STRING}`;
}

return `${modelProperty} ? ${property.type}.${TO_DTO_METHOD}(${modelProperty}) : ${UNDEFINED_STRING}`;
Expand Down Expand Up @@ -279,7 +348,9 @@ export class ModelsGenerator {

case PropertyKind.Object:
if (property.isCollection) {
return `${dtoProperty} ? ${dtoProperty}.map(x => ${property.type}.${FROM_DTO_METHOD}(x)) : ${ARRAY_STRING}`;
return `${dtoProperty} ? ${dtoProperty}.map(x => ${
property.dtoTypeAlias ?? property.type
}.${FROM_DTO_METHOD}(x)) : ${ARRAY_STRING}`;
}

return `${dtoProperty} ? ${property.type}.${FROM_DTO_METHOD}(${dtoProperty}) : ${UNDEFINED_STRING}`;
Expand Down
23 changes: 22 additions & 1 deletion src/generators/models-generator/InterfacesGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
TypeAliasDeclarationStructure
} from 'ts-morph';

import { IInterfaceModel, IInterfacePropertyModel } from '../../models/InterfaceModel';
import { IInterfaceModel, IInterfacePropertyModel, IInterfaceUnionModel } from '../../models/InterfaceModel';
import { TypeSerializer } from '../utils/TypeSerializer';
import { getInterfaceName } from '../../utils';

export class InterfacesGenerator {
public getCodeStructure(interfaces: IInterfaceModel[]): (InterfaceDeclarationStructure | TypeAliasDeclarationStructure)[] {
Expand Down Expand Up @@ -39,6 +40,26 @@ export class InterfacesGenerator {
return [...baseInterfaces, ...types];
}

public getCodeUnionsStructure(interfaces: IInterfaceUnionModel[]): TypeAliasDeclarationStructure[] {
const classUnion: TypeAliasDeclarationStructure[] = interfaces.map((z) => {
return {
kind: StructureKind.TypeAlias,
type: z.parentInterface + '|' + z.unionInterfaces.join(' | '),
name: z.name,
isExported: true
};
});
const interfacesUnion: TypeAliasDeclarationStructure[] = interfaces.map((z) => {
return {
kind: StructureKind.TypeAlias,
type: getInterfaceName(z.parentInterface) + '|' + z.unionInterfaces.map((x) => getInterfaceName(x)).join(' | '),
name: getInterfaceName(z.name),
isExported: true
};
});
return [...classUnion, ...interfacesUnion];
}

protected getInterfaceProperty(model: IInterfacePropertyModel): OptionalKind<PropertySignatureStructure> {
return {
name: model.name,
Expand Down
2 changes: 1 addition & 1 deletion src/models/EnumModel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface IEnumModel {
name: string;
isNullable: boolean;
items: { key: string; value: number }[];
items: { key: string; value: number | string }[];
}
6 changes: 6 additions & 0 deletions src/models/InterfaceModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ export interface IInterfaceModel {
properties: IInterfacePropertyModel[];
combineInterfaces: string[];
}

export interface IInterfaceUnionModel {
name: string;
parentInterface: string;
unionInterfaces: string[];
}
3 changes: 2 additions & 1 deletion src/models/ModelsContainer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { IEnumModel } from './EnumModel';
import { IIdentityModel } from './IdentityModel';
import { IInterfaceModel } from './InterfaceModel';
import { IInterfaceModel, IInterfaceUnionModel } from './InterfaceModel';
import { IObjectModel } from './ObjectModel';

export interface IModelsContainer {
enums: IEnumModel[];
interfaces: IInterfaceModel[];
unionInterfaces: IInterfaceUnionModel[];
identities: IIdentityModel[];
objects: IObjectModel[];
}
10 changes: 8 additions & 2 deletions src/models/ObjectModel.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { IOpenAPI3Reference } from '../swagger/v3/reference';
import { IType } from './TypeModel';

export interface IObjectPropertyModel extends IType {
name: string;
isNullable: boolean;
isCollection: boolean;
typeAlias?: string;
dtoTypeAlias?: string;
}

export interface IObjectModel {
Expand All @@ -13,5 +14,10 @@ export interface IObjectModel {
isNullable: boolean;
properties: IObjectPropertyModel[];
combineTypes: string[];
combineTypesRefs: IOpenAPI3Reference[];
}

export interface IObjectUnionModel {
name: string;
baseTypeName: string;
unionTypesNames: string[];
}
Loading

0 comments on commit 5062e2e

Please sign in to comment.