Skip to content

Commit

Permalink
feat(@nestjs/swagger): Allow custom schema naming
Browse files Browse the repository at this point in the history
You can use @ApiSchema to set a custom schema name.
Custom schema names are not inherited.
  • Loading branch information
Stefan Radacovsky authored and mothershipper committed May 12, 2023
1 parent be70eb0 commit aad9825
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
3 changes: 2 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export const DECORATORS = {
API_EXCLUDE_ENDPOINT: `${DECORATORS_PREFIX}/apiExcludeEndpoint`,
API_EXCLUDE_CONTROLLER: `${DECORATORS_PREFIX}/apiExcludeController`,
API_EXTRA_MODELS: `${DECORATORS_PREFIX}/apiExtraModels`,
API_EXTENSION: `${DECORATORS_PREFIX}/apiExtension`
API_EXTENSION: `${DECORATORS_PREFIX}/apiExtension`,
API_SCHEMA: `${DECORATORS_PREFIX}/apiSchema`
};
20 changes: 20 additions & 0 deletions lib/decorators/api-schema.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { DECORATORS } from '../constants';
import { SchemaObjectMetadata } from '../interfaces/schema-object-metadata.interface';
import { createClassDecorator, createPropertyDecorator } from './helpers';

export interface ApiSchemaOptions extends Pick<SchemaObjectMetadata, 'name'> {
/**
* Name of the schema.
*/
name: string;
}

export function ApiSchema(options: ApiSchemaOptions): ClassDecorator {
return createApiSchemaDecorator(options);
}

export function createApiSchemaDecorator(
options: ApiSchemaOptions
): ClassDecorator {
return createClassDecorator(DECORATORS.API_SCHEMA, [options]);
}
1 change: 1 addition & 0 deletions lib/decorators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export * from './api-response.decorator';
export * from './api-security.decorator';
export * from './api-use-tags.decorator';
export * from './api-extension.decorator';
export * from './api-schema.decorator';
13 changes: 11 additions & 2 deletions lib/services/schema-object-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
pick
} from 'lodash';
import { DECORATORS } from '../constants';
import { ApiSchemaOptions } from '../decorators';
import { getTypeIsArrayTuple } from '../decorators/helpers';
import { exploreGlobalApiExtraModelsMetadata } from '../explorers/api-extra-models.explorer';
import {
Expand Down Expand Up @@ -203,8 +204,16 @@ export class SchemaObjectFactory {
if (typeDefinitionRequiredFields.length > 0) {
typeDefinition['required'] = typeDefinitionRequiredFields;
}
schemas[type.name] = typeDefinition;
return type.name;
const customSchema: ApiSchemaOptions[] = Reflect.getOwnMetadata(
DECORATORS.API_SCHEMA,
type
);
const schemaName =
customSchema && customSchema.length === 1
? customSchema[0].name
: type.name;
schemas[schemaName] = typeDefinition;
return schemaName;
}

mergePropertyWithMetadata(
Expand Down
30 changes: 29 additions & 1 deletion test/services/schema-object-factory.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApiProperty } from '../../lib/decorators';
import { ApiProperty, ApiSchema } from '../../lib/decorators';
import { SchemasObject } from '../../lib/interfaces/open-api-spec.interface';
import { ModelPropertiesAccessor } from '../../lib/services/model-properties-accessor';
import { SchemaObjectFactory } from '../../lib/services/schema-object-factory';
Expand Down Expand Up @@ -265,5 +265,33 @@ describe('SchemaObjectFactory', () => {
properties: { name: { type: 'string', minLength: 1 } }
});
});

it('should use schema name instead of class name', () => {
@ApiSchema({
name: 'CreateUser'
})
class CreateUserDto {}

const schemas = [];

schemaObjectFactory.exploreModelSchema(CreateUserDto, schemas);

expect(Object.keys(schemas[0])[0]).toEqual('CreateUser');
});

it('should not use schema name of base class', () => {
@ApiSchema({
name: 'CreateUser'
})
class CreateUserDto {}

class UpdateUserDto extends CreateUserDto {}

const schemas = [];

schemaObjectFactory.exploreModelSchema(UpdateUserDto, schemas);

expect(Object.keys(schemas[0])[0]).toEqual('UpdateUserDto');
});
});
});

0 comments on commit aad9825

Please sign in to comment.