Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
- The `numericRange` option removed from `Documentation` class constructor argument;
- The `brandHandling` should consist of postprocessing functions altering the depiction made by Zod 4;
- The `Depicter` type changed to `Overrider` having different signature;
- The `optionalPropStyle` option removed from `Integration` class constructor:
- Use the new `z.interface()` schema to describe key-optional objects: https://v4.zod.dev/v4#zinterface.

## Version 23

Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,6 @@ import { Integration } from "express-zod-api";
const client = new Integration({
routing,
variant: "client", // <— optional, see also "types" for a DIY solution
optionalPropStyle: { withQuestionMark: true, withUndefined: true }, // optional
});

const prettierFormattedTypescriptCode = await client.printFormatted(); // or just .print() for unformatted
Expand Down
22 changes: 1 addition & 21 deletions express-zod-api/src/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,6 @@ interface IntegrationParams {
* @default https://example.com
* */
serverUrl?: string;
/**
* @desc configures the style of object's optional properties
* @default { withQuestionMark: true, withUndefined: true }
*/
optionalPropStyle?: {
/**
* @desc add question mark to the optional property definition
* @example { someProp?: boolean }
* */
withQuestionMark?: boolean;
/**
* @desc add undefined to the property union type
* @example { someProp: boolean | undefined }
*/
withUndefined?: boolean;
};
/**
* @desc The schema to use for responses without body such as 204
* @default z.undefined()
Expand Down Expand Up @@ -110,14 +94,10 @@ export class Integration extends IntegrationBase {
clientClassName = "Client",
subscriptionClassName = "Subscription",
serverUrl = "https://example.com",
optionalPropStyle = { withQuestionMark: true, withUndefined: true },
noContent = z.undefined(),
}: IntegrationParams) {
super(serverUrl);
const commons = {
makeAlias: this.#makeAlias.bind(this),
optionalPropStyle,
};
const commons = { makeAlias: this.#makeAlias.bind(this) };
const ctxIn = { brandHandling, ctx: { ...commons, isResponse: false } };
const ctxOut = { brandHandling, ctx: { ...commons, isResponse: true } };
const onEndpoint: OnEndpoint = (endpoint, path, method) => {
Expand Down
2 changes: 0 additions & 2 deletions express-zod-api/src/zts-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ export interface ZTSContext extends FlatObject {
schema: $ZodType | (() => $ZodType),
produce: () => ts.TypeNode,
) => ts.TypeNode;
// @todo remove it in favor of z.interface
optionalPropStyle: { withQuestionMark?: boolean; withUndefined?: boolean };
}

export type Producer = SchemaHandler<ts.TypeNode, ZTSContext>;
25 changes: 7 additions & 18 deletions express-zod-api/src/zts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,7 @@ const onInterface: Producer = (int: z.ZodInterface, { next, makeAlias }) =>

const onObject: Producer = (
{ _zod: { def } }: z.ZodObject,
{
isResponse,
next,
optionalPropStyle: { withQuestionMark: hasQuestionMark },
},
{ isResponse, next },
) => {
const members = Object.entries(def.shape).map<ts.TypeElement>(
([key, value]) => {
Expand All @@ -103,7 +99,7 @@ const onObject: Producer = (
return makeInterfaceProp(key, next(value), {
comment,
isDeprecated,
isOptional: isOptional && hasQuestionMark,
isOptional,
});
},
);
Expand Down Expand Up @@ -131,18 +127,11 @@ const onSomeUnion: Producer = (
const makeSample = (produced: ts.TypeNode) =>
samples?.[produced.kind as keyof typeof samples];

const onOptional: Producer = (
{ _zod: { def } }: $ZodOptional,
{ next, optionalPropStyle: { withUndefined: hasUndefined } },
) => {
const actualTypeNode = next(def.innerType);
return hasUndefined
? f.createUnionTypeNode([
actualTypeNode,
ensureTypeNode(ts.SyntaxKind.UndefinedKeyword),
])
: actualTypeNode;
};
const onOptional: Producer = ({ _zod: { def } }: $ZodOptional, { next }) =>
f.createUnionTypeNode([
next(def.innerType),
ensureTypeNode(ts.SyntaxKind.UndefinedKeyword),
]);

const onNullable: Producer = ({ _zod: { def } }: $ZodNullable, { next }) =>
f.createUnionTypeNode([next(def.innerType), makeLiteralType(null)]);
Expand Down
Loading