Loading...
Loading...
Registers and manages custom format validators in z-schema. Use when the user needs to add custom format validation, create sync or async format validators, register formats globally or per instance, validate emails or dates or phone numbers or custom business rules with format, configure formatAssertions for vocabulary-aware behavior, use customFormats option, list registered formats, handle async format timeouts, or understand how format validation differs across JSON Schema drafts.
npx skill4agent add zaggino/z-schema custom-format-validatorsformat| Format | Validates |
|---|---|
| RFC 3339 full-date ( |
| RFC 3339 date-time ( |
| RFC 3339 time ( |
| RFC 5321 email address |
| Internationalized email |
| RFC 1123 hostname |
| Internationalized hostname |
| IPv4 address |
| IPv6 address |
| RFC 3986 URI |
| URI or relative reference |
| RFC 6570 URI template |
| Internationalized URI |
| Internationalized URI reference |
| RFC 6901 JSON Pointer |
| Relative JSON Pointer |
| ECMA-262 regex |
| ISO 8601 duration |
| RFC 4122 UUID |
(input: unknown) => booleantruefalsetrueimport ZSchema from 'z-schema';
ZSchema.registerFormat('postal-code', (value) => {
if (typeof value !== 'string') return true; // skip non-strings
return /^\d{5}(-\d{4})?$/.test(value);
});const validator = ZSchema.create();
validator.registerFormat('postal-code', (value) => {
if (typeof value !== 'string') return true;
return /^\d{5}(-\d{4})?$/.test(value);
});const validator = ZSchema.create({
customFormats: {
'postal-code': (value) => typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value),
'always-valid': () => true,
'disable-email': null, // disable the built-in email validator
},
});nullPromise<boolean>{ async: true }const validator = ZSchema.create({ async: true });
validator.registerFormat('user-exists', async (value) => {
if (typeof value !== 'number') return true;
const user = await db.findUser(value);
return user != null;
});
// Validate (returns Promise)
try {
await validator.validate(data, schema);
} catch (err) {
console.log(err.details);
}asyncTimeoutconst validator = ZSchema.create({
async: true,
asyncTimeout: 10000, // 10 seconds
});ASYNC_TIMEOUTformat| Draft | Default behavior | With |
|---|---|---|
| draft-04/06/07 | Always asserts (fails on mismatch) | Always asserts |
| draft-2019-09 | Always asserts (z-schema default) | Annotation-only unless vocabulary enabled |
| draft-2020-12 | Always asserts (z-schema default) | Annotation-only unless vocabulary enabled |
formatAssertions: nullconst validator = ZSchema.create({ formatAssertions: true });const validator = ZSchema.create({ formatAssertions: false });UNKNOWN_FORMATconst validator = ZSchema.create({ ignoreUnknownFormats: true });// Global
ZSchema.unregisterFormat('postal-code');
// Instance
validator.unregisterFormat('postal-code');// List globally registered custom formats
const customFormats = ZSchema.getRegisteredFormats();
// List all supported formats (built-in + custom) on an instance
const allFormats = validator.getSupportedFormats();
// Check if a specific format is supported
const supported = validator.isFormatSupported('postal-code');ZSchema.registerFormat('phone', (value) => {
if (typeof value !== 'string') return true;
return /^\+?[1-9]\d{1,14}$/.test(value); // E.164 format
});ZSchema.registerFormat('iso-date', (value) => {
if (typeof value !== 'string') return true;
const d = new Date(value);
return !isNaN(d.getTime()) && value === d.toISOString().split('T')[0];
});const validator = ZSchema.create({ async: true });
validator.registerFormat('valid-country', async (value) => {
if (typeof value !== 'string') return true;
const countries = await fetchValidCountries();
return countries.includes(value.toUpperCase());
});ZSchema.registerFormat('fill-defaults', (obj) => {
if (typeof obj === 'object' && obj !== null) {
(obj as Record<string, unknown>).createdAt ??= new Date().toISOString();
}
return true;
});{
"type": "object",
"properties": {
"phone": { "type": "string", "format": "phone" },
"country": { "type": "string", "format": "valid-country" },
"zipCode": { "type": "string", "format": "postal-code" }
}
}