An ExtensionConfig object mapping builder type names to method records.
A branded ExtensionDescriptor ready to pass to withExtensions.
const slugExt = defineExtension({
string: {
slug(this: StringSchemaBuilder) {
return this.addValidator((val) => {
const valid = /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(val);
return { valid, errors: valid ? [] : [{ message: 'invalid slug' }] };
});
}
}
});
// Usage:
const s = withExtensions(slugExt);
const schema = s.string().slug();
schema.introspect().extensions.slug; // true
const currencyExt = defineExtension({
number: {
currency(this: NumberSchemaBuilder, opts?: { maxDecimals?: number }) {
const maxDec = opts?.maxDecimals ?? 2;
return this.withExtension('currency', { maxDecimals: maxDec })
.min(0)
.addValidator((val) => {
const decimals = (String(val).split('.')[1] ?? '').length;
const valid = decimals <= maxDec;
return { valid, errors: valid ? [] : [{ message: `max ${maxDec} decimals` }] };
});
}
}
});
const myExt = defineExtension({
string: {
email(this: StringSchemaBuilder) { return this.addValidator(...); }
},
number: {
port(this: NumberSchemaBuilder) { return this.isInteger().min(1).max(65535); }
}
});
Defines an extension targeting one or more schema builder types.
Each extension is a plain object keyed by builder type name (
"string","number","date", …) whose values are method implementations. Methods receivethisbound to the builder instance and must return a builder to support fluent chaining.Ergonomic metadata (auto-infer)
Extension methods do not have to call
this.withExtension(). The system wraps each method and automatically attacheswithExtension(methodName, args)to the returned builder when the key is not already present. This eliminates the most common source of duplication in extension code.trueIf you need custom metadata (e.g. a different key, a transformed value, or a structured object), call
this.withExtension(key, value)explicitly inside the method — the auto-infer logic detects the existing key and skips automatic attachment.Validation
defineExtensionvalidates the configuration eagerly:validate,introspect) cannot be overridden.