Files
deepseek-harness/vendor/schemastery
Tianyi Cui d2fb352f3e Enable maximum-strict TypeScript across our packages
tsconfig.base.json adds noUncheckedIndexedAccess,
exactOptionalPropertyTypes, noImplicitOverride,
noFallthroughCasesInSwitch, noUnusedLocals, and noUnusedParameters on
top of strict. Vendored packages opt out of the new flags locally
(their tsconfigs are ours to regenerate; their source is not), keeping
upstream-sync friendliness.

Our code fixed accordingly: index accesses acknowledge undefined
(assembler flush cursors, lastTurnNumber); optional properties are
omitted instead of set-to-undefined (GenerateResult.usage,
ToolDefinition.strict, GenerateOptions.system/tools, error payloads
via an errorData helper); Session.onAppend is explicitly
`(…) => void | undefined`; tests and examples updated for unused
parameters and indexed access.
2026-06-11 14:02:47 +08:00
..

Schemastery

Codecov downloads npm GitHub

Type Driven Schema Validator.

Features

  • Lightweight. Much smaller than other validation libraries.
  • Easy to use. You can use any schema as a function or constructor directly.
  • Powerful. Schemastery supports some advanced types such as union, intersect and transform.
  • Extensible. You can create your own schema types via Schema.extend().
  • Serializable. Schema objects can be serialized into JSON and then be hydrated in another environment.

Basic Examples

use as validator (JavaScript)

const Schema = require('schemastery')

const validate = Schema.number().default(10)

validate(0)     // 0
validate(null)  // 10
validate('')    // TypeError

use as constructor (TypeScript)

import Schema from 'schemastery'

interface Config {
  foo: Record<string, string>
  bar: string[]
}

const Config = Schema.object({
  foo: Schema.dict(Schema.string()).default({}),
  bar: Schema.array(Schema.string()).default([]),
})

// config is an instance of Config
// in this case, that is { foo: {}, bar: [] }
const config = new Config()

General Types

Schema.any()

Assert that the value is of any type.

const validate = Schema.any()

validate()            // undefined
validate(0)           // 0
validate({})          // {}

Schema.never()

Assert that the value is nullable.

const validate = Schema.never()

validate()            // undefined
validate(0)           // TypeError
validate({})          // TypeError

Schema.const(value)

Assert that the value is equal to the given constant.

const validate = Schema.const(10)

validate(10)          // 10
validate(0)           // TypeError

Schema.number()

Assert that the value is a number.

const validate = Schema.number()

validate()            // undefined
validate(1)           // 1
validate('')          // TypeError

Schema.string()

Assert that the value is a string.

const validate = Schema.string()

validate()            // undefined
validate(0)           // TypeError
validate('foo')       // 'foo'

Schema.boolean()

Assert that the value is a boolean.

const validate = Schema.boolean()

validate()            // undefined
validate(0)           // TypeError
validate(true)        // true

Schema.is(constructor)

Assert that the value is an instance of the given constructor.

const validate = Schema.is(RegExp)

validate()            // undefined
validate(/foo/)       // /foo/
validate('foo')       // TypeError

Schema.array(inner)

Assert that the value is an array of inner. The default value will be [] if not specified.

const validate = Schema.array(Schema.number())

validate()                  // []
validate(0)                 // TypeError
validate([0, 1])            // [0, 1]
validate([0, '1'])          // TypeError

Schema.dict(inner)

Assert that the value is a dictionary of inner. The default value will be {} if not specified.

const validate = Schema.dict(Schema.number())

validate()                  // {}
validate(0)                 // TypeError
validate({ a: 0, b: 1 })    // { a: 0, b: 1 }
validate({ a: 0, b: '1' })  // TypeError

Schema.tuple(list)

Assert that the value is a tuple whose each element is of corresponding subtype. The default value will be [] if not specified.

const validate = Schema.tuple([
  Schema.number(),
  Schema.string(),
])

validate()                  // []
validate([0])               // { a: 0 }
validate([0, 1])            // TypeError
validate([0, '1'])          // [0, '1']

Schema.object(dict)

Assert that the value is an object whose each property is of corresponding subtype. The default value will be {} if not specified.

const validate = Schema.object({
  a: Schema.number(),
  b: Schema.string(),
})

validate()                  // {}
validate({ a: 0 })          // { a: 0 }
validate({ a: 0, b: 1 })    // TypeError
validate({ a: 0, b: '1' })  // { a: 0, b: '1' }

Schema.union(list)

Assert that the value is one of the specified types.

const validate = Schema.union([
  Schema.number(),
  Schema.string(),
])

validate()                  // undefined
validate(0)                 // 0
validate('1')               // '1'
validate(true)              // TypeError

Schema.intersect(list)

Assert that the value should match each specified type.

const validate = Schema.intersect([
  Schema.object({ a: Schema.string().required() }),
  Schema.object({ b: Schema.number().default(0) }),
])

validate()                  // TypeError
validate({ a: '' })         // { a: '', b: 0 }
validate({ a: '', b: 1 })   // { a: '', b: 1 }
validate({ a: '', b: '2' }) // TypeError

Schema.transform(inner, callback)

Assert that the value is of the specified subtype and then transformed by callback.

const validate = Schema.transform(Schema.number().default(0), n => n + 1)

validate()                  // 1
validate('0')               // TypeError
validate(10)                // 11

Instance Methods

Note: default and required are mutually exclusive.

schema.required()

Assert that the value is not nullable.

schema.default(value)

Set the fallback value when nullable.

schema.description(text)

Set the description of the schema.

schema.simplify(value)

Normalize a value by removing parts that are equal to schema defaults. This is useful when storing user configuration and keeping persisted files compact.

const Config = Schema.object({
  foo: Schema.string().default(''),
  bar: Schema.number().default(0),
})

Config.simplify({ foo: '', bar: 1 }) // { bar: 1 }

Validation Options

All schemas are callable. The second argument accepts validation options:

const Config = Schema.object({
  foo: Schema.number(),
})

Config({ foo: '1' }, { autofix: true }) // {}
  • autofix: remove invalid object properties where possible.
  • ignore: skip validation for selected values and schema nodes.
  • path: provide an initial path for nested validation errors.

Shorthand Syntax

Some shorthand syntax is available for inner types.

  • undefined -> Schema.any()
  • String -> Schema.string()
  • Number -> Schema.number()
  • Boolean -> Schema.boolean()
  • 1 -> Schema.const(1) (only for primitive types)
  • Date -> Schema.is(Date)
Schema.array(String)        // Schema.array(Schema.string())
Schema.dict(RegExp)         // Schema.dict(Schema.is(RegExp))
Schema.union([1, 2])        // Schema.union([Schema.const(1), Schema.const(2)])

You can also use Schema.from() to get the inferred schema from a shorthand value.

Schema.from()               // Schema.any()
Schema.from(Date)           // Schema.is(Date)
Schema.from('foo')          // Schema.const('foo')

Advanced Examples

Here are some examples which demonstrate how to define advanced types.

Enumeration

const Enum = Schema.union(['red', 'blue'])

Enum('red')                 // 'red'
Enum('blue')                // 'blue'
Enum('green')               // TypeError

ToString

const ToString = Schema.transform(Schema.any(), v => String(v))

ToString('')                // ''
ToString(0)                 // '0'
ToString({})                // '{}'

Listable

const Listable = Schema.union([
  Schema.array(Number),
  Schema.transform(Number, n => [n]),
]).default([])

Listable()                  // []
Listable(0)                 // [0]
Listable([1, 2])            // [1, 2]

Alias

const Config = Schema.dict(Number, Schema.union([
  'foo',
  Schema.transform('bar', () => 'foo'),
]))

Config({ foo: 1 })          // { foo: 1 }
Config({ bar: 2 })          // { foo: 2 }
Config({ bar: '3' })        // TypeError

Extensibility

Custom schema types are registered with Schema.extend(type, resolve). A resolver receives the input value, schema node, validation options, and a strict flag. Return [value] for accepted input, or [value, adapted] when the caller should write an adapted value back to the source object.

Schema.extend('trimmed', (data, schema, options) => {
  if (typeof data !== 'string') {
    throw new Schema.ValidationError(`expected string but got ${data}`, options)
  }
  return [data.trim()]
})

Serializability

const schema1 = Schema.object({
  foo: Schema.string(),
  bar: Schema.number(),
})

// should have the same effect as schema1
const schema2 = new Schema(JSON.parse(JSON.stringify(schema1)))

Schemastery also exposes the Standard Schema ~standard property, so compatible tools can validate values without depending on Schemastery-specific APIs.