Skip to content

Commit

Permalink
Merge pull request #1552 from hey-api/fix/zod-bigint-coerce
Browse files Browse the repository at this point in the history
fix: zod plugin coerces bigint
  • Loading branch information
mrlubos authored Jan 12, 2025
2 parents a22d34f + ceb8bd7 commit 9c9e9c5
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 125 deletions.
5 changes: 5 additions & 0 deletions .changeset/poor-queens-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/openapi-ts': patch
---

fix: use z.coerce before calling z.bigint
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ jobs:

- name: Publish previews
if: matrix.node-version == '22.11.0' && matrix.os == 'ubuntu-latest'
run: pnpx pkg-pr-new publish --compact --pnpm './packages/*'
run: pnpx pkg-pr-new publish --pnpm './packages/*'
38 changes: 19 additions & 19 deletions packages/client-axios/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,46 +135,46 @@ export interface RequestOptions<
}

export type RequestResult<
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = boolean,
> = ThrowOnError extends true
? Promise<AxiosResponse<Data>>
? Promise<AxiosResponse<TData>>
: Promise<
| (AxiosResponse<Data> & { error: undefined })
| (AxiosResponse<TData> & { error: undefined })
| (AxiosError<TError> & { data: undefined; error: TError })
>;

type MethodFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

type RequestFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<ThrowOnError>>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

export interface Client {
/**
* Returns the final request URL. This method works only with experimental parser.
*/
buildUrl: <
Data extends {
TData extends {
body?: unknown;
path?: Record<string, unknown>;
query?: Record<string, unknown>;
url: string;
},
>(
options: Pick<Data, 'url'> & Omit<Options<Data>, 'axios'>,
options: Pick<TData, 'url'> & Omit<Options<TData>, 'axios'>,
) => string;
delete: MethodFn;
get: MethodFn;
Expand All @@ -198,22 +198,22 @@ interface DataShape {
}

export type Options<
Data extends DataShape = DataShape,
TData extends DataShape = DataShape,
ThrowOnError extends boolean = boolean,
> = OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'path' | 'query' | 'url'> &
Omit<Data, 'url'>;
Omit<TData, 'url'>;

export type OptionsLegacyParser<
Data = unknown,
TData = unknown,
ThrowOnError extends boolean = boolean,
> = Data extends { body?: any }
? Data extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & Data
> = TData extends { body?: any }
? TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & TData
: OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'headers'>
: Data extends { headers?: any }
: TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'headers' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'body'>
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & Data;
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & TData;
38 changes: 19 additions & 19 deletions packages/client-fetch/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,18 @@ export interface RequestOptions<
}

export type RequestResult<
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = boolean,
> = ThrowOnError extends true
? Promise<{
data: Data;
data: TData;
request: Request;
response: Response;
}>
: Promise<
(
| { data: Data; error: undefined }
| { data: TData; error: undefined }
| { data: undefined; error: TError }
) & {
request: Request;
Expand All @@ -165,21 +165,21 @@ export type RequestResult<
>;

type MethodFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

type RequestFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<ThrowOnError>>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

export interface Client<
Req = Request,
Expand All @@ -191,14 +191,14 @@ export interface Client<
* Returns the final request URL. This method works only with experimental parser.
*/
buildUrl: <
Data extends {
TData extends {
body?: unknown;
path?: Record<string, unknown>;
query?: Record<string, unknown>;
url: string;
},
>(
options: Pick<Data, 'url'> & Options<Data>,
options: Pick<TData, 'url'> & Options<TData>,
) => string;
connect: MethodFn;
delete: MethodFn;
Expand All @@ -224,22 +224,22 @@ interface DataShape {
}

export type Options<
Data extends DataShape = DataShape,
TData extends DataShape = DataShape,
ThrowOnError extends boolean = boolean,
> = OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'path' | 'query' | 'url'> &
Omit<Data, 'url'>;
Omit<TData, 'url'>;

export type OptionsLegacyParser<
Data = unknown,
TData = unknown,
ThrowOnError extends boolean = boolean,
> = Data extends { body?: any }
? Data extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & Data
> = TData extends { body?: any }
? TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & TData
: OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'headers'>
: Data extends { headers?: any }
: TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'headers' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'body'>
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & Data;
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & TData;
19 changes: 13 additions & 6 deletions packages/openapi-ts/src/plugins/zod/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface Result {
export const zodId = 'zod';

// frequently used identifiers
const coerceIdentifier = compiler.identifier({ text: 'coerce' });
const defaultIdentifier = compiler.identifier({ text: 'default' });
const intersectionIdentifier = compiler.identifier({ text: 'intersection' });
const lazyIdentifier = compiler.identifier({ text: 'lazy' });
Expand Down Expand Up @@ -263,12 +264,18 @@ const numberTypeToZodSchema = ({
}

let numberExpression = compiler.callExpression({
functionName: compiler.propertyAccessExpression({
expression: zIdentifier,
name: isBigInt
? compiler.identifier({ text: 'bigint' })
: compiler.identifier({ text: 'number' }),
}),
functionName: isBigInt
? compiler.propertyAccessExpression({
expression: compiler.propertyAccessExpression({
expression: zIdentifier,
name: coerceIdentifier,
}),
name: compiler.identifier({ text: 'bigint' }),
})
: compiler.propertyAccessExpression({
expression: zIdentifier,
name: compiler.identifier({ text: 'number' }),
}),
});

if (!isBigInt && schema.type === 'integer') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { z } from 'zod';

export const zFoo = z.object({
bar: z.number().int().optional(),
foo: z.bigint(),
foo: z.coerce.bigint(),
id: z.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { z } from 'zod';

export const zFoo = z.object({
bar: z.number().int().optional(),
foo: z.bigint(),
foo: z.coerce.bigint(),
id: z.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { z } from 'zod';

export const zFoo = z.object({
bar: z.number().int().optional(),
foo: z.bigint(),
foo: z.coerce.bigint(),
id: z.string()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export const zFoo = z.object({
z.literal(true)
]).optional(),
corge: z.object({}).optional(),
garply: z.bigint().optional()
garply: z.coerce.bigint().optional()
});
Original file line number Diff line number Diff line change
Expand Up @@ -135,46 +135,46 @@ export interface RequestOptions<
}

export type RequestResult<
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = boolean,
> = ThrowOnError extends true
? Promise<AxiosResponse<Data>>
? Promise<AxiosResponse<TData>>
: Promise<
| (AxiosResponse<Data> & { error: undefined })
| (AxiosResponse<TData> & { error: undefined })
| (AxiosError<TError> & { data: undefined; error: TError })
>;

type MethodFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

type RequestFn = <
Data = unknown,
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
>(
options: Omit<RequestOptions<ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<ThrowOnError>>, 'method'>,
) => RequestResult<Data, TError, ThrowOnError>;
) => RequestResult<TData, TError, ThrowOnError>;

export interface Client {
/**
* Returns the final request URL. This method works only with experimental parser.
*/
buildUrl: <
Data extends {
TData extends {
body?: unknown;
path?: Record<string, unknown>;
query?: Record<string, unknown>;
url: string;
},
>(
options: Pick<Data, 'url'> & Omit<Options<Data>, 'axios'>,
options: Pick<TData, 'url'> & Omit<Options<TData>, 'axios'>,
) => string;
delete: MethodFn;
get: MethodFn;
Expand All @@ -198,22 +198,22 @@ interface DataShape {
}

export type Options<
Data extends DataShape = DataShape,
TData extends DataShape = DataShape,
ThrowOnError extends boolean = boolean,
> = OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'path' | 'query' | 'url'> &
Omit<Data, 'url'>;
Omit<TData, 'url'>;

export type OptionsLegacyParser<
Data = unknown,
TData = unknown,
ThrowOnError extends boolean = boolean,
> = Data extends { body?: any }
? Data extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & Data
> = TData extends { body?: any }
? TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & TData
: OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'headers'>
: Data extends { headers?: any }
: TData extends { headers?: any }
? OmitKeys<RequestOptions<ThrowOnError>, 'headers' | 'url'> &
Data &
TData &
Pick<RequestOptions<ThrowOnError>, 'body'>
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & Data;
: OmitKeys<RequestOptions<ThrowOnError>, 'url'> & TData;
Loading

0 comments on commit 9c9e9c5

Please sign in to comment.