-
Notifications
You must be signed in to change notification settings - Fork 211
Migrate to Zod #808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Migrate to Zod #808
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { z } from "zod"; | ||
|
|
||
| export const urlSchema = z.object({ | ||
| url: z.string().url(), | ||
| }); | ||
|
|
||
| export type URL = z.infer<typeof urlSchema>; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,16 +2,18 @@ import Ajv from "ajv"; | |
| import addFormats from "ajv-formats"; | ||
| import projectSchema from "../resources/schema/project.json" with { type: "json" }; | ||
| import collectionSchema from "../resources/schema/collection.json" with { type: "json" }; | ||
| import urlSchema from "../resources/schema/url.json" with { type: "json" }; | ||
| //import urlSchema from "../resources/schema/url.json" with { type: "json" }; | ||
| import socialProfileSchema from "../resources/schema/social-profile.json" with { type: "json" }; | ||
| import blockchainAddressSchema from "../resources/schema/blockchain-address.json" with { type: "json" }; | ||
| import { Project } from "../types/project.js"; | ||
| import { Collection } from "../types/collection.js"; | ||
| import { URL } from "../types/url.js"; | ||
| //import { URL } from "../types/url.js"; | ||
| import { URL, urlSchema } from "../resources/schema/url.js"; | ||
| import { SocialProfile } from "../types/social-profile.js"; | ||
| import { BlockchainAddress } from "../types/blockchain-address.js"; | ||
| import { DEFAULT_FORMAT, FileFormat } from "../types/files.js"; | ||
| import { readFileParse } from "../utils/files.js"; | ||
| import { z } from "zod"; | ||
|
|
||
| // Initialize Ajv | ||
| type Schema = | ||
|
|
@@ -20,6 +22,11 @@ type Schema = | |
| | "url.json" | ||
| | "social-profile.json" | ||
| | "blockchain-address.json"; | ||
| type SchemaZod = "url.json"; | ||
| const schemaMap = { | ||
| "url.json": urlSchema, | ||
| } as const; | ||
| type SchemaMap = typeof schemaMap; | ||
| const PROJECT_SCHEMA: Schema = "project.json"; | ||
| const COLLECTION_SCHEMA: Schema = "collection.json"; | ||
| const URL_SCHEMA: Schema = "url.json"; | ||
|
|
@@ -69,6 +76,36 @@ function validateObject<T>(obj: any, schemaName: Schema): ValidationResult { | |
| return { valid: true, errors: {} }; | ||
| } | ||
|
|
||
| function validateObjectZod<T extends SchemaZod>( | ||
| obj: unknown, | ||
| schemaName: T, | ||
| ): ValidationResult { | ||
| const schema = schemaMap[schemaName]; | ||
|
|
||
| if (!schema) { | ||
| return { valid: false, errors: { schema: "Schema not found" } }; | ||
| } | ||
|
|
||
| const result = schema.safeParse(obj); | ||
|
|
||
| if (result.success) { | ||
| return { valid: true, errors: {} }; | ||
| } | ||
|
|
||
| const errors: Record<string, string> = {}; | ||
| const formatted = result.error.format(); | ||
|
||
| for (const [key, value] of Object.entries(formatted)) { | ||
| if (key === "_errors") continue; | ||
|
|
||
| if (value && typeof value === "object" && "_errors" in value) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This still looks wrong, I don't think we should be unsafely casting as a ZodFormattedError and directly accessing |
||
| const fieldErrors = (value as z.ZodFormattedError<any, string>)._errors; | ||
| errors[key] = fieldErrors.join(", "); | ||
| } | ||
| } | ||
|
|
||
| return { valid: false, errors }; | ||
| } | ||
|
|
||
| function safeCastObject<T>(obj: any, schemaName: Schema): T { | ||
| const result = validateObject<T>(obj, schemaName); | ||
| if (!result.valid) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of hard-coding the schemas using Zod, I'd suggest we leave it as JSON Schema and convert it at build/test time to the respective library.
For example, you should be able to use this for Zod.
https://www.npmjs.com/package/json-schema-to-zod
In the future, we may also want to do something similar to Python Pydantic
https://github.com/richard-gyiko/json-schema-to-pydantic