// deno-lint-ignore-file ban-types export type ConfigSpec = Record; export type ValueType = | "string" | "number" | "boolean" | "enum" | "list" | "object" | "union"; export type ValueSpec = ValueSpecOf; // core spec types. These types provide the metadata for performing validations export type ValueSpecOf = T extends "string" ? ValueSpecString : T extends "number" ? ValueSpecNumber : T extends "boolean" ? ValueSpecBoolean : T extends "enum" ? ValueSpecEnum : T extends "list" ? ValueSpecList : T extends "object" ? ValueSpecObject : T extends "union" ? ValueSpecUnion : never; export interface ValueSpecString extends ListValueSpecString, WithStandalone { type: "string"; default: null | DefaultString; nullable: boolean; textarea: null | boolean; } export interface ValueSpecNumber extends ListValueSpecNumber, WithStandalone { type: "number"; nullable: boolean; default: null | number; } export interface ValueSpecEnum extends ListValueSpecEnum, WithStandalone { type: "enum"; default: string; } export interface ValueSpecBoolean extends WithStandalone { type: "boolean"; default: boolean; } export interface ValueSpecUnion { type: "union"; tag: UnionTagSpec; variants: { [key: string]: ConfigSpec }; default: string; } export interface ValueSpecObject extends WithStandalone { type: "object"; spec: ConfigSpec; } export interface WithStandalone { name: string; description: null | string; warning: null | string; } // no lists of booleans, lists export type ListValueSpecType = | "string" | "number" | "enum" | "object" | "union"; // represents a spec for the values of a list export type ListValueSpecOf = T extends "string" ? ListValueSpecString : T extends "number" ? ListValueSpecNumber : T extends "enum" ? ListValueSpecEnum : T extends "object" ? ListValueSpecObject : T extends "union" ? ListValueSpecUnion : never; // represents a spec for a list export type ValueSpecList = ValueSpecListOf; export interface ValueSpecListOf extends WithStandalone { type: "list"; subtype: T; spec: ListValueSpecOf; range: string; // '[0,1]' (inclusive) OR '[0,*)' (right unbounded), normal math rules default: | string[] | number[] | DefaultString[] | object[] | readonly string[] | readonly number[] | readonly DefaultString[] | readonly object[]; } // sometimes the type checker needs just a little bit of help export function isValueSpecListOf( t: ValueSpecList, s: S ): t is ValueSpecListOf { return t.subtype === s; } export interface ListValueSpecString { pattern: null | string; "pattern-description": null | string; masked: boolean; placeholder: null | string; } export interface ListValueSpecNumber { range: string; integral: boolean; units: null | string; placeholder: null | string; } export interface ListValueSpecEnum { values: string[] | readonly string[]; "value-names": { [value: string]: string }; } export interface ListValueSpecObject { spec: ConfigSpec; // this is a mapped type of the config object at this level, replacing the object's values with specs on those values "unique-by": UniqueBy; // indicates whether duplicates can be permitted in the list "display-as": null | string; // this should be a handlebars template which can make use of the entire config which corresponds to 'spec' } export type UniqueBy = | null | undefined | string | { any: readonly UniqueBy[] | UniqueBy[] } | { all: readonly UniqueBy[] | UniqueBy[] }; export interface ListValueSpecUnion { tag: UnionTagSpec; variants: { [key: string]: ConfigSpec }; "display-as": null | string; // this may be a handlebars template which can conditionally (on tag.id) make use of each union's entries, or if left blank will display as tag.id "unique-by": UniqueBy; default: string; // this should be the variantName which one prefers a user to start with by default when creating a new union instance in a list } export interface UnionTagSpec { id: string; // The name of the field containing one of the union variants "variant-names": { // the name of each variant [variant: string]: string; }; name: string; description: null | string; warning: null | string; } export type DefaultString = string | { charset: string; len: number };