Skip to content

Commit

Permalink
Merge branch 'master' into fix/external-enums
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec authored Oct 23, 2024
2 parents f5e7273 + c45d942 commit a6a9588
Show file tree
Hide file tree
Showing 14 changed files with 1,744 additions and 1,822 deletions.
10 changes: 10 additions & 0 deletions e2e/api-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
"title": "Page",
"format": "int32",
"default": 0,
"example": 123,
"type": "number"
}
},
Expand All @@ -302,6 +303,10 @@
"in": "query",
"schema": {
"nullable": true,
"example": [
"sort1",
"sort2"
],
"type": "array",
"items": {
"type": "string"
Expand Down Expand Up @@ -490,6 +495,7 @@
"title": "Page",
"format": "int32",
"default": 0,
"example": 123,
"type": "number"
}
},
Expand All @@ -499,6 +505,10 @@
"required": true,
"schema": {
"nullable": true,
"example": [
"sort1",
"sort2"
],
"type": "array",
"items": {
"type": "string"
Expand Down
6 changes: 4 additions & 2 deletions e2e/src/cats/dto/pagination-query.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ export class PaginationQuery {
exclusiveMaximum: true,
exclusiveMinimum: true,
format: 'int32',
default: 0
default: 0,
example: 123
})
page: number;

@ApiProperty({
name: '_sortBy',
nullable: true
nullable: true,
example: ['sort1', 'sort2']
})
sortBy: string[];

Expand Down
1 change: 1 addition & 0 deletions lib/decorators/api-header.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function ApiHeader(
in: 'header',
description: options.description,
required: options.required,
examples: options.examples,
schema: {
type: 'string',
...(options.schema || {})
Expand Down
1 change: 1 addition & 0 deletions lib/decorators/api-property.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ApiPropertyOptions
name?: string;
enum?: any[] | Record<string, any> | (() => (any[] | Record<string, any>));
enumName?: string;
'x-enumNames'?: string[]
}

const isEnumArray = (obj: ApiPropertyOptions): boolean =>
Expand Down
9 changes: 9 additions & 0 deletions lib/document-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ export class DocumentBuilder {
return this;
}

public setOpenAPIVersion(version: string): this {
if (version.match(/^\d\.\d\.\d$/)) {
this.document.openapi = version;
} else {
this.logger.warn('The OpenApi version is invalid. Expecting format "x.x.x"');
}
return this;
}

public addServer(
url: string,
description?: string,
Expand Down
129 changes: 70 additions & 59 deletions lib/plugin/visitors/model-class.visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ import {
getExternalImports,
replaceExternalImportsInTypeReference
} from '../utils/external-imports.util';
import {
decoratorsProperties,
decoratorsPropertiesMappingType
} from '../../services/decorators-properties';

type ClassMetadata = Record<string, ts.ObjectLiteralExpression>;

Expand Down Expand Up @@ -661,66 +665,73 @@ export class ModelClassVisitor extends AbstractFileVisitor {
options
);
}
this.addPropertyByValidationDecorator(
factory,
'Min',
'minimum',
decorators,
assignments,
options
);
this.addPropertyByValidationDecorator(
factory,
'Max',
'maximum',
decorators,
assignments,
options
);
this.addPropertyByValidationDecorator(
factory,
'MinLength',
'minLength',
decorators,
assignments,
options
);
this.addPropertyByValidationDecorator(
factory,
'MaxLength',
'maxLength',
decorators,
assignments,
options
);
this.addPropertiesByValidationDecorator(
factory,
'IsPositive',
decorators,
assignments,
() => {
return [
factory.createPropertyAssignment(
'minimum',
createPrimitiveLiteral(factory, 1)
)
];
}
);
this.addPropertiesByValidationDecorator(
factory,
'IsNegative',
decorators,
assignments,
() => {
return [
factory.createPropertyAssignment(
'maximum',
createPrimitiveLiteral(factory, -1)
)
];

decoratorsProperties.forEach((decoratorProperty) => {
if (
decoratorProperty.mappingType === decoratorsPropertiesMappingType.DIRECT
) {
this.addPropertyByValidationDecorator(
factory,
decoratorProperty.decorator,
decoratorProperty.property,
decorators,
assignments,
options
);
} else if (
decoratorProperty.mappingType ===
decoratorsPropertiesMappingType.INDIRECT_VALUE
) {
this.addPropertiesByValidationDecorator(
factory,
decoratorProperty.decorator,
decorators,
assignments,
() => {
return [
factory.createPropertyAssignment(
decoratorProperty.property,
createPrimitiveLiteral(factory, decoratorProperty.value)
)
];
}
);
} else if (
decoratorProperty.mappingType ===
decoratorsPropertiesMappingType.INDIRECT_ARGUMENT
) {
this.addPropertiesByValidationDecorator(
factory,
decoratorProperty.decorator,
decorators,
assignments,
(decoratorRef: ts.Decorator) => {
const decoratorArguments = getDecoratorArguments(decoratorRef);
const result = [];

const argumentValue = head(decoratorArguments);
if (!canReferenceNode(argumentValue, options)) {
return result;
}

const clonedArgumentValue = this.clonePrimitiveLiteral(
factory,
argumentValue
);
if (clonedArgumentValue) {
result.push(
factory.createPropertyAssignment(
decoratorProperty.property,
clonedArgumentValue
)
);
}
return result;
}
);
}
);
});

this.addPropertiesByValidationDecorator(
factory,
'Length',
Expand Down
145 changes: 145 additions & 0 deletions lib/services/decorators-properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
export enum decoratorsPropertiesMappingType {
DIRECT,
INDIRECT_VALUE,
INDIRECT_ARGUMENT
}
export const decoratorsProperties = [
{
mappingType: decoratorsPropertiesMappingType.DIRECT,
decorator: 'Min',
property: 'minimum',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.DIRECT,
decorator: 'Max',
property: 'maximum',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.DIRECT,
decorator: 'MinLength',
property: 'minLength',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.DIRECT,
decorator: 'MaxLength',
property: 'maxLength',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'ArrayNotEmpty',
property: 'minItems',
value: 1
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsPositive',
property: 'minimum',
value: 1
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsNegative',
property: 'maximum',
value: -1
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'ArrayUnique',
property: 'uniqueItems',
value: true
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsBase64',
property: 'format',
value: 'base64'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsCreditCard',
property: 'format',
value: 'credit-card'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsCurrency',
property: 'format',
value: 'currency'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsEmail',
property: 'format',
value: 'email'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsJSON',
property: 'format',
value: 'json'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsUrl',
property: 'format',
value: 'uri'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsUuid',
property: 'format',
value: 'uuid'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsMobilePhone',
property: 'format',
value: 'mobile-phone'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsAscii',
property: 'pattern',
value: '^[\\x00-\\x7F]+$'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsHexColor',
property: 'pattern',
value: '^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_VALUE,
decorator: 'IsHexadecimal',
property: 'pattern',
value: '^(0x|0h)?[0-9A-F]+$'
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_ARGUMENT,
decorator: 'ArrayMinSize',
property: 'minItems',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_ARGUMENT,
decorator: 'ArrayMaxSize',
property: 'maxItems',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_ARGUMENT,
decorator: 'IsDivisibleBy',
property: 'multipleOf',
value: undefined
},
{
mappingType: decoratorsPropertiesMappingType.INDIRECT_ARGUMENT,
decorator: 'Contains',
property: 'pattern',
value: undefined
}
];
Loading

0 comments on commit a6a9588

Please sign in to comment.