@quenk/preconditions
Version:
Make data satisfy constraints before using.
138 lines (137 loc) • 4.17 kB
TypeScript
import { Except } from '@quenk/noni/lib/control/except';
import { Record } from '@quenk/noni/lib/data/record';
import { PreconditionSpec, Schema } from './';
import { Maybe } from '@quenk/noni/lib/data/maybe';
export declare const DEFAULT_PIPELINE_KEY = "preconditions";
/**
* Node holds information about a single schema type that has been parsed
* to produce a precondition.
*
* These types are meant to server as an intermediate representation before
* producing the final output.
*/
export type Node<T> = ObjectNode<T> | ArrayNode<T> | PrimNode<T>;
/**
* ObjectNode holds information about an object precondition.
*/
export type ObjectNode<T> = ['object', ObjectArgs<T>, Optional];
/**
* ObjectArgs:
*
* 0: Any parsed builtin preconditions.
* 1: Preconditions parsed from the `properties` key.
* 2: Preconditions parsed from the `additionalProperties` key.
* 3: Custom specified preconditions.
*/
export type ObjectArgs<T> = [T[], Record<T>, T?, T[]?];
/**
* ArrayNode holds information about an array precondition.
*
* The second element is described as follows:
*
* 0: Any parsed builtin preconditions.
* 1: Preconditions parsed from the `items` property.
* 2 : Custom specified preconditions.
*/
export type ArrayNode<T> = ['array', ArrayArgs<T>, Optional];
/**
* ArrayArgs:
*
* 0: Any parsed builtin preconditions.
* 1: Preconditions parsed from the `items` property.
* 2 : Custom specified preconditions.
*/
export type ArrayArgs<T> = [T[], T, T[]?];
/**
* PrimNode holds information about preconditions for primitive values.
*/
export type PrimNode<T> = ['boolean' | 'number' | 'string', T[], Optional];
/**
* Optional if set to true indicates a precondition is optional and should
* not be applied if no value is specified.
*
* This is only observed for properties of an object schema.
*/
export type Optional = boolean;
/**
* A string used to resolve a precondition's name consisting of it's module
* and name separated by a "dot".
*
* For example: "base.every" indicates the "every" precondition from the "base"
* module.
*/
export type Path = string;
/**
* ParseContext is used to shape the output of a parsed schema into a
* precondition.
*
* @typeparam T - determines what a precondition looks like and is specified by
* the result of visit().
*/
export interface ParseContext<T> {
/**
* builtinsAvailable to be automatically included in the parsed preconditions.
*
* Each schema type has its own list and is included in order.
*/
builtinsAvailable: Partial<BuiltinsAvailable>;
/**
* get a single precondition T given a spec.
*/
get: (spec: PreconditionSpec<T>) => Maybe<T>;
/**
* getPipeline given a Schema, returns its pipeline or an empty array if
* none exists.
*/
getPipeline(schema: Schema): PreconditionSpec<T>[];
/**
* visit a Node in the tree returning a transformation.
*
* This function is called on each Node in a tree recursively.
*/
visit: (entry: Node<T>) => T;
}
/**
* BuiltinsAvailable specifies which of the builtins to recognize in each schema
* type.
*/
export interface BuiltinsAvailable {
/**
* object schema builtins.
*/
object: Path[];
/**
* array schema builtins.
*/
array: Path[];
/**
* string schema builtins.
*/
string: Path[];
/**
* boolean schema builtins.
*/
boolean: Path[];
/**
* number schema builtins.
*/
number: Path[];
}
/**
* defaultBuiltins available.
*/
export declare const defaultBuiltins: BuiltinsAvailable;
/**
* parse a Schema into a representation.
*
* This function works by converting a schema into some generic representation
* T. It walks the properties of an object type schema or the items property
* of an array schema in a stack safe manner.
*
* The provided ParseContext is given the chance to transform each encountered
* schema into a precondition via visit().
*
* @param ctx - The parse context.
* @param schema - The root schema to parse.
*/
export declare const parse: <T>(ctx: ParseContext<T>, schema: Schema) => Except<T>;