-
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Proprietary schemas using native zod methods and Metadata (#1442)
I was dreaming about it. Unfortunately `zod` does not provide any way to make a custom or branded or third-party schema that can be identified as one programmatically. Developer of `zod` also does not want to make any method to store metadata in schemas, instead, recommends to wrap schemas in some other structures, which is not suitable for the purposes of `express-zod-api`. There are many small inconvenient things in making custom schema classes, that I'd like to replace into native methods, and use `withMeta` wrapper for storing proprietary identifier, so the generators and walkers could still handle it. Related issues: ``` colinhacks/zod#1718 colinhacks/zod#2413 colinhacks/zod#273 colinhacks/zod#71 colinhacks/zod#37 ``` PR I've been waiting for months to merged (programmatically distinguishable branding): ``` colinhacks/zod#2860 ```
- Loading branch information
Showing
28 changed files
with
350 additions
and
479 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
openapi: 3.1.0 | ||
info: | ||
title: Example API | ||
version: 16.2.2 | ||
version: 16.3.0-beta1 | ||
paths: | ||
/v1/user/retrieve: | ||
get: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,15 @@ | ||
import { | ||
INVALID, | ||
ParseInput, | ||
ParseReturnType, | ||
ZodIssueCode, | ||
ZodParsedType, | ||
ZodType, | ||
ZodTypeDef, | ||
addIssueToContext, | ||
} from "zod"; | ||
import { isValidDate } from "./schema-helpers"; | ||
|
||
// simple regex for ISO date, supports the following formats: | ||
// 2021-01-01T00:00:00.000Z | ||
// 2021-01-01T00:00:00.0Z | ||
// 2021-01-01T00:00:00Z | ||
// 2021-01-01T00:00:00 | ||
// 2021-01-01 | ||
export const isoDateRegex = | ||
/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?)?Z?$/; | ||
|
||
const zodDateInKind = "ZodDateIn"; | ||
|
||
export interface ZodDateInDef extends ZodTypeDef { | ||
typeName: typeof zodDateInKind; | ||
} | ||
|
||
export class ZodDateIn extends ZodType<Date, ZodDateInDef, string> { | ||
_parse(input: ParseInput): ParseReturnType<Date> { | ||
const { status, ctx } = this._processInputParams(input); | ||
if (ctx.parsedType !== ZodParsedType.string) { | ||
addIssueToContext(ctx, { | ||
code: ZodIssueCode.invalid_type, | ||
expected: ZodParsedType.string, | ||
received: ctx.parsedType, | ||
}); | ||
return INVALID; | ||
} | ||
|
||
if (!isoDateRegex.test(ctx.data as string)) { | ||
addIssueToContext(ctx, { | ||
code: ZodIssueCode.invalid_string, | ||
validation: "regex", | ||
}); | ||
status.dirty(); | ||
} | ||
|
||
const date = new Date(ctx.data); | ||
|
||
if (!isValidDate(date)) { | ||
addIssueToContext(ctx, { | ||
code: ZodIssueCode.invalid_date, | ||
}); | ||
return INVALID; | ||
} | ||
|
||
return { status: status.value, value: date }; | ||
} | ||
|
||
static create = () => | ||
new ZodDateIn({ | ||
typeName: zodDateInKind, | ||
}); | ||
} | ||
import { z } from "zod"; | ||
import { proprietary } from "./metadata"; | ||
import { isValidDate, isoDateRegex } from "./schema-helpers"; | ||
|
||
export const ezDateInKind = "DateIn"; | ||
|
||
export const dateIn = () => | ||
proprietary( | ||
ezDateInKind, | ||
z | ||
.string() | ||
.regex(isoDateRegex) | ||
.transform((str) => new Date(str)) | ||
.pipe(z.date().refine(isValidDate)), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,14 @@ | ||
import { | ||
INVALID, | ||
ParseInput, | ||
ParseReturnType, | ||
ZodIssueCode, | ||
ZodParsedType, | ||
ZodType, | ||
ZodTypeDef, | ||
addIssueToContext, | ||
} from "zod"; | ||
import { z } from "zod"; | ||
import { proprietary } from "./metadata"; | ||
import { isValidDate } from "./schema-helpers"; | ||
|
||
const zodDateOutKind = "ZodDateOut"; | ||
export const ezDateOutKind = "DateOut"; | ||
|
||
export interface ZodDateOutDef extends ZodTypeDef { | ||
typeName: typeof zodDateOutKind; | ||
} | ||
|
||
export class ZodDateOut extends ZodType<string, ZodDateOutDef, Date> { | ||
_parse(input: ParseInput): ParseReturnType<string> { | ||
const { status, ctx } = this._processInputParams(input); | ||
if (ctx.parsedType !== ZodParsedType.date) { | ||
addIssueToContext(ctx, { | ||
code: ZodIssueCode.invalid_type, | ||
expected: ZodParsedType.date, | ||
received: ctx.parsedType, | ||
}); | ||
return INVALID; | ||
} | ||
|
||
if (!isValidDate(ctx.data)) { | ||
addIssueToContext(ctx, { | ||
code: ZodIssueCode.invalid_date, | ||
}); | ||
return INVALID; | ||
} | ||
|
||
return { status: status.value, value: (ctx.data as Date).toISOString() }; | ||
} | ||
|
||
static create = () => | ||
new ZodDateOut({ | ||
typeName: zodDateOutKind, | ||
}); | ||
} | ||
export const dateOut = () => | ||
proprietary( | ||
ezDateOutKind, | ||
z | ||
.date() | ||
.refine(isValidDate) | ||
.transform((date) => date.toISOString()), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.