Skip to content

Commit

Permalink
feat: Allow non-object JSON responses
Browse files Browse the repository at this point in the history
* allow non-object JSON responses

* add basic type tests
  • Loading branch information
mxsdev authored Aug 15, 2023
1 parent 78f95b1 commit 25d62b0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 15 deletions.
4 changes: 3 additions & 1 deletion packages/nextlove/src/generators/generate-openapi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ export async function generateOpenAPI(opts: GenerateOpenAPIOpts) {
}

const responseSchema = generateSchema(
addOkStatus ? jsonResponse.extend({ ok: z.boolean() }) : jsonResponse
addOkStatus && jsonResponse instanceof z.ZodObject
? jsonResponse.extend({ ok: z.boolean() })
: jsonResponse
)

const schemaWithReferences = embedSchemaReferences(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ export const generateRouteTypes = async (opts: GenerateRouteTypesOpts) => {
routeSpec.jsonResponse
? printNode(
zodToTs(
setupParams.addOkStatus
setupParams.addOkStatus &&
routeSpec.jsonResponse instanceof z.ZodObject
? routeSpec.jsonResponse.extend({ ok: z.boolean() })
: routeSpec.jsonResponse
).node
Expand Down
15 changes: 2 additions & 13 deletions packages/nextlove/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface RouteSpec<
QueryParams extends ParamDef = z.ZodObject<any, any, any, any, any>,
CommonParams extends ParamDef = z.ZodObject<any, any, any, any, any>,
Middlewares extends readonly Middleware<any, any>[] = any[],
JsonResponse extends ParamDef = z.ZodObject<any, any, any, any, any>,
JsonResponse extends ParamDef = z.ZodTypeAny,
FormData extends ParamDef = z.ZodTypeAny
> {
methods: Methods
Expand Down Expand Up @@ -148,17 +148,6 @@ export type CreateWithRouteSpecFunction = <
SP extends SetupParams<AuthMiddlewares, any>
>(
setupParams: SP
) => <
RS extends RouteSpec<
string,
any,
any,
any,
any,
any,
z.ZodObject<any, any, any, any, any>,
any
>
>(
) => <RS extends RouteSpec<string, any, any, any, any, any, z.ZodTypeAny, any>>(
route_spec: RS
) => (next: RouteFunction<SP, RS>) => any
41 changes: 41 additions & 0 deletions packages/nextlove/tests/route-spec-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,44 @@ export const myRoute7 = withRouteSpec(myRoute7Spec)(async (req, res) => {
const errorApiResponse400 = res.status(400)
expectTypeOf(errorApiResponse400.json).toMatchTypeOf<(body: any) => void>()
})

export const myRoute8Spec = {
auth: "none",
methods: ["GET"],
jsonResponse: z.array(z.object({ id: z.string() })),
}

export const myRoute8 = withRouteSpec(myRoute8Spec)(async (req, res) => {
const sucessfulApiResponse200 = res.status(200)
expectTypeOf(sucessfulApiResponse200.json).toMatchTypeOf<
(body: { id: string }[]) => void
>()
const sucessfulApiResponse201 = res.status(201)
expectTypeOf(sucessfulApiResponse201.json).toMatchTypeOf<
(body: { id: string }[]) => void
>()
const errorApiResponse400 = res.status(400)
expectTypeOf(errorApiResponse400.json).toMatchTypeOf<(body: any) => void>()
})

export const myRoute9Spec = {
auth: "none",
methods: ["GET"],
jsonResponse: z.union([
z.object({ id: z.string() }),
z.object({ name: z.string() }),
]),
}

export const myRoute9 = withRouteSpec(myRoute9Spec)(async (req, res) => {
const sucessfulApiResponse200 = res.status(200)
expectTypeOf(sucessfulApiResponse200.json).toMatchTypeOf<
(body: { id: string } | { name: string }) => void
>()
const sucessfulApiResponse201 = res.status(201)
expectTypeOf(sucessfulApiResponse201.json).toMatchTypeOf<
(body: { id: string } | { name: string }) => void
>()
const errorApiResponse400 = res.status(400)
expectTypeOf(errorApiResponse400.json).toMatchTypeOf<(body: any) => void>()
})

0 comments on commit 25d62b0

Please sign in to comment.