diff --git a/lib/decorators/api-property.decorator.ts b/lib/decorators/api-property.decorator.ts index 11ad63557..4d500b30a 100644 --- a/lib/decorators/api-property.decorator.ts +++ b/lib/decorators/api-property.decorator.ts @@ -84,6 +84,10 @@ export function createApiPropertyDecorator( }; } + if (options.pattern instanceof RegExp) { + options.pattern = options.pattern.source; + } + return createPropertyDecorator( DECORATORS.API_MODEL_PROPERTIES, options, diff --git a/lib/interfaces/schema-object-metadata.interface.ts b/lib/interfaces/schema-object-metadata.interface.ts index dee1bdf1b..003976a1f 100644 --- a/lib/interfaces/schema-object-metadata.interface.ts +++ b/lib/interfaces/schema-object-metadata.interface.ts @@ -7,10 +7,13 @@ export type EnumAllowedTypes = | Record | (() => any[] | Record); -interface SchemaObjectCommonMetadata - extends Omit { +interface SchemaObjectCommonMetadata extends Omit< + SchemaObject, + 'type' | 'required' | 'properties' | 'enum' | 'pattern' +> { isArray?: boolean; name?: string; + pattern?: string | RegExp; enum?: EnumAllowedTypes; } diff --git a/test/services/schema-object-factory.spec.ts b/test/services/schema-object-factory.spec.ts index 371a8713d..8d542343c 100644 --- a/test/services/schema-object-factory.spec.ts +++ b/test/services/schema-object-factory.spec.ts @@ -421,6 +421,69 @@ describe('SchemaObjectFactory', () => { }); }); + it('should convert RegExp pattern to string in schema', () => { + class RegExpPatternDto { + @ApiProperty({ pattern: /^[+]?abc$/ }) + code: string; + } + + const schemas: Record = {}; + schemaObjectFactory.exploreModelSchema(RegExpPatternDto, schemas); + + expect(schemas[RegExpPatternDto.name]).toEqual({ + type: 'object', + properties: { + code: { + type: 'string', + pattern: '^[+]?abc$' + } + }, + required: ['code'] + }); + }); + + it('should strip flags when converting RegExp pattern', () => { + class RegExpFlagsDto { + @ApiProperty({ pattern: /abc/i }) + value: string; + } + + const schemas: Record = {}; + schemaObjectFactory.exploreModelSchema(RegExpFlagsDto, schemas); + + expect(schemas[RegExpFlagsDto.name]).toEqual({ + type: 'object', + properties: { + value: { + type: 'string', + pattern: 'abc' + } + }, + required: ['value'] + }); + }); + + it('should keep string pattern unchanged', () => { + class StringPatternDto { + @ApiProperty({ pattern: '^[a-z]+$' }) + slug: string; + } + + const schemas: Record = {}; + schemaObjectFactory.exploreModelSchema(StringPatternDto, schemas); + + expect(schemas[StringPatternDto.name]).toEqual({ + type: 'object', + properties: { + slug: { + type: 'string', + pattern: '^[a-z]+$' + } + }, + required: ['slug'] + }); + }); + it('should override base class metadata', () => { class CreatUserDto { @ApiProperty({ minLength: 0, required: true })