Skip to content

Commit

Permalink
Merge pull request #3148 from nestjs/fix/query-params-3144
Browse files Browse the repository at this point in the history
fix: spread query parameters if feasible #3144
  • Loading branch information
kamilmysliwiec authored Nov 5, 2024
2 parents d2eac71 + 8e45aa8 commit f23dd40
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 124 deletions.
192 changes: 100 additions & 92 deletions e2e/api-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -666,11 +666,109 @@
}
},
{
"name": "PaginationQuery",
"name": "page",
"in": "query",
"required": true,
"schema": {
"minimum": 0,
"maximum": 10000,
"exclusiveMaximum": true,
"exclusiveMinimum": true,
"title": "Page",
"format": "int32",
"default": 0,
"example": 123
}
},
{
"name": "_sortBy",
"in": "query",
"required": true,
"schema": {
"nullable": true,
"example": [
"sort1",
"sort2"
]
}
},
{
"name": "limit",
"in": "query",
"required": true,
"schema": {
"$ref": "#/components/schemas/PaginationQuery"
"type": "number"
}
},
{
"name": "constrainedLimit",
"in": "query",
"required": true,
"schema": {
"oneOf": [
{
"minimum": 0,
"maximum": 10,
"format": "int32"
},
{
"minimum": 100,
"maximum": 100,
"format": "int32"
}
]
}
},
{
"name": "enum",
"in": "query",
"required": true,
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/LettersEnum"
}
]
}
},
{
"name": "enumArr",
"in": "query",
"required": true,
"schema": {
"type": "array"
}
},
{
"name": "letters",
"in": "query",
"required": true,
"schema": {
"type": "array"
}
},
{
"name": "beforeDate",
"in": "query",
"required": true,
"schema": {
"format": "date-time"
}
},
{
"name": "filter",
"in": "query",
"required": true,
"schema": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"additionalProperties": true
}
},
{
Expand Down Expand Up @@ -1526,96 +1624,6 @@
],
"description": "This is a description for the Letters schema",
"deprecated": true
},
"PaginationQuery": {
"type": "object",
"properties": {
"page": {
"type": "number",
"minimum": 0,
"maximum": 10000,
"title": "Page",
"exclusiveMaximum": true,
"exclusiveMinimum": true,
"format": "int32",
"default": 0,
"example": 123
},
"_sortBy": {
"nullable": true,
"example": [
"sort1",
"sort2"
],
"type": "array",
"items": {
"type": "string"
}
},
"limit": {
"type": "number"
},
"constrainedLimit": {
"oneOf": [
{
"minimum": 0,
"maximum": 10,
"format": "int32"
},
{
"minimum": 100,
"maximum": 100,
"format": "int32"
}
]
},
"enum": {
"allOf": [
{
"$ref": "#/components/schemas/LettersEnum"
}
]
},
"enumArr": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LettersEnum"
}
},
"letters": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Letter"
}
},
"beforeDate": {
"format": "date-time",
"type": "string"
},
"filter": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"additionalProperties": true
}
},
"required": [
"page",
"_sortBy",
"limit",
"constrainedLimit",
"enum",
"enumArr",
"letters",
"beforeDate",
"filter"
]
}
}
},
Expand Down
46 changes: 41 additions & 5 deletions lib/services/schema-object-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,47 @@ export class SchemaObjectFactory {
};
}
if (isFunction(param.type)) {
return this.getCustomType(param, schemas);
if (param.name) {
// We should not spread parameters that have a name
// Just generate the schema for the type instead and link it with ref if needed
return this.getCustomType(param, schemas);
}

const propertiesWithType = this.extractPropertiesFromType(
param.type,
schemas
);
if (!propertiesWithType) {
return param;
}

return propertiesWithType.map(
(property: ParameterObject & ParamWithTypeMetadata) => {
const keysToOmit = [
'isArray',
'enumName',
'enumSchema',
'selfRequired'
];
const parameterObject = {
...(omit(property, keysToOmit) as ParameterObject),
in: 'query',
required: property.required ?? true
};

const keysToMoveToSchema = [
...this.swaggerTypesMapper.getSchemaOptionsKeys(),
'allOf'
];
return keysToMoveToSchema.reduce((acc, key) => {
if (key in property) {
acc.schema = { ...acc.schema, [key]: property[key] };
delete acc[key];
}
return acc;
}, parameterObject);
}
) as ParameterObject[];
}
return param;
}
Expand Down Expand Up @@ -734,8 +774,4 @@ export class SchemaObjectFactory {
];
return [pick(metadata, modifierKeys), modifierKeys];
}

private hasRawContent(metadata: SchemaObjectMetadata) {
return 'content' in metadata;
}
}
54 changes: 27 additions & 27 deletions lib/services/swagger-types-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,33 @@ export class SwaggerTypesMapper {
};
}

getSchemaOptionsKeys(): Array<keyof SchemaObject> {
return [
'properties',
'patternProperties',
'additionalProperties',
'minimum',
'maximum',
'maxProperties',
'minItems',
'minProperties',
'maxItems',
'minLength',
'maxLength',
'exclusiveMaximum',
'exclusiveMinimum',
'uniqueItems',
'title',
'format',
'pattern',
'nullable',
'default',
'example',
'oneOf',
'anyOf'
];
}

private getSchemaOptions(param: Record<string, any>): Partial<SchemaObject> {
const schemaKeys = this.getSchemaOptionsKeys();
const optionsObject: Partial<SchemaObject> = schemaKeys.reduce(
Expand Down Expand Up @@ -152,31 +179,4 @@ export class SwaggerTypesMapper {
private omitParamKeys(param: ParamWithTypeMetadata | BaseParameterObject) {
return omit(param, this.keysToRemove);
}

private getSchemaOptionsKeys(): Array<keyof SchemaObject> {
return [
'properties',
'patternProperties',
'additionalProperties',
'minimum',
'maximum',
'maxProperties',
'minItems',
'minProperties',
'maxItems',
'minLength',
'maxLength',
'exclusiveMaximum',
'exclusiveMinimum',
'uniqueItems',
'title',
'format',
'pattern',
'nullable',
'default',
'example',
'oneOf',
'anyOf'
];
}
}

0 comments on commit f23dd40

Please sign in to comment.