@sprucelabs/schema
Version:
Static and dynamic binding plus runtime validation and transformation to ensure your app is sound. 🤓
62 lines (61 loc) • 3.09 kB
TypeScript
import { FieldDefinitions, FieldMap, FieldValueTypeGeneratorMap } from './../.spruce/schemas/fields/fields.types';
import { FieldError } from '../errors/options.types';
import { Schema, SchemaFieldsByName, SchemaValues, StaticSchemaEntity } from '../schemas.static.types';
import { Unpack, IsArray, IsRequired } from '../types/utilities.types';
export type SchemasById = Record<string, Schema[]>;
export type SchemaFieldUnion<S extends Schema[], CreateEntityInstances extends boolean = false> = {
[K in keyof S]: S[K] extends Schema ? CreateEntityInstances extends true ? StaticSchemaEntity<S[K]> : {
schemaId: S[K]['id'];
version?: S[K]['version'];
values: SchemaValues<S[K]>;
} : any;
};
export interface FieldDefinitionToSchemaOptions {
/** All definitions we're validating against */
schemasById?: SchemasById;
}
export type ToValueTypeOptions<F extends FieldDefinitions, CreateEntityInstances extends boolean = true> = {
schemasById?: SchemasById;
createEntityInstances?: CreateEntityInstances;
} & Partial<F['options']>;
/** Options passed to validate() */
export type ValidateOptions<F extends FieldDefinitions> = {
/** All schemas we're validating against */
schemasById?: SchemasById;
} & Partial<F['options']>;
export type FieldType = keyof FieldMap;
export type FieldName<F extends SchemaFieldsByName> = Extract<keyof F, string>;
export type FieldDefinition<Value = any, DefaultValue = Value, ArrayValue = Value[], DefaultArrayValue = DefaultValue[]> = {
type: FieldType;
/** Default options are empty */
options?: {};
isPrivate?: boolean;
label?: string;
hint?: string;
isRequired?: boolean;
minArrayLength?: number;
} & ({
isArray: true;
defaultValue?: DefaultArrayValue | null;
value?: ArrayValue | null;
} | {
isArray?: false | undefined;
defaultValue?: DefaultValue | null;
value?: Value | null;
});
export type FieldDefinitionValueType<F extends FieldDefinitions, CreateEntityInstances extends boolean = false, ShouldIncludeNullAndUndefinedFields extends boolean = false> = F extends FieldDefinitions ? IsRequired<IsArray<NonNullable<FieldValueTypeGeneratorMap<F, CreateEntityInstances, ShouldIncludeNullAndUndefinedFields>[F['type']]>, F['isArray']>, F['isRequired']> : any;
export interface Field<F extends FieldDefinitions> {
readonly definition: F;
readonly type: F['type'];
readonly options: F['options'];
readonly isRequired: F['isRequired'];
readonly isPrivate: F['isPrivate'];
readonly isArray: F['isArray'];
readonly minArrayLength: F['minArrayLength'];
readonly label: F['label'];
readonly hint: F['hint'];
name: string;
validate(value: any, options?: ValidateOptions<F>): FieldError[];
toValueType<CreateEntityInstances extends boolean>(value: any, options?: ToValueTypeOptions<F, CreateEntityInstances>): Unpack<Exclude<FieldDefinitionValueType<F, CreateEntityInstances>, undefined | null>>;
}
export type FieldSubclass<F extends FieldDefinitions> = new (name: string, definition: F) => Field<F>;