Comparing version 1.1.2 to 1.2.0
@@ -11,6 +11,8 @@ import { BaseValidator } from "../validators/base/validator"; | ||
import { IfValidator } from "../validators/if/validator"; | ||
import { RecursiveValidator } from "../validators/recursive/validator"; | ||
import { TypeOf } from "../validators/functional"; | ||
import { ArrayFunction, TupleFunction } from "../validators/array-types"; | ||
import { ExtractObject } from "../validators/object-types"; | ||
import { Decorations } from "../validators/decorations"; | ||
import { Annotations, TopLevelAnnotations } from "../annotations"; | ||
import { RecursiveValue } from "../validators/types"; | ||
export declare const v: { | ||
@@ -29,19 +31,30 @@ string: () => StringValidator<string>; | ||
any: () => AnyValidator; | ||
recursive: () => RecursiveValidator; | ||
}; | ||
/** | ||
* Decorate a validator with a name and other annotations | ||
* Cast a recursive value (a value in a recursive type) | ||
*/ | ||
export declare const recursiveCast: <T>(value: RecursiveValue) => T; | ||
/** | ||
* Cast a value into a recursive value (inversion of recursiveCast) | ||
*/ | ||
export declare const recursiveUnCast: <T>(value: T) => RecursiveValue; | ||
export declare const raw: <T = unknown>(jsonSchema: any) => BaseValidator<T, BaseValidator<T, any>>; | ||
/** | ||
* Annotate a validator with a name and other decorations | ||
* | ||
* @param decorations Decorations | ||
* @param validator Target validator to decorate | ||
* @returns Decorated validator | ||
* @param annotations Annotations | ||
* @param validator Target validator to annotate | ||
* @returns Annotated validator | ||
*/ | ||
export declare function suretype<T extends BaseValidator<unknown, any>>(decorations: Decorations, validator: T): T; | ||
export declare function suretype<T extends BaseValidator<unknown, any>>(annotations: TopLevelAnnotations, validator: T): T; | ||
export declare function annotate<T extends BaseValidator<unknown, any>>(annotations: Partial<Annotations>, validator: T): T; | ||
/** | ||
* Ensures a validator is decorated with a name. This will not overwrite the | ||
* Ensures a validator is annotated with a name. This will not overwrite the | ||
* name of a validator, only ensure it has one. | ||
* | ||
* @param name The name to decorate with, unless already decorated | ||
* @param name The name to annotate with, unless already annotated | ||
* @param validator The target validator | ||
* @returns Decorated validator | ||
* @returns Annotated validator | ||
*/ | ||
export declare function ensureNamed<T extends BaseValidator<unknown, any>>(name: string, validator: T): T; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ensureNamed = exports.suretype = exports.v = void 0; | ||
exports.ensureNamed = exports.annotate = exports.suretype = exports.raw = exports.recursiveUnCast = exports.recursiveCast = exports.v = void 0; | ||
const validator_1 = require("../validators/boolean/validator"); | ||
@@ -15,4 +15,6 @@ const validator_2 = require("../validators/number/validator"); | ||
const validator_11 = require("../validators/if/validator"); | ||
const validator_12 = require("../validators/raw/validator"); | ||
const validator_13 = require("../validators/recursive/validator"); | ||
const validation_1 = require("../validation"); | ||
const decorations_1 = require("../validators/decorations"); | ||
const annotations_1 = require("../annotations"); | ||
const string = () => new validator_3.StringValidator(); | ||
@@ -32,2 +34,3 @@ const number = () => new validator_2.NumberValidator(); | ||
const _if = (validator) => new validator_11.IfValidator(validator); | ||
const recursive = () => new validator_13.RecursiveValidator(); | ||
exports.v = { | ||
@@ -44,28 +47,45 @@ string, | ||
any, | ||
recursive, | ||
}; | ||
/** | ||
* Decorate a validator with a name and other annotations | ||
* Cast a recursive value (a value in a recursive type) | ||
*/ | ||
const recursiveCast = (value) => value; | ||
exports.recursiveCast = recursiveCast; | ||
/** | ||
* Cast a value into a recursive value (inversion of recursiveCast) | ||
*/ | ||
const recursiveUnCast = (value) => value; | ||
exports.recursiveUnCast = recursiveUnCast; | ||
const raw = (jsonSchema) => new validator_12.RawValidator(jsonSchema); | ||
exports.raw = raw; | ||
/** | ||
* Annotate a validator with a name and other decorations | ||
* | ||
* @param decorations Decorations | ||
* @param validator Target validator to decorate | ||
* @returns Decorated validator | ||
* @param annotations Annotations | ||
* @param validator Target validator to annotate | ||
* @returns Annotated validator | ||
*/ | ||
function suretype(decorations, validator) { | ||
return validation_1.decorateValidator(validation_1.cloneValidator(validator, false), new decorations_1.DecorationsHolder(decorations)); | ||
function suretype(annotations, validator) { | ||
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder(annotations)); | ||
} | ||
exports.suretype = suretype; | ||
function annotate(annotations, validator) { | ||
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder(annotations)); | ||
} | ||
exports.annotate = annotate; | ||
/** | ||
* Ensures a validator is decorated with a name. This will not overwrite the | ||
* Ensures a validator is annotated with a name. This will not overwrite the | ||
* name of a validator, only ensure it has one. | ||
* | ||
* @param name The name to decorate with, unless already decorated | ||
* @param name The name to annotate with, unless already annotated | ||
* @param validator The target validator | ||
* @returns Decorated validator | ||
* @returns Annotated validator | ||
*/ | ||
function ensureNamed(name, validator) { | ||
var _a; | ||
if ((_a = validation_1.getDecorations(validator)) === null || _a === void 0 ? void 0 : _a.options.name) | ||
const annotations = annotations_1.getAnnotations(validator); | ||
if (annotations === null || annotations === void 0 ? void 0 : annotations.name) | ||
return validator; | ||
return validation_1.decorateValidator(validation_1.cloneValidator(validator, false), new decorations_1.DecorationsHolder({ name })); | ||
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder({ ...annotations, name })); | ||
} | ||
exports.ensureNamed = ensureNamed; |
@@ -5,3 +5,3 @@ "use strict"; | ||
const errors_1 = require("./errors"); | ||
const validation_1 = require("./validation"); | ||
const annotations_1 = require("./annotations"); | ||
const tree_traverser_1 = require("./tree-traverser"); | ||
@@ -17,8 +17,9 @@ /** | ||
validators = validators | ||
.filter(validator => validation_1.getDecorations(validator)); | ||
.filter(validator => { var _a; return (_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name; }); | ||
} | ||
else if (onNonSuretypeValidator === 'error') { | ||
validators.forEach(validator => { | ||
if (!validation_1.getDecorations(validator)) | ||
throw new TypeError("Got undecorated validator"); | ||
var _a; | ||
if (!((_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name)) | ||
throw new TypeError("Got unnamed validator"); | ||
}); | ||
@@ -29,5 +30,5 @@ } | ||
validators | ||
.map(validator => validation_1.getDecorations(validator)) | ||
.map(validator => { var _a; return (_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name; }) | ||
.filter((t) => !!t) | ||
.forEach(({ options: { name } }) => { | ||
.forEach(name => { | ||
if (nameSet.has(name)) | ||
@@ -34,0 +35,0 @@ throw new errors_1.DuplicateError(`Duplicate validators found with name "${name}"`); |
@@ -8,3 +8,4 @@ export * from "./api"; | ||
export { getValidatorSchema } from "./validation"; | ||
export { Annotations, TopLevelAnnotations, getAnnotations, } from "./annotations"; | ||
import type { TypeOf } from "./validators/functional"; | ||
export type { TypeOf }; |
@@ -13,3 +13,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getValidatorSchema = exports.extractSingleJsonSchema = exports.extractJsonSchema = exports.validate = exports.compile = void 0; | ||
exports.getAnnotations = exports.getValidatorSchema = exports.extractSingleJsonSchema = exports.extractJsonSchema = exports.validate = exports.compile = void 0; | ||
__exportStar(require("./api"), exports); | ||
@@ -26,1 +26,3 @@ __exportStar(require("./errors"), exports); | ||
Object.defineProperty(exports, "getValidatorSchema", { enumerable: true, get: function () { return validation_1.getValidatorSchema; } }); | ||
var annotations_1 = require("./annotations"); | ||
Object.defineProperty(exports, "getAnnotations", { enumerable: true, get: function () { return annotations_1.getAnnotations; } }); |
@@ -10,2 +10,3 @@ import { TreeTraverser, BaseValidator } from "./validators/base/validator"; | ||
private duplicates; | ||
currentSchemaName: string | undefined; | ||
constructor(initialValidators: Array<BaseValidator<unknown, any>>, refMethod: ExportRefMethod); | ||
@@ -12,0 +13,0 @@ visit(validator: BaseValidator<unknown, any>): any; |
@@ -5,2 +5,3 @@ "use strict"; | ||
const validation_1 = require("./validation"); | ||
const annotations_1 = require("./annotations"); | ||
class TreeTraverserImpl { | ||
@@ -14,2 +15,3 @@ constructor(initialValidators, refMethod) { | ||
this.duplicates = new Map(); | ||
this.currentSchemaName = undefined; | ||
initialValidators | ||
@@ -36,4 +38,4 @@ .map(validator => this.makeRef(validator, false)) | ||
return undefined; | ||
const decorations = validation_1.getDecorations(validator); | ||
if (!decorations) | ||
const decorations = annotations_1.getAnnotations(validator); | ||
if (!(decorations === null || decorations === void 0 ? void 0 : decorations.name)) | ||
return undefined; | ||
@@ -52,8 +54,10 @@ const nameIfInitial = this.initialValidators.get(validator); | ||
insert({ name, validator }) { | ||
this.currentSchemaName = name; | ||
this.definitions[name] = validation_1.validatorToSchema(validator, this); | ||
this.currentSchemaName = undefined; | ||
return name; | ||
} | ||
makeRef(validator, extra) { | ||
const decorations = validation_1.getDecorations(validator); | ||
const name = this.getNextName(decorations === null || decorations === void 0 ? void 0 : decorations.options.name); | ||
const decorations = annotations_1.getAnnotations(validator); | ||
const name = this.getNextName(decorations === null || decorations === void 0 ? void 0 : decorations.name); | ||
if (extra) | ||
@@ -60,0 +64,0 @@ this.extraValidators.set(validator, name); |
import type { AnyType } from "./validators/types"; | ||
import type { DecorationsHolder } from "./validators/decorations"; | ||
import { BaseValidator, TreeTraverser } from "./validators/base/validator"; | ||
@@ -8,5 +7,3 @@ export declare function validatorToSchema<T extends BaseValidator<unknown>>(validator: T, traverser: TreeTraverser): any; | ||
export declare function cloneValidator<T extends BaseValidator<unknown>>(validator: T, clean: boolean): T; | ||
export declare function decorateValidator<T extends BaseValidator<unknown>>(validator: T, decorations: DecorationsHolder): T; | ||
export declare function getDecorations<T extends BaseValidator<unknown>>(validator: T): DecorationsHolder | undefined; | ||
export declare function attachSchemaToValidator<Fn extends Function>(validator: Fn, schema: BaseValidator<unknown>): typeof validator; | ||
export declare function getValidatorSchema(val: any): BaseValidator<unknown> | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getValidatorSchema = exports.attachSchemaToValidator = exports.getDecorations = exports.decorateValidator = exports.cloneValidator = exports.validatorParent = exports.validatorType = exports.validatorToSchema = void 0; | ||
exports.getValidatorSchema = exports.attachSchemaToValidator = exports.cloneValidator = exports.validatorParent = exports.validatorType = exports.validatorToSchema = void 0; | ||
const validator_1 = require("./validators/base/validator"); | ||
@@ -21,11 +21,2 @@ function validatorToSchema(validator, traverser) { | ||
exports.cloneValidator = cloneValidator; | ||
function decorateValidator(validator, decorations) { | ||
validator._decorations = decorations; | ||
return validator; | ||
} | ||
exports.decorateValidator = decorateValidator; | ||
function getDecorations(validator) { | ||
return validator._decorations; | ||
} | ||
exports.getDecorations = getDecorations; | ||
const schemaLookup = new WeakMap(); | ||
@@ -32,0 +23,0 @@ function attachSchemaToValidator(validator, schema) { |
import { AnyType } from "../types"; | ||
import { DecorationsHolder } from "../decorations"; | ||
import { AnnotationsHolder } from "../../annotations"; | ||
export interface TreeTraverser { | ||
@@ -9,6 +9,7 @@ visit(validator: BaseValidator<unknown, any>): any; | ||
}; | ||
currentSchemaName: string | undefined; | ||
} | ||
export declare abstract class BaseValidator<T, U extends BaseValidator<T, U> = BaseValidator<T, any>> { | ||
protected _parent: this | undefined; | ||
protected _decorations: DecorationsHolder | undefined; | ||
protected _annotations: AnnotationsHolder | undefined; | ||
protected abstract type: AnyType; | ||
@@ -15,0 +16,0 @@ protected abstract toSchema(traverser: TreeTraverser): any; |
@@ -7,3 +7,3 @@ "use strict"; | ||
this._parent = undefined; | ||
this._decorations = undefined; | ||
this._annotations = undefined; | ||
} | ||
@@ -17,5 +17,5 @@ setupClone(clean, clone) { | ||
getJsonSchemaObject(traverser) { | ||
if (!this._decorations) | ||
if (!this._annotations) | ||
return {}; | ||
const { title, description, examples } = this._decorations.options; | ||
const { title, description, examples } = this._annotations.options; | ||
return { | ||
@@ -22,0 +22,0 @@ ...(title ? { title } : {}), |
@@ -15,2 +15,5 @@ import { BaseValidator } from "./base/validator"; | ||
import { RequiredValidator } from "./required/validator"; | ||
import { RawValidator } from "./raw/validator"; | ||
import { RecursiveValidator } from "./recursive/validator"; | ||
import { RecursiveValue } from "./types"; | ||
export declare type IsRequired<T> = T extends RequiredValidator<infer U, infer _> ? true : false; | ||
@@ -21,5 +24,5 @@ export declare type ExtractRequired<T> = T extends RequiredValidator<infer U, infer _> ? U : never; | ||
}; | ||
export declare type TypeOf<T, InclRequired = false> = T extends ObjectValidator<infer U> ? FlattenObject<U> : T extends TupleValidator<infer U, infer V, infer N, infer A> ? U : T extends ArrayValidator<infer U> ? U : T extends StringValidator<infer U> ? U : T extends NumberValidator<infer U> ? U : T extends BooleanValidator<infer U> ? U : T extends NullValidator<infer U> ? U : T extends AnyValidator ? any : T extends AnyOfValidator<infer U> ? U : T extends AllOfValidator<infer U> ? U : T extends ElseValidator<infer U> ? U : T extends ThenValidator<infer U> ? U : T extends IfValidator<infer U> ? U : T extends ValueValidator<infer U, infer V> ? U : T extends RequiredValidator<infer U, infer _> ? InclRequired extends true ? U : never : T extends BaseValidator<infer U> ? U : never; | ||
export declare type TypeOf<T, InclRequired = false> = T extends ObjectValidator<infer U> ? FlattenObject<U> : T extends TupleValidator<infer U, infer V, infer N, infer A> ? U : T extends ArrayValidator<infer U> ? U : T extends StringValidator<infer U> ? U : T extends NumberValidator<infer U> ? U : T extends BooleanValidator<infer U> ? U : T extends NullValidator<infer U> ? U : T extends AnyValidator ? any : T extends RecursiveValidator ? RecursiveValue : T extends RawValidator ? unknown : T extends AnyOfValidator<infer U> ? U : T extends AllOfValidator<infer U> ? U : T extends ElseValidator<infer U> ? U : T extends ThenValidator<infer U> ? U : T extends IfValidator<infer U> ? U : T extends ValueValidator<infer U, infer V> ? U : T extends RequiredValidator<infer U, infer _> ? InclRequired extends true ? U : never : T extends BaseValidator<infer U> ? U : never; | ||
export declare type Writeable<T> = { | ||
-readonly [P in keyof T]: T[P]; | ||
}; |
@@ -6,3 +6,4 @@ "use strict"; | ||
const validator_1 = require("../value/validator"); | ||
const validator_2 = require("../any/validator"); | ||
const validator_2 = require("../required/validator"); | ||
const validator_3 = require("../any/validator"); | ||
class ObjectValidator extends validator_1.ValueValidator { | ||
@@ -17,3 +18,3 @@ constructor(properties) { | ||
var _a, _b, _c; | ||
return (_c = (_a = this._additional) !== null && _a !== void 0 ? _a : (_b = this._parent) === null || _b === void 0 ? void 0 : _b.chainedAdditional()) !== null && _c !== void 0 ? _c : new validator_2.AnyValidator(); | ||
return (_c = (_a = this._additional) !== null && _a !== void 0 ? _a : (_b = this._parent) === null || _b === void 0 ? void 0 : _b.chainedAdditional()) !== null && _c !== void 0 ? _c : new validator_3.AnyValidator(); | ||
} | ||
@@ -42,3 +43,3 @@ const(value) { | ||
properties[key] = traverser.visit(this._properties[key]); | ||
if (validator_1.isRequired(this._properties[key])) | ||
if (validator_2.isRequired(this._properties[key])) | ||
required.push(key); | ||
@@ -45,0 +46,0 @@ }); |
@@ -10,1 +10,2 @@ import { AnyType } from "../types"; | ||
} | ||
export declare function isRequired(validator: BaseValidator<unknown>): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RequiredValidator = void 0; | ||
exports.isRequired = exports.RequiredValidator = void 0; | ||
const validator_1 = require("../base/validator"); | ||
@@ -26,1 +26,5 @@ const validation_1 = require("../../validation"); | ||
exports.RequiredValidator = RequiredValidator; | ||
function isRequired(validator) { | ||
return validator instanceof RequiredValidator; | ||
} | ||
exports.isRequired = isRequired; |
@@ -5,3 +5,4 @@ "use strict"; | ||
const validator_1 = require("../value/validator"); | ||
const validator_2 = require("../any/validator"); | ||
const validator_2 = require("../required/validator"); | ||
const validator_3 = require("../any/validator"); | ||
const errors_1 = require("../../errors"); | ||
@@ -28,3 +29,3 @@ class TupleValidator extends validator_1.ValueValidator { | ||
for (let i = validators.length - 1; i >= 0; --i) { | ||
if (validator_1.isRequired(validators[i])) | ||
if (validator_2.isRequired(validators[i])) | ||
return i + 1; | ||
@@ -68,3 +69,3 @@ } | ||
type === true | ||
? new validator_2.AnyValidator() | ||
? new validator_3.AnyValidator() | ||
: type === false | ||
@@ -99,3 +100,3 @@ ? undefined | ||
? false | ||
: this._additional instanceof validator_2.AnyValidator | ||
: this._additional instanceof validator_3.AnyValidator | ||
? true | ||
@@ -102,0 +103,0 @@ : traverser.visit(this._additional) |
export declare type Type = "string" | "number" | "integer" | "object" | "array" | "boolean" | "null"; | ||
export declare type AnyType = Type | "any" | "any-of" | "all-of" | "if"; | ||
export declare type AnyType = Type | "any" | "any-of" | "all-of" | "if" | "recursive"; | ||
export declare type FilterProperties<T, Cond> = { | ||
@@ -8,1 +8,3 @@ [K in keyof T]: T[K] extends Cond ? K : never; | ||
export declare type SubType<T, Cond, Invert = false> = Invert extends true ? Omit<T, FilterNames<T, Cond>> : Pick<T, FilterNames<T, Cond>>; | ||
export declare abstract class RecursiveValue { | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RecursiveValue = void 0; | ||
class RecursiveValue { | ||
} | ||
exports.RecursiveValue = RecursiveValue; |
@@ -113,2 +113,1 @@ import { Type } from "../types"; | ||
} | ||
export declare function isRequired(validator: BaseValidator<unknown>): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isRequired = exports.ValueValidator = void 0; | ||
exports.ValueValidator = void 0; | ||
const validator_1 = require("../base/validator"); | ||
@@ -160,5 +160,1 @@ const errors_1 = require("../../errors"); | ||
} | ||
function isRequired(validator) { | ||
return validator instanceof validator_2.RequiredValidator; | ||
} | ||
exports.isRequired = isRequired; |
{ | ||
"name": "suretype", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "Typesafe JSON (Schema) validator with magic powers 🧙♂️", | ||
@@ -49,2 +49,3 @@ "author": "Gustaf Räntilä", | ||
"rimraf": "^3.0.1", | ||
"superstruct": "^0.15.0", | ||
"tempy": "^1.0.0", | ||
@@ -51,0 +52,0 @@ "ts-jest": "^26.5.3", |
@@ -14,8 +14,10 @@ [![npm version][npm-image]][npm-url] | ||
<details style="padding-left: 32px; border-left: 4px solid gray;"> | ||
<summary>It's as easy as Joi, but ~50x faster.</summary> | ||
<summary>It's as easy as Joi, but ~50x faster, (at least) as typesafe as Superstruct, but ~80x faster.</summary> | ||
<p> | ||
``` | ||
Joi x 412,045 ops/sec ±0.75% (87 runs sampled) | ||
suretype x 22,161,985 ops/sec ±0.43% (90 runs sampled) | ||
❯ yarn benchmark | ||
Joi x 385,563 ops/sec ±0.39% (95 runs sampled) | ||
Superstruct x 257,141 ops/sec ±0.34% (90 runs sampled) | ||
suretype x 21,499,582 ops/sec ±0.85% (92 runs sampled) | ||
``` | ||
@@ -26,3 +28,3 @@ | ||
It supports most (if not all) of JSON schema, and *nothing beyond that*, so that the validator schemas written in TypeScript (or JavaScript) can be ensured to be convertible into JSON schema. | ||
It supports most (if not all) of JSON schema, and *nothing beyond that*, so that the validator schemas written in TypeScript (or JavaScript) can be ensured to be convertible into JSON schema. This also prevents suretype from becoming feature bloated - it has a small and extremely simple API. | ||
@@ -91,3 +93,3 @@ Errors are prettified using [awesome-ajv-errors][awesome-ajv-errors-url]. | ||
The default behaviour of `compile` is to return a validator function returning decorated Ajv output. | ||
The default behaviour of `compile` is to return a validator function returning extended Ajv output. | ||
@@ -151,15 +153,34 @@ ```ts | ||
# Decorating schemas | ||
## Raw JSON Schema validator | ||
You can decorate a validator schema using `suretype()`. The return value is still a validator schema, but when exporting it, the decorations will be included. | ||
Sometimes it's handy to not describe the validator schema programmatically, but rather use a raw JSON Schema. There will be no type deduction, so the corresponding interface must be provided explicitly. Only use this if you know the JSON Schema maps to the interface! `raw` works just like the `v.*` functions and returns a validator schema. It can also be annotated. | ||
```ts | ||
import { suretype, v } from "suretype" | ||
import { raw, compile } from 'suretype' | ||
type User = ...; // Get this type from somewhere | ||
const userSchema = raw< User >( { type: 'object', properties: { /* ... */ } } ); | ||
// Compile as usual | ||
const ensureUser = compile( userSchema, { ensure: true } ); | ||
``` | ||
# Annotating schemas | ||
You can annotate a validator schema using `suretype()` or `annotate()`. The return value is still a validator schema, but when exporting it, the annotations will be included. | ||
The difference between `suretype()` and `annotate()` is that `suretype()` requires the `name` property, where as it's optional in `annotate()`. Use `suretype()` to annotate top-level schemas so that they have proper names in the corresponding JSON Schema. | ||
Annotations are useful when exporting the schema to other formats (e.g. JSON Schema or pretty TypeScript interfaces). | ||
```ts | ||
import { suretype, annotate, v } from "suretype" | ||
const cartItemSchema = suretype( | ||
// Decorations | ||
// Annotations | ||
{ name: "CartItem" }, | ||
// The validator schema | ||
v.object( { | ||
productId: v.string( ), | ||
productId: annotate( { title: "The product id string" }, v.string( ) ), | ||
// ... | ||
@@ -170,6 +191,6 @@ } ) | ||
The decorator interface (i.e. the fields you can decorate) is: | ||
The interface (i.e. the fields you can use) is called `Annotations`: | ||
```ts | ||
interface Decorations { | ||
interface Annotations { | ||
name: string; | ||
@@ -189,3 +210,3 @@ title?: string; | ||
The `userSchema` is the same as in the above example, although it's wrapped in `suretype()` which decorates it with a name and other attributes. | ||
The `userSchema` is the same as in the above example, although it's wrapped in `suretype()` which annotates it with a name and other attributes. | ||
@@ -192,0 +213,0 @@ <details style="padding-left: 32px;border-left: 4px solid gray;"> |
163867
68
4267
341
14