From 8688e9f04a6ed44004539560deba3100e5a8a9f5 Mon Sep 17 00:00:00 2001 From: Piet Groot Kormelink Date: Wed, 27 Apr 2022 22:05:27 +0200 Subject: [PATCH 1/5] add localized bool schema support --- README.md | 18 +++++++++++++++++ deno/lib/__tests__/localize.test.ts | 11 ++++++++++ deno/lib/types.ts | 31 ++++++++++++++++++++++++++--- src/__tests__/localize.test.ts | 10 ++++++++++ src/types.ts | 31 ++++++++++++++++++++++++++--- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 deno/lib/__tests__/localize.test.ts create mode 100644 src/__tests__/localize.test.ts diff --git a/README.md b/README.md index ecd04b222..79685dfda 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,8 @@ These docs have been translated into [Chinese](./README_ZH.md). - [.promise](#promise) - [.or](#or) - [.and](#and) + - [.describe](#describe) + - [.localize](#localize) - [Guides and concepts](#guides-and-concepts) - [Type inference](#type-inference) - [Writing generic functions](#writing-generic-functions) @@ -1694,6 +1696,22 @@ const nullishString = z.string().nullish(); // string | null | undefined z.string().optional().nullable(); ``` +### `.localize` + +A schema method that defines that the schema should be translated. + +```ts +const isLocalized = z.string().localize(true).localized; // boolean +``` + +### `.describe` + +A schema method that adds a description to the schema for documentation purpose. + +```ts +const description = z.string().describe('usefull description').description; // string +``` + ### `.array` A convenience method that returns an array schema for the given type: diff --git a/deno/lib/__tests__/localize.test.ts b/deno/lib/__tests__/localize.test.ts new file mode 100644 index 000000000..e8e8fb33e --- /dev/null +++ b/deno/lib/__tests__/localize.test.ts @@ -0,0 +1,11 @@ +// @ts-ignore TS6133 +import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; +const test = Deno.test; + +import * as z from "../index.ts"; + +test("localize", () => { + const localized = true; + const schema = z.string().localize(localized); + expect(schema.localized).toEqual(localized); +}); diff --git a/deno/lib/types.ts b/deno/lib/types.ts index ee8bd6f27..a0ea1484c 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -58,6 +58,7 @@ export type CustomErrorParams = Partial>; export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; + localized?: boolean; } class ParseInputLazyPath implements ParseInput { @@ -104,12 +105,23 @@ type RawCreateParams = invalid_type_error?: string; required_error?: string; description?: string; + localized?: boolean; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; +type ProcessedCreateParams = { + errorMap?: ZodErrorMap; + description?: string; + localized?: boolean; +}; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; - const { errorMap, invalid_type_error, required_error, description } = params; + const { + errorMap, + invalid_type_error, + required_error, + description, + localized, + } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( `Can't use "invalid" or "required" in conjunction with custom error map.` @@ -124,7 +136,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description }; + return { errorMap: customMap, description, localized }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -148,6 +160,10 @@ export abstract class ZodType< return this._def.description; } + get localized() { + return this._def.localized; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -374,6 +390,7 @@ export abstract class ZodType< this.describe = this.describe.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); + this.localize = this.localize.bind(this); } optional(): ZodOptional { @@ -430,6 +447,14 @@ export abstract class ZodType< }); } + localize(localized: boolean): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + localized, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } diff --git a/src/__tests__/localize.test.ts b/src/__tests__/localize.test.ts new file mode 100644 index 000000000..fa761be8b --- /dev/null +++ b/src/__tests__/localize.test.ts @@ -0,0 +1,10 @@ +// @ts-ignore TS6133 +import { expect, test } from "@jest/globals"; + +import * as z from "../index"; + +test("localize", () => { + const localized = true; + const schema = z.string().localize(localized); + expect(schema.localized).toEqual(localized); +}); diff --git a/src/types.ts b/src/types.ts index 360e7fc49..ccb68a45c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -58,6 +58,7 @@ export type CustomErrorParams = Partial>; export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; + localized?: boolean; } class ParseInputLazyPath implements ParseInput { @@ -104,12 +105,23 @@ type RawCreateParams = invalid_type_error?: string; required_error?: string; description?: string; + localized?: boolean; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; +type ProcessedCreateParams = { + errorMap?: ZodErrorMap; + description?: string; + localized?: boolean; +}; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; - const { errorMap, invalid_type_error, required_error, description } = params; + const { + errorMap, + invalid_type_error, + required_error, + description, + localized, + } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( `Can't use "invalid" or "required" in conjunction with custom error map.` @@ -124,7 +136,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description }; + return { errorMap: customMap, description, localized }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -148,6 +160,10 @@ export abstract class ZodType< return this._def.description; } + get localized() { + return this._def.localized; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -374,6 +390,7 @@ export abstract class ZodType< this.describe = this.describe.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); + this.localize = this.localize.bind(this); } optional(): ZodOptional { @@ -430,6 +447,14 @@ export abstract class ZodType< }); } + localize(localized: boolean): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + localized, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } From dc9c4387454b9fb35718b0c9c2ef4a01fe35cfe2 Mon Sep 17 00:00:00 2001 From: Piet Groot Kormelink Date: Thu, 28 Apr 2022 08:14:54 +0200 Subject: [PATCH 2/5] add name() to define displayName --- README.md | 15 ++++++++++++--- deno/lib/__tests__/name.test.ts | 11 +++++++++++ deno/lib/types.ts | 19 ++++++++++++++++++- src/__tests__/name.test.ts | 10 ++++++++++ src/types.ts | 19 ++++++++++++++++++- 5 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 deno/lib/__tests__/name.test.ts create mode 100644 src/__tests__/name.test.ts diff --git a/README.md b/README.md index 79685dfda..78e93d914 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ These docs have been translated into [Chinese](./README_ZH.md). - [.and](#and) - [.describe](#describe) - [.localize](#localize) + - [.name](#name) - [Guides and concepts](#guides-and-concepts) - [Type inference](#type-inference) - [Writing generic functions](#writing-generic-functions) @@ -1696,6 +1697,14 @@ const nullishString = z.string().nullish(); // string | null | undefined z.string().optional().nullable(); ``` +### `.describe` + +A schema method that adds a description to the schema for documentation purpose. + +```ts +const description = z.string().describe('usefull description').description; // string +``` + ### `.localize` A schema method that defines that the schema should be translated. @@ -1704,12 +1713,12 @@ A schema method that defines that the schema should be translated. const isLocalized = z.string().localize(true).localized; // boolean ``` -### `.describe` +### `.name` -A schema method that adds a description to the schema for documentation purpose. +A schema method that defines the displayName. ```ts -const description = z.string().describe('usefull description').description; // string +const name = z.string().name(true).displayName; ``` ### `.array` diff --git a/deno/lib/__tests__/name.test.ts b/deno/lib/__tests__/name.test.ts new file mode 100644 index 000000000..6e1ad178f --- /dev/null +++ b/deno/lib/__tests__/name.test.ts @@ -0,0 +1,11 @@ +// @ts-ignore TS6133 +import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; +const test = Deno.test; + +import * as z from "../index.ts"; + +test("name", () => { + const displayName = "myDisplayName"; + const schema = z.string().name(displayName); + expect(schema.displayName).toEqual(displayName); +}); diff --git a/deno/lib/types.ts b/deno/lib/types.ts index a0ea1484c..a9cffae66 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -59,6 +59,7 @@ export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; localized?: boolean; + displayName?: string; } class ParseInputLazyPath implements ParseInput { @@ -106,12 +107,14 @@ type RawCreateParams = required_error?: string; description?: string; localized?: boolean; + displayName?: string; } | undefined; type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string; localized?: boolean; + displayName?: string; }; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; @@ -121,6 +124,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { required_error, description, localized, + displayName, } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( @@ -136,7 +140,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description, localized }; + return { errorMap: customMap, description, localized, displayName }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -164,6 +168,10 @@ export abstract class ZodType< return this._def.localized; } + get displayName() { + return this._def.displayName; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -391,6 +399,7 @@ export abstract class ZodType< this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); this.localize = this.localize.bind(this); + this.name = this.name.bind(this); } optional(): ZodOptional { @@ -455,6 +464,14 @@ export abstract class ZodType< }); } + name(displayName: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + displayName, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } diff --git a/src/__tests__/name.test.ts b/src/__tests__/name.test.ts new file mode 100644 index 000000000..1a8199b96 --- /dev/null +++ b/src/__tests__/name.test.ts @@ -0,0 +1,10 @@ +// @ts-ignore TS6133 +import { expect, test } from "@jest/globals"; + +import * as z from "../index"; + +test("name", () => { + const displayName = "myDisplayName"; + const schema = z.string().name(displayName); + expect(schema.displayName).toEqual(displayName); +}); diff --git a/src/types.ts b/src/types.ts index ccb68a45c..415d2f7a2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -59,6 +59,7 @@ export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; localized?: boolean; + displayName?: string; } class ParseInputLazyPath implements ParseInput { @@ -106,12 +107,14 @@ type RawCreateParams = required_error?: string; description?: string; localized?: boolean; + displayName?: string; } | undefined; type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string; localized?: boolean; + displayName?: string; }; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; @@ -121,6 +124,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { required_error, description, localized, + displayName, } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( @@ -136,7 +140,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description, localized }; + return { errorMap: customMap, description, localized, displayName }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -164,6 +168,10 @@ export abstract class ZodType< return this._def.localized; } + get displayName() { + return this._def.displayName; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -391,6 +399,7 @@ export abstract class ZodType< this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); this.localize = this.localize.bind(this); + this.name = this.name.bind(this); } optional(): ZodOptional { @@ -455,6 +464,14 @@ export abstract class ZodType< }); } + name(displayName: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + displayName, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } From 2a03baa5fa89854ee5b6f21189787e717c38081f Mon Sep 17 00:00:00 2001 From: Piet Groot Kormelink Date: Thu, 28 Apr 2022 13:56:51 +0200 Subject: [PATCH 3/5] rename package to @mindlercare/zod --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e48cdc607..58f70d113 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "zod", + "name": "@mindlercare/zod", "version": "3.14.4", "description": "TypeScript-first schema declaration and validation library with static type inference", "main": "./lib/index.js", From ae24bf7de933b27d22f4ddd48c7995235af0631d Mon Sep 17 00:00:00 2001 From: Piet Groot Kormelink Date: Fri, 29 Apr 2022 13:45:56 +0200 Subject: [PATCH 4/5] add post install build --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 58f70d113..671e76dd5 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,8 @@ "play": "nodemon -e ts -w . -x ts-node src/playground.ts --project tsconfig.json --trace-warnings", "depcruise": "depcruise -c .dependency-cruiser.js src", "benchmark": "ts-node src/benchmarks/index.ts", - "prepare": "husky install" + "prepare": "husky install", + "postinstall": "yarn build" }, "devDependencies": { "@rollup/plugin-typescript": "^8.2.0", From d60a2284580c4ae740971c3f572ad938901d07c0 Mon Sep 17 00:00:00 2001 From: Piet Groot Kormelink Date: Fri, 29 Apr 2022 14:55:54 +0200 Subject: [PATCH 5/5] updated postinstall --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 671e76dd5..31d1724b1 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "depcruise": "depcruise -c .dependency-cruiser.js src", "benchmark": "ts-node src/benchmarks/index.ts", "prepare": "husky install", - "postinstall": "yarn build" + "postinstall": "yarn --ignore-scripts && yarn build" }, "devDependencies": { "@rollup/plugin-typescript": "^8.2.0",