zaggino/z-schema/custom-format-validators

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

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.

Install

npx vskill@latest install zaggino/z-schema/custom-format-validators

SKILL.md

Custom Format Validators in z-schema

JSON Schema format constrains string (or other) values beyond basic type checking. z-schema includes built-in validators and supports registering custom ones — both sync and async.

Built-in formats

z-schema ships with validators for all standard JSON Schema formats:

<!-- Keep this table in sync with the same table in docs/features.md. -->

FormatValidates
dateRFC 3339 full-date (2024-01-15)
date-timeRFC 3339 date-time (2024-01-15T09:30:00Z)
timeRFC 3339 time (09:30:00Z)
emailRFC 5321 email address
idn-emailInternationalized email
hostnameRFC 1123 hostname
host-nameAlias for hostname
idn-hostnameInternationalized hostname
ipv4IPv4 address
ipv6IPv6 address
uriRFC 3986 URI
strict-uriRFC 3986 URI, validated strictly (also what strictUris: true swaps in for uri)
uri-referenceURI or relative reference
uri-templateRFC 6570 URI Template (full ABNF, Errata 6937)
iriInternationalized URI
iri-referenceInternationalized URI reference
json-pointerRFC 6901 JSON Pointer
relative-json-pointerRelative JSON Pointer
regexECMA-262 regex
durationISO 8601 duration
uuidRFC 4122 UUID

Registering a sync format

A format validator is a function (input: unknown) => boolean. Return true if valid, false if invalid. Return true for non-applicable types (e.g., when input is not a string) — z-schema calls format validators for any value type.

Global registration (shared across all instances)
typescript
import 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);
});
Instance-scoped registration
typescript
const validator = ZSchema.create();
validator.registerFormat('postal-code', (value) => {
if (typeof value !== 'string') return true;
return /^\d{5}(-\d{4})?$/.test(value);
});

Instance formats override global formats with the same name.

Via options at creation time
typescript
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
},
});

Pass null to disable a built-in or globally registered format.

Registering an async format

Return Promise<boolean>. The validator must be created with { async: true }.

typescript
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);
}
Timeout

Async format validators time out after asyncTimeout milliseconds (default: 2000). Increase for slow operations:

typescript
const validator = ZSchema.create({
async: true,
asyncTimeout: 10000, // 10 seconds
});

Timed-out validators produce an ASYNC_TIMEOUT error.

Format assertion behavior across drafts

The JSON Schema spec changed how format works in newer drafts:

DraftDefault behaviorWith formatAssertions: true
draft-04/06/07Always asserts (fails on mismatch)Always asserts
draft-2019-09Always asserts (z-schema default)Annotation-only unless vocabulary enabled
draft-2020-12Always asserts (z-schema default)Annotation-only unless vocabulary enabled

z-schema defaults to formatAssertions: null (legacy — always assert). To respect the spec's vocabulary-aware behavior for modern drafts:

typescript
const validator = ZSchema.create({ formatAssertions: true });

To disable all format assertions (annotation-only):

typescript
const validator = ZSchema.create({ formatAssertions: false });

Unknown formats

By default, z-schema reports UNKNOWN_FORMAT for unrecognized format names in draft-04/06/07. Modern drafts (2019-09, 2020-12) always silently ignore unknown formats.

To suppress unknown format errors in older drafts:

typescript
const validator = ZSchema.create({ ignoreUnknownFormats: true });

Unregistering a format

typescript
// Global
ZSchema.unregisterFormat('postal-code');
// Instance
validator.unregisterFormat('postal-code');

Listing formats

typescript
// 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');

Real-world patterns

Phone number validation
typescript
ZSchema.registerFormat('phone', (value) => {
if (typeof value !== 'string') return true;
return /^\+?[1-9]\d{1,14}$/.test(value); // E.164 format
});
ISO 8601 date (strict)
typescript
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];
});
Business rule: value from external list
typescript
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());
});
Side-effect: prefill defaults

Format validators can mutate objects (use with caution):

typescript
ZSchema.registerFormat('fill-defaults', (obj) => {
if (typeof obj === 'object' && obj !== null) {
(obj as Record<string, unknown>).createdAt ??= new Date().toISOString();
}
return true;
});

Schema usage

json
{
"type": "object",
"properties": {
"phone": { "type": "string", "format": "phone" },
"country": { "type": "string", "format": "valid-country" },
"zipCode": { "type": "string", "format": "postal-code" }
}
}

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
342
Repository forks
91
Repository npm downloads, 7 days
2,859,562
7-day trend score
62

Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 7 Apr 2026, 6 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/zaggino/z-schema/custom-format-validators/badge)](https://verified-skill.com/skills/zaggino/z-schema/custom-format-validators)

Something wrong with this skill or its page? Tell us.