zon-format
Version:
ZON: The most token-efficient serialization format for LLMs - beats CSV, TOON, JSON, and all competitors
554 lines (553 loc) • 19.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.zon = exports.ZonSchema = void 0;
exports.validate = validate;
const decoder_1 = require("../core/decoder");
/**
* Abstract base class for ZON schemas.
* Defines the contract for parsing validation and prompt generation.
*/
class ZonSchema {
describe(description) {
this.description = description;
return this;
}
example(value) {
this.exampleValue = value;
return this;
}
optional() {
return new ZonOptional(this);
}
nullable() {
return new ZonNullable(this);
}
default(value) {
return new ZonDefault(this, value);
}
refine(validator, message) {
return new ZonRefinement(this, validator, message);
}
}
exports.ZonSchema = ZonSchema;
class ZonNullable extends ZonSchema {
constructor(schema) {
super();
this.schema = schema;
}
parse(data, path = []) {
if (data === null) {
return { success: true, data: null };
}
return this.schema.parse(data, path);
}
toPrompt(indent = 0) {
return `${this.schema.toPrompt(indent)} (nullable)`;
}
}
class ZonOptional extends ZonSchema {
constructor(schema) {
super();
this.schema = schema;
}
parse(data, path = []) {
if (data === undefined || data === null) {
return { success: true, data: undefined };
}
return this.schema.parse(data, path);
}
toPrompt(indent = 0) {
return `${this.schema.toPrompt(indent)} (optional)`;
}
}
class ZonString extends ZonSchema {
constructor() {
super(...arguments);
this.emailValidation = false;
this.urlValidation = false;
this.uuidValidation = false;
this.datetimeValidation = false;
this.dateValidation = false;
this.timeValidation = false;
}
min(length) {
this.minLength = length;
return this;
}
max(length) {
this.maxLength = length;
return this;
}
email() {
this.emailValidation = true;
return this;
}
url() {
this.urlValidation = true;
return this;
}
regex(pattern, message) {
this.regexPattern = pattern;
this.regexMessage = message;
return this;
}
uuid(version = 'any') {
this.uuidValidation = version;
return this;
}
datetime() {
this.datetimeValidation = true;
return this;
}
date() {
this.dateValidation = true;
return this;
}
time() {
this.timeValidation = true;
return this;
}
parse(data, path = []) {
if (typeof data !== 'string') {
return {
success: false,
error: `Expected string at ${path.join('.') || 'root'}, got ${typeof data}`,
issues: [{ path, message: `Expected string, got ${typeof data}`, code: 'invalid_type' }],
};
}
if (this.minLength !== undefined && data.length < this.minLength) {
return {
success: false,
error: `String too short at ${path.join('.') || 'root'}: minimum ${this.minLength} characters`,
issues: [{ path, message: `String too short: minimum ${this.minLength} characters`, code: 'custom' }],
};
}
if (this.maxLength !== undefined && data.length > this.maxLength) {
return {
success: false,
error: `String too long at ${path.join('.') || 'root'}: maximum ${this.maxLength} characters`,
issues: [{ path, message: `String too long: maximum ${this.maxLength} characters`, code: 'custom' }],
};
}
if (this.emailValidation && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
return {
success: false,
error: `Invalid email at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Invalid email format', code: 'custom' }],
};
}
if (this.urlValidation) {
try {
new URL(data);
}
catch (_a) {
return {
success: false,
error: `Invalid URL at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Invalid URL format', code: 'custom' }],
};
}
}
if (this.regexPattern && !this.regexPattern.test(data)) {
return {
success: false,
error: this.regexMessage || `Pattern mismatch at ${path.join('.') || 'root'}`,
issues: [{ path, message: this.regexMessage || 'Does not match required pattern', code: 'custom' }],
};
}
if (this.uuidValidation) {
const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const uuidAnyRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const pattern = this.uuidValidation === 'v4' ? uuidV4Regex : uuidAnyRegex;
const versionStr = this.uuidValidation === 'v4' ? ' v4' : '';
if (!pattern.test(data)) {
return {
success: false,
error: `Invalid UUID${versionStr} at ${path.join('.') || 'root'}`,
issues: [{ path, message: `Invalid UUID${versionStr} format`, code: 'custom' }],
};
}
}
if (this.datetimeValidation && !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})$/.test(data)) {
return {
success: false,
error: `Invalid datetime at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Invalid ISO 8601 datetime format', code: 'custom' }],
};
}
if (this.dateValidation && !/^\d{4}-\d{2}-\d{2}$/.test(data)) {
return {
success: false,
error: `Invalid date at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Invalid date format (expected YYYY-MM-DD)', code: 'custom' }],
};
}
if (this.timeValidation && !/^\d{2}:\d{2}:\d{2}$/.test(data)) {
return {
success: false,
error: `Invalid time at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Invalid time format (expected HH:MM:SS)', code: 'custom' }],
};
}
return { success: true, data };
}
toPrompt(indent = 0) {
const constraints = [];
if (this.minLength !== undefined)
constraints.push(`min: ${this.minLength}`);
if (this.maxLength !== undefined)
constraints.push(`max: ${this.maxLength}`);
if (this.emailValidation)
constraints.push('email');
if (this.urlValidation)
constraints.push('url');
if (this.regexPattern)
constraints.push('pattern');
if (this.uuidValidation)
constraints.push(`uuid${this.uuidValidation === 'v4' ? '-v4' : ''}`);
if (this.datetimeValidation)
constraints.push('datetime');
if (this.dateValidation)
constraints.push('date');
if (this.timeValidation)
constraints.push('time');
const constraintStr = constraints.length > 0 ? ` (${constraints.join(', ')})` : '';
const desc = this.description ? ` - ${this.description}` : '';
return `string${constraintStr}${desc}`;
}
}
class ZonNumber extends ZonSchema {
constructor() {
super(...arguments);
this.isPositive = false;
this.isNegative = false;
this.isInteger = false;
}
min(value) {
this.minValue = value;
return this;
}
max(value) {
this.maxValue = value;
return this;
}
positive() {
this.isPositive = true;
return this;
}
negative() {
this.isNegative = true;
return this;
}
int() {
this.isInteger = true;
return this;
}
parse(data, path = []) {
if (typeof data !== 'number' || isNaN(data)) {
return {
success: false,
error: `Expected number at ${path.join('.') || 'root'}, got ${typeof data}`,
issues: [{ path, message: `Expected number, got ${typeof data}`, code: 'invalid_type' }],
};
}
if (this.isInteger && !Number.isInteger(data)) {
return {
success: false,
error: `Expected integer at ${path.join('.') || 'root'}, got ${data}`,
issues: [{ path, message: `Expected integer, got ${data}`, code: 'custom' }],
};
}
if (this.isPositive && data <= 0) {
return {
success: false,
error: `Expected positive number at ${path.join('.') || 'root'}, got ${data}`,
issues: [{ path, message: `Expected positive number, got ${data}`, code: 'custom' }],
};
}
if (this.isNegative && data >= 0) {
return {
success: false,
error: `Expected negative number at ${path.join('.') || 'root'}, got ${data}`,
issues: [{ path, message: `Expected negative number, got ${data}`, code: 'custom' }],
};
}
if (this.minValue !== undefined && data < this.minValue) {
return {
success: false,
error: `Number too small at ${path.join('.') || 'root'}: minimum ${this.minValue}`,
issues: [{ path, message: `Number too small: minimum ${this.minValue}`, code: 'custom' }],
};
}
if (this.maxValue !== undefined && data > this.maxValue) {
return {
success: false,
error: `Number too large at ${path.join('.') || 'root'}: maximum ${this.maxValue}`,
issues: [{ path, message: `Number too large: maximum ${this.maxValue}`, code: 'custom' }],
};
}
return { success: true, data };
}
toPrompt(indent = 0) {
const constraints = [];
if (this.isInteger)
constraints.push('integer');
if (this.isPositive)
constraints.push('positive');
if (this.isNegative)
constraints.push('negative');
if (this.minValue !== undefined)
constraints.push(`min: ${this.minValue}`);
if (this.maxValue !== undefined)
constraints.push(`max: ${this.maxValue}`);
const constraintStr = constraints.length > 0 ? ` (${constraints.join(', ')})` : '';
const desc = this.description ? ` - ${this.description}` : '';
return `number${constraintStr}${desc}`;
}
}
class ZonBoolean extends ZonSchema {
parse(data, path = []) {
if (typeof data !== 'boolean') {
return {
success: false,
error: `Expected boolean at ${path.join('.') || 'root'}, got ${typeof data}`,
issues: [{ path, message: `Expected boolean, got ${typeof data}`, code: 'invalid_type' }],
};
}
return { success: true, data };
}
toPrompt(indent = 0) {
const desc = this.description ? ` - ${this.description}` : '';
return `boolean${desc}`;
}
}
class ZonEnum extends ZonSchema {
constructor(values) {
super();
this.values = values;
}
parse(data, path = []) {
if (!this.values.includes(data)) {
return {
success: false,
error: `Expected one of [${this.values.join(', ')}] at ${path.join('.') || 'root'}, got '${data}'`,
issues: [{ path, message: `Invalid enum value. Expected: ${this.values.join(', ')}`, code: 'invalid_enum' }],
};
}
return { success: true, data };
}
toPrompt(indent = 0) {
const desc = this.description ? ` - ${this.description}` : '';
return `enum(${this.values.join(', ')})${desc}`;
}
}
class ZonArray extends ZonSchema {
constructor(elementSchema) {
super();
this.elementSchema = elementSchema;
}
min(length) {
this.minLength = length;
return this;
}
max(length) {
this.maxLength = length;
return this;
}
parse(data, path = []) {
if (!Array.isArray(data)) {
return {
success: false,
error: `Expected array at ${path.join('.') || 'root'}, got ${typeof data}`,
issues: [{ path, message: `Expected array, got ${typeof data}`, code: 'invalid_type' }],
};
}
if (this.minLength !== undefined && data.length < this.minLength) {
return {
success: false,
error: `Array too short at ${path.join('.') || 'root'}: minimum ${this.minLength} items`,
issues: [{ path, message: `Array too short: minimum ${this.minLength} items`, code: 'custom' }],
};
}
if (this.maxLength !== undefined && data.length > this.maxLength) {
return {
success: false,
error: `Array too long at ${path.join('.') || 'root'}: maximum ${this.maxLength} items`,
issues: [{ path, message: `Array too long: maximum ${this.maxLength} items`, code: 'custom' }],
};
}
const result = [];
for (let i = 0; i < data.length; i++) {
const itemResult = this.elementSchema.parse(data[i], [...path, i]);
if (!itemResult.success) {
return itemResult;
}
result.push(itemResult.data);
}
return { success: true, data: result };
}
toPrompt(indent = 0) {
const constraints = [];
if (this.minLength !== undefined)
constraints.push(`min: ${this.minLength}`);
if (this.maxLength !== undefined)
constraints.push(`max: ${this.maxLength}`);
const constraintStr = constraints.length > 0 ? ` (${constraints.join(', ')})` : '';
const desc = this.description ? ` - ${this.description}` : '';
return `array of [${this.elementSchema.toPrompt(indent)}]${constraintStr}${desc}`;
}
}
class ZonObject extends ZonSchema {
constructor(shape) {
super();
this.shape = shape;
}
parse(data, path = []) {
if (typeof data !== 'object' || data === null || Array.isArray(data)) {
return {
success: false,
error: `Expected object at ${path.join('.') || 'root'}, got ${data === null ? 'null' : typeof data}`,
issues: [{ path, message: `Expected object, got ${data === null ? 'null' : typeof data}`, code: 'invalid_type' }],
};
}
const result = {};
for (const key in this.shape) {
const fieldSchema = this.shape[key];
const fieldResult = fieldSchema.parse(data[key], [...path, key]);
if (!fieldResult.success) {
return fieldResult;
}
result[key] = fieldResult.data;
}
return { success: true, data: result };
}
toPrompt(indent = 0) {
const spaces = ' '.repeat(indent);
const lines = [`object:`];
if (this.description) {
lines[0] += ` (${this.description})`;
}
for (const key in this.shape) {
const fieldSchema = this.shape[key];
const fieldPrompt = fieldSchema.toPrompt(indent + 2);
lines.push(`${spaces} - ${key}: ${fieldPrompt}`);
}
return lines.join('\n');
}
}
class ZonLiteral extends ZonSchema {
constructor(value) {
super();
this.value = value;
}
parse(data, path = []) {
if (data !== this.value) {
return {
success: false,
error: `Expected literal '${this.value}' at ${path.join('.') || 'root'}, got '${data}'`,
issues: [{ path, message: `Must be exactly '${this.value}'`, code: 'invalid_type' }],
};
}
return { success: true, data: this.value };
}
toPrompt(indent = 0) {
const desc = this.description ? ` - ${this.description}` : '';
return `literal(${JSON.stringify(this.value)})${desc}`;
}
}
class ZonUnion extends ZonSchema {
constructor(schemas) {
super();
this.schemas = schemas;
}
parse(data, path = []) {
const errors = [];
for (const schema of this.schemas) {
const result = schema.parse(data, path);
if (result.success) {
return result;
}
errors.push(result.error);
}
return {
success: false,
error: `No union member matched at ${path.join('.') || 'root'}`,
issues: [{ path, message: 'Value does not match any union member', code: 'invalid_type' }],
};
}
toPrompt(indent = 0) {
const desc = this.description ? ` - ${this.description}` : '';
return `oneOf(${this.schemas.map(s => s.toPrompt()).join(' | ')})${desc}`;
}
}
class ZonDefault extends ZonSchema {
constructor(schema, defaultValue) {
super();
this.schema = schema;
this.defaultValue = defaultValue;
}
parse(data, path = []) {
if (data === undefined || data === null) {
return { success: true, data: this.defaultValue };
}
return this.schema.parse(data, path);
}
toPrompt(indent = 0) {
return `${this.schema.toPrompt(indent)} (default: ${JSON.stringify(this.defaultValue)})`;
}
}
class ZonRefinement extends ZonSchema {
constructor(schema, validator, message) {
super();
this.schema = schema;
this.validator = validator;
this.message = message;
}
parse(data, path = []) {
const result = this.schema.parse(data, path);
if (!result.success)
return result;
if (!this.validator(result.data)) {
return {
success: false,
error: `${this.message} at ${path.join('.') || 'root'}`,
issues: [{ path, message: this.message, code: 'custom' }],
};
}
return result;
}
toPrompt(indent = 0) {
return `${this.schema.toPrompt(indent)} (custom validation)`;
}
}
exports.zon = {
string: () => new ZonString(),
number: () => new ZonNumber(),
boolean: () => new ZonBoolean(),
enum: (values) => new ZonEnum(values),
array: (schema) => new ZonArray(schema),
object: (shape) => new ZonObject(shape),
literal: (value) => new ZonLiteral(value),
union: (...schemas) => new ZonUnion(schemas),
};
/**
* Validates a ZON string or decoded object against a schema.
* @param input ZON string or decoded object
* @param schema ZON Schema
*/
function validate(input, schema) {
let data = input;
if (typeof input === 'string') {
try {
data = (0, decoder_1.decode)(input);
}
catch (e) {
return {
success: false,
error: `ZON Parse Error: ${e.message}`,
issues: [{ path: [], message: e.message, code: 'custom' }],
};
}
}
return schema.parse(data);
}