diff --git a/packages/validators/package.json b/packages/validators/package.json index 08524a7..5601984 100644 --- a/packages/validators/package.json +++ b/packages/validators/package.json @@ -12,7 +12,8 @@ }, "dependencies": { "vitest": "^2.0.2", - "zod": "^3.23.8" + "zod": "^3.23.8", + "zod-validation-error": "^3.3.0" }, "devDependencies": { "@types/node": "^18", diff --git a/packages/validators/src/url/index.ts b/packages/validators/src/url/index.ts index c8d55f7..e514a20 100644 --- a/packages/validators/src/url/index.ts +++ b/packages/validators/src/url/index.ts @@ -1,4 +1,5 @@ import { ZodError } from 'zod' +import { fromError } from 'zod-validation-error' import { OptionsError, UrlValidationError } from '@/url/errors' import { defaultOptions, Options, optionsSchema } from '@/url/options' @@ -8,13 +9,12 @@ export class UrlValidator { private schema constructor(options: Options = defaultOptions) { - let validatedOptions: Options - try { - validatedOptions = optionsSchema.parse({ ...defaultOptions, ...options }) - } catch (error) { - throw new OptionsError(`Invalid options: ${(error as Error).message}`) + const result = optionsSchema.safeParse({ ...defaultOptions, ...options }) + if (result.success) { + this.schema = createUrlSchema(result.data) + return } - this.schema = createUrlSchema(validatedOptions) + throw new OptionsError(fromError(result.error)) } parse(url: string): URL { @@ -23,7 +23,7 @@ export class UrlValidator { return result.data } if (result.error instanceof ZodError) { - throw new UrlValidationError(JSON.stringify(result.error.format())) + throw new UrlValidationError(fromError(result.error)) } else { throw result.error } diff --git a/packages/validators/src/url/options.ts b/packages/validators/src/url/options.ts index 6c71360..0515e03 100644 --- a/packages/validators/src/url/options.ts +++ b/packages/validators/src/url/options.ts @@ -16,7 +16,17 @@ export type Whitelist = z.infer export const optionsSchema = z.object({ baseUrl: z .string() - .transform((value) => new URL(value)) + .transform((value, ctx) => { + try { + return new URL(value) + } catch (error) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: (error as Error).message, + }) + return z.NEVER + } + }) .refine( (value) => value.protocol === 'http:' || value.protocol === 'https:', ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2bbe7a3..384f0da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: zod: specifier: ^3.23.8 version: 3.23.8 + zod-validation-error: + specifier: ^3.3.0 + version: 3.3.0(zod@3.23.8) devDependencies: '@types/node': specifier: ^18 @@ -1959,6 +1962,12 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod-validation-error@3.3.0: + resolution: {integrity: sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -4014,4 +4023,8 @@ snapshots: yocto-queue@0.1.0: {} + zod-validation-error@3.3.0(zod@3.23.8): + dependencies: + zod: 3.23.8 + zod@3.23.8: {}