Skip to content

Commit

Permalink
added support for effects in request params
Browse files Browse the repository at this point in the history
  • Loading branch information
AGalabov committed Apr 3, 2024
1 parent 2fff075 commit 56995bf
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 37 deletions.
104 changes: 91 additions & 13 deletions spec/routes/parameters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,41 @@ describe('parameters', () => {
]);
});

it('generates a deepPartial object query parameter for route', () => {
it('generates query parameter for route from object with refine', () => {
const { parameters } = generateDataForRoute({
request: {
query: z
.object({
filter: z
.object({ test: z.string() })
.openapi({ param: { style: 'deepObject' } }),
filter: z.string(),
})
.deepPartial(),
.refine(({ filter }) => filter.length > 3),
},
});

expect(parameters).toEqual([
{
in: 'query',
name: 'filter',
required: false,
style: 'deepObject',
required: true,
schema: {
type: 'object',
properties: {
test: {
type: 'string',
},
},
type: 'string',
},
},
]);
});

it('generates a query parameter for route', () => {
const { parameters } = generateDataForRoute({
request: { query: z.object({ test: z.string() }) },
});

expect(parameters).toEqual([
{
in: 'query',
name: 'test',
required: true,
schema: {
type: 'string',
},
},
]);
Expand Down Expand Up @@ -133,6 +142,29 @@ describe('parameters', () => {
]);
});

it('generates path parameter for route from object with refine', () => {
const { parameters } = generateDataForRoute({
request: {
params: z
.object({
filter: z.string(),
})
.refine(({ filter }) => filter.length > 3),
},
});

expect(parameters).toEqual([
{
in: 'path',
name: 'filter',
required: true,
schema: {
type: 'string',
},
},
]);
});

it('generates a reference path parameter for route', () => {
const TestParam = registerParameter(
'TestParam',
Expand Down Expand Up @@ -212,6 +244,29 @@ describe('parameters', () => {
]);
});

it('generates cookie parameter for route from object with refine', () => {
const { parameters } = generateDataForRoute({
request: {
cookies: z
.object({
filter: z.string(),
})
.refine(({ filter }) => filter.length > 3),
},
});

expect(parameters).toEqual([
{
in: 'cookie',
name: 'filter',
required: true,
schema: {
type: 'string',
},
},
]);
});

it('generates a reference cookie parameter for route', () => {
const TestParam = registerParameter(
'TestParam',
Expand Down Expand Up @@ -312,6 +367,29 @@ describe('parameters', () => {
]);
});

it('generates header parameter for route from object with refine', () => {
const { parameters } = generateDataForRoute({
request: {
headers: z
.object({
filter: z.string(),
})
.refine(({ filter }) => filter.length > 3),
},
});

expect(parameters).toEqual([
{
in: 'header',
name: 'filter',
required: true,
schema: {
type: 'string',
},
},
]);
});

it('generates a reference header parameter for route', () => {
const TestHeader = registerParameter(
'TestHeader',
Expand Down
54 changes: 35 additions & 19 deletions src/openapi-generator.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import type { AnyZodObject, ZodRawShape, ZodType, ZodTypeAny } from 'zod';
import type {
AnyZodObject,
ZodEffects,
ZodRawShape,
ZodType,
ZodTypeAny,
} from 'zod';
import {
ConflictError,
MissingParameterDataError,
enhanceMissingParametersError,
} from './errors';
import {
compact,
isNil,
mapValues,
objectEquals,
omit,
omitBy,
} from './lib/lodash';
import { compact, isNil, mapValues, objectEquals, omitBy } from './lib/lodash';
import { isAnyZodType, isZodType } from './lib/zod-is-type';
import {
OpenAPIComponentObject,
Expand All @@ -21,7 +20,7 @@ import {
ZodContentObject,
ZodRequestBody,
} from './openapi-registry';
import { ZodOpenApiFullMetadata, ZodOpenAPIMetadata } from './zod-extensions';
import { ZodOpenApiFullMetadata } from './zod-extensions';
import {
BaseParameterObject,
ComponentsObject,
Expand Down Expand Up @@ -500,7 +499,11 @@ export class OpenAPIGenerator {
return [];
}

const { query, params, headers, cookies } = request;
const { headers } = request;

const query = this.cleanParameter(request.query);
const params = this.cleanParameter(request.params);
const cookies = this.cleanParameter(request.cookies);

const queryParameters = enhanceMissingParametersError(
() => (query ? this.generateInlineParameters(query, 'query') : []),
Expand All @@ -518,14 +521,17 @@ export class OpenAPIGenerator {
);

const headerParameters = enhanceMissingParametersError(
() =>
headers
? isZodType(headers, 'ZodObject')
? this.generateInlineParameters(headers, 'header')
: headers.flatMap(header =>
this.generateInlineParameters(header, 'header')
)
: [],
() => {
if (Array.isArray(headers)) {
return headers.flatMap(header =>
this.generateInlineParameters(header, 'header')
);
}
const cleanHeaders = this.cleanParameter(headers);
return cleanHeaders
? this.generateInlineParameters(cleanHeaders, 'header')
: [];
},
{ location: 'header' }
);

Expand All @@ -537,6 +543,16 @@ export class OpenAPIGenerator {
];
}

private cleanParameter(
schema: AnyZodObject | ZodEffects<AnyZodObject> | undefined
) {
if (!schema) {
return undefined;
}

return isZodType(schema, 'ZodEffects') ? schema._def.schema : schema;
}

generatePath(route: RouteConfig): PathItemObject {
const { method, path, request, responses, ...pathItemConfig } = route;

Expand Down
10 changes: 5 additions & 5 deletions src/openapi-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type ResponseObject = ResponseObject30 | ResponseObject31;
type SchemaObject = SchemaObject30 | SchemaObject31;
type SecuritySchemeObject = SecuritySchemeObject30 | SecuritySchemeObject31;

import type { AnyZodObject, ZodType, ZodTypeAny } from 'zod';
import type { AnyZodObject, ZodEffects, ZodType, ZodTypeAny } from 'zod';

type Method =
| 'get'
Expand Down Expand Up @@ -107,10 +107,10 @@ export type RouteConfig = Omit<OperationObject, 'responses'> & {
path: string;
request?: {
body?: ZodRequestBody;
params?: AnyZodObject;
query?: AnyZodObject;
cookies?: AnyZodObject;
headers?: AnyZodObject | ZodType<unknown>[];
params?: AnyZodObject | ZodEffects<AnyZodObject>;
query?: AnyZodObject | ZodEffects<AnyZodObject>;
cookies?: AnyZodObject | ZodEffects<AnyZodObject>;
headers?: AnyZodObject | ZodEffects<AnyZodObject> | ZodType<unknown>[];
};
responses: {
[statusCode: string]: ResponseConfig;
Expand Down

0 comments on commit 56995bf

Please sign in to comment.