-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend): reusable validation schema (#94)
* feature(frontend): reusable zod validation schemas * test(frontend): zod validation schemas unit tests
- Loading branch information
1 parent
dc7cccd
commit a38cb23
Showing
18 changed files
with
1,596 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import isEmail from 'validator/es/lib/isEmail'; | ||
import type { z } from 'zod'; | ||
|
||
import { stringSchema } from '~/.server/validation/string-schema'; | ||
|
||
/** | ||
* Interface defining customizable error messages for email address validation schema. | ||
*/ | ||
export interface EmailAddressSchemaErrorMessages { | ||
/** | ||
* Error message for when the email address format is invalid. | ||
* @default 'Email address format is invalid.' | ||
*/ | ||
format_error?: string; | ||
|
||
/** | ||
* Error message for when the email address is not a string. | ||
* @default 'Email address must be a string.' | ||
*/ | ||
invalid_type_error?: string; | ||
|
||
/** | ||
* Error message for when the email address exceeds the maximum length. | ||
* @default 'Email address must be less than or equal to {maximum} characters | ||
*/ | ||
max_length_error?: string; | ||
|
||
/** | ||
* Error message for when the email address is required. | ||
* @default 'Email address is required.' | ||
*/ | ||
required_error?: string; | ||
} | ||
|
||
/** | ||
* Configuration options for email address validation, including maximum length and error messages. | ||
*/ | ||
export interface EmailAddressSchemaOptions { | ||
errorMessages?: EmailAddressSchemaErrorMessages; | ||
maxLength?: number; | ||
} | ||
|
||
const DEFAULT_MESSAGES = { | ||
format_error: 'Email address format is invalid.', | ||
invalid_type_error: 'Email address must be a string.', | ||
max_length_error: 'Email address must be less than or equal to {maximum} characters.', | ||
required_error: 'Email address is required.', | ||
} as const satisfies Required<EmailAddressSchemaErrorMessages>; | ||
|
||
/** | ||
* Creates a Zod schema for validating names with customizable options. | ||
* | ||
* @param options - Configuration options for validation. | ||
* @returns A Zod schema for validating names. | ||
*/ | ||
export function emailAddressSchema(options: EmailAddressSchemaOptions = {}): z.ZodEffects<z.ZodString> { | ||
const defaultMaxEmailLength = 254; // matches validator.js | ||
|
||
const { errorMessages = {}, maxLength = defaultMaxEmailLength } = options; | ||
|
||
const messages: Required<EmailAddressSchemaErrorMessages> = { | ||
...DEFAULT_MESSAGES, | ||
...errorMessages, | ||
}; | ||
|
||
return stringSchema({ | ||
errorMessages: { | ||
invalid_type_error: messages.invalid_type_error, | ||
max_length_error: messages.max_length_error, | ||
min_length_error: messages.required_error, | ||
required_error: messages.required_error, | ||
}, | ||
minLength: 1, | ||
maxLength: Math.min(defaultMaxEmailLength, maxLength), | ||
}).superRefine((email, ctx) => { | ||
if (!email) return; | ||
if (isEmail(email)) return; | ||
|
||
ctx.addIssue({ | ||
code: 'custom', | ||
message: messages.format_error, | ||
fatal: true, | ||
}); | ||
}); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import type { z } from 'zod'; | ||
|
||
import { nameSchema } from '~/.server/validation/name-schema'; | ||
|
||
/** | ||
* Interface defining customizable error messages for firstName validation schema. | ||
*/ | ||
export interface FirstNameSchemaErrorMessages { | ||
/** | ||
* Error message for when the first name contains digits. | ||
* @default 'First name must not contain any digits.' | ||
*/ | ||
format_error?: string; | ||
|
||
/** | ||
* Error message for when the first name is not a string. | ||
* @default 'First name must be a string.' | ||
*/ | ||
invalid_type_error?: string; | ||
|
||
/** | ||
* Error message for when the first name exceeds the maximum length. | ||
* @default 'First name must contain at most {maximum} characters.' | ||
*/ | ||
max_length_error?: string; | ||
|
||
/** | ||
* Error message for when the first name is required. | ||
* @default 'First name is required.' | ||
*/ | ||
required_error?: string; | ||
} | ||
|
||
/** | ||
* Configuration options for firstName validation, including maximum length and error messages. | ||
*/ | ||
export interface FirstNameSchemaOptions { | ||
errorMessages?: FirstNameSchemaErrorMessages; | ||
maxLength?: number; | ||
} | ||
|
||
const DEFAULT_MESSAGES = { | ||
format_error: 'First name must not contain any digits.', | ||
invalid_type_error: 'First name must be a string.', | ||
max_length_error: 'First name must contain at most {maximum} characters.', | ||
required_error: 'First name is required.', | ||
} as const satisfies Required<FirstNameSchemaErrorMessages>; | ||
|
||
/** | ||
* Creates a Zod schema for validating firstNames with customizable options. | ||
* | ||
* @param options - Configuration options for validation. | ||
* @returns A Zod schema for validating firstNames. | ||
*/ | ||
export function firstNameSchema(options: FirstNameSchemaOptions = {}): z.ZodString { | ||
const { errorMessages = {}, maxLength = 100 } = options; | ||
|
||
const messages: Required<FirstNameSchemaErrorMessages> = { | ||
...DEFAULT_MESSAGES, | ||
...errorMessages, | ||
}; | ||
|
||
return nameSchema({ | ||
errorMessages: { | ||
format_error: messages.format_error, | ||
invalid_type_error: messages.invalid_type_error, | ||
max_length_error: messages.max_length_error, | ||
required_error: messages.required_error, | ||
}, | ||
maxLength, | ||
}); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './email-address-schema'; | ||
export * from './first-name-schema'; | ||
export * from './last-name-schema'; | ||
export * from './name-schema'; | ||
export * from './string-schema'; |
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 |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import type { z } from 'zod'; | ||
|
||
import { nameSchema } from '~/.server/validation/name-schema'; | ||
|
||
/** | ||
* Interface defining customizable error messages for last name validation schema. | ||
*/ | ||
export interface LastNameSchemaErrorMessages { | ||
/** | ||
* Error message for when the last name contains digits. | ||
* @default 'Last name must not contain any digits.' | ||
*/ | ||
format_error?: string; | ||
|
||
/** | ||
* Error message for when the last name is not a string. | ||
* @default 'Last name must be a string.' | ||
*/ | ||
invalid_type_error?: string; | ||
|
||
/** | ||
* Error message for when the last name exceeds the maximum length. | ||
* @default 'Last name must contain at most {maximum} characters.' | ||
*/ | ||
max_length_error?: string; | ||
|
||
/** | ||
* Error message for when the last name is required. | ||
* @default 'Last name is required.' | ||
*/ | ||
required_error?: string; | ||
} | ||
|
||
/** | ||
* Configuration options for last name validation, including maximum length and error messages. | ||
*/ | ||
export interface LastNameSchemaOptions { | ||
errorMessages?: LastNameSchemaErrorMessages; | ||
maxLength?: number; | ||
} | ||
|
||
const DEFAULT_MESSAGES = { | ||
format_error: 'Last name must not contain any digits.', | ||
invalid_type_error: 'Last name must be a string.', | ||
max_length_error: 'Last name must contain at most {maximum} characters.', | ||
required_error: 'Last name is required.', | ||
} as const satisfies Required<LastNameSchemaErrorMessages>; | ||
|
||
/** | ||
* Creates a Zod schema for validating last names with customizable options. | ||
* | ||
* @param options - Configuration options for validation. | ||
* @returns A Zod schema for validating last names. | ||
*/ | ||
export function lastNameSchema(options: LastNameSchemaOptions = {}): z.ZodString { | ||
const { errorMessages = {}, maxLength = 100 } = options; | ||
|
||
const messages: Required<LastNameSchemaErrorMessages> = { | ||
...DEFAULT_MESSAGES, | ||
...errorMessages, | ||
}; | ||
|
||
return nameSchema({ | ||
errorMessages: { | ||
format_error: messages.format_error, | ||
invalid_type_error: messages.invalid_type_error, | ||
max_length_error: messages.max_length_error, | ||
required_error: messages.required_error, | ||
}, | ||
maxLength, | ||
}); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import type { z } from 'zod'; | ||
|
||
import { stringSchema } from '~/.server/validation/string-schema'; | ||
|
||
/** | ||
* Interface defining customizable error messages for name validation schema. | ||
*/ | ||
export interface NameSchemaErrorMessages { | ||
format_error?: string; | ||
invalid_type_error?: string; | ||
max_length_error?: string; | ||
required_error?: string; | ||
} | ||
|
||
/** | ||
* Configuration options for name validation, including maximum length and error messages. | ||
*/ | ||
export interface NameSchemaOptions { | ||
errorMessages?: NameSchemaErrorMessages; | ||
maxLength?: number; | ||
} | ||
|
||
const DEFAULT_MESSAGES = { | ||
format_error: 'Name must not contain any digits.', | ||
invalid_type_error: 'Name must be a string.', | ||
max_length_error: 'Name must contain at most {maximum} characters.', | ||
required_error: 'Name is required.', | ||
} as const satisfies Required<NameSchemaErrorMessages>; | ||
|
||
/** | ||
* Creates a Zod schema for validating names with customizable options. | ||
* | ||
* @param options - Configuration options for validation. | ||
* @returns A Zod schema for validating names. | ||
*/ | ||
export function nameSchema(options: NameSchemaOptions = {}): z.ZodString { | ||
const { errorMessages = {}, maxLength = 100 } = options; | ||
|
||
const messages: Required<NameSchemaErrorMessages> = { | ||
...DEFAULT_MESSAGES, | ||
...errorMessages, | ||
}; | ||
|
||
return stringSchema({ | ||
errorMessages: { | ||
format_error: messages.format_error, | ||
invalid_type_error: messages.invalid_type_error, | ||
max_length_error: messages.max_length_error, | ||
min_length_error: messages.required_error, | ||
required_error: messages.required_error, | ||
}, | ||
format: 'non-digit', | ||
minLength: 1, | ||
maxLength, | ||
}); | ||
} |
Oops, something went wrong.