This commit is contained in:
Matt Hill
2023-03-27 15:35:20 -06:00
parent 5e2d87c11b
commit 42951b4fa2
7 changed files with 101 additions and 88 deletions

View File

@@ -36,7 +36,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
name: string;
description: string | null;
warning: string | null;
default: string[]
default: string[];
range: string;
spec: {
masked: boolean | null;
@@ -58,7 +58,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
name: string;
description: string | null;
warning: string | null;
default: string[]
default: string[];
range: string;
spec: {
range: string;
@@ -79,7 +79,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
name: string;
description: string | null;
warning: string | null;
default: Record<string, unknown>[]
default: Record<string, unknown>[];
range: string;
spec: {
spec: Config<InputSpec>;
@@ -112,10 +112,12 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
name: string;
description: string | null;
warning: string | null;
default: Record<string, unknown>[]
default: Record<string, unknown>[];
range: string;
spec: {
variants: Variants<{ [key: string]: { name: string, spec: InputSpec } }>;
variants: Variants<{
[key: string]: { name: string; spec: InputSpec };
}>;
displayAs: null | string;
uniqueBy: UniqueBy;
default: string;

View File

@@ -13,9 +13,9 @@ import {
export type DefaultString =
| string
| {
charset: string | null | undefined;
len: number;
};
charset: string | null | undefined;
len: number;
};
/**
* A value is going to be part of the form in the FE of the OS.
@@ -43,10 +43,10 @@ export type DefaultString =
export class Value<A extends ValueSpec> extends IBuilder<A> {
static boolean<
A extends {
name: string,
description: string | null
warning: string | null
default: boolean | null
name: string;
description: string | null;
warning: string | null;
default: boolean | null;
}
>(a: A) {
return new Value({
@@ -56,11 +56,11 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
}
static string<
A extends {
name: string,
description: string | null
warning: string | null
nullable: boolean
default: DefaultString | null
name: string;
description: string | null;
warning: string | null;
nullable: boolean;
default: DefaultString | null;
masked: boolean | null;
placeholder: string | null;
pattern: string | null;
@@ -75,11 +75,11 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
}
static number<
A extends {
name: string
description: string | null
warning: string | null
nullable: boolean
default: number | null
name: string;
description: string | null;
warning: string | null;
nullable: boolean;
default: number | null;
range: string;
integral: boolean;
units: string | null;
@@ -93,11 +93,11 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
}
static select<
A extends {
name: string
description: string | null
warning: string | null
nullable: boolean
default: string | null
name: string;
description: string | null;
warning: string | null;
nullable: boolean;
default: string | null;
values: Record<string, string>;
}
>(a: A) {
@@ -108,12 +108,12 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
}
static multiselect<
A extends {
name: string
description: string | null
warning: string | null
default: string[]
name: string;
description: string | null;
warning: string | null;
default: string[];
values: Record<string, string>;
range: string
range: string;
}
>(a: A) {
return new Value({
@@ -139,11 +139,11 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
});
}
static union<
A extends {
A extends {
name: string;
description: string | null;
warning: string | null;
variants: Variants<{ [key: string]: { name: string, spec: InputSpec } }>;
variants: Variants<{ [key: string]: { name: string; spec: InputSpec } }>;
default: string;
}
>(a: A) {

View File

@@ -41,22 +41,25 @@ import { Config } from ".";
export class Variants<
A extends {
[key: string]: {
name: string,
spec: InputSpec
}
name: string;
spec: InputSpec;
};
}
> extends IBuilder<A> {
static of<
A extends {
[key: string]: { name: string, spec: Config<InputSpec> };
[key: string]: { name: string; spec: Config<InputSpec> };
}
>(a: A) {
const variants: { [K in keyof A]: { name: string, spec: BuilderExtract<A[K]['spec']> } } = {} as any;
const variants: {
[K in keyof A]: { name: string; spec: BuilderExtract<A[K]["spec"]> };
} = {} as any;
for (const key in a) {
const value = a[key]
const value = a[key];
variants[key] = {
name: value.name, spec: value.spec.build() as any
}
name: value.name,
spec: value.spec.build() as any,
};
}
return new Variants(variants);
}

View File

@@ -48,9 +48,8 @@ export interface ValueSpecNumber extends ListValueSpecNumber, WithStandalone {
export interface ValueSpecSelect extends SelectBase, WithStandalone {
type: "select";
nullable: boolean
nullable: boolean;
default: null | string;
}
export interface ValueSpecMultiselect extends SelectBase, WithStandalone {
@@ -67,7 +66,7 @@ export interface ValueSpecBoolean extends WithStandalone {
export interface ValueSpecUnion extends WithStandalone {
type: "union";
variants: { [key: string]: { name: string, spec: InputSpec } };
variants: { [key: string]: { name: string; spec: InputSpec } };
default: null | string;
}
@@ -116,14 +115,14 @@ export interface ValueSpecListOf<T extends ListValueSpecType>
spec: ListValueSpecOf<T>;
range: string; // '[0,1]' (inclusive) OR '[0,*)' (right unbounded), normal math rules
default:
| string[]
| number[]
| DefaultString[]
| Record<string, unknown>[]
| readonly string[]
| readonly number[]
| readonly DefaultString[]
| readonly Record<string, unknown>[];
| string[]
| number[]
| DefaultString[]
| Record<string, unknown>[]
| readonly string[]
| readonly number[]
| readonly DefaultString[]
| readonly Record<string, unknown>[];
}
// sometimes the type checker needs just a little bit of help
@@ -166,7 +165,7 @@ export type UniqueBy =
| { all: readonly UniqueBy[] | UniqueBy[] };
export interface ListValueSpecUnion {
variants: { [key: string]: { name: string, spec: InputSpec } };
variants: { [key: string]: { name: string; spec: InputSpec } };
/** 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*/
displayAs: null | string;
uniqueBy: UniqueBy;

View File

@@ -2,7 +2,16 @@ import * as matches from "ts-matches";
import { Parser } from "ts-matches";
import { InputSpec, ValueSpec as ValueSpecAny } from "../config/config-types";
const { string, some, object, arrayOf, dictionary, unknown, number, literals, boolean, array } = matches
const {
string,
some,
object,
dictionary,
unknown,
number,
literals,
boolean,
} = matches;
type TypeBoolean = "boolean";
type TypeString = "string";
@@ -83,8 +92,8 @@ export type TypeFromProps<A> =
const isType = object({ type: string });
const matchVariant = object({
name: string,
spec: unknown
})
spec: unknown,
});
const recordString = dictionary([string, unknown]);
const matchDefault = object({ default: unknown });
const matchNullable = object({ nullable: literals(true) });
@@ -157,13 +166,13 @@ export function matchNumberWithRange(range: string) {
leftValue === "*"
? (_) => true
: left === "["
? (x) => x >= Number(leftValue)
: (x) => x > Number(leftValue),
? (x) => x >= Number(leftValue)
: (x) => x > Number(leftValue),
leftValue === "*"
? "any"
: left === "["
? `greaterThanOrEqualTo${leftValue}`
: `greaterThan${leftValue}`
? `greaterThanOrEqualTo${leftValue}`
: `greaterThan${leftValue}`
)
.validate(
// prettier-ignore
@@ -192,10 +201,7 @@ const isGenerator = object({
charset: string,
len: number,
}).test;
function defaultNullable<A>(
parser: Parser<unknown, A>,
value: unknown
) {
function defaultNullable<A>(parser: Parser<unknown, A>, value: unknown) {
if (matchDefault.test(value)) {
if (isGenerator(value.default)) {
return parser.defaultTo(
@@ -257,7 +263,7 @@ export function guardAll<A extends ValueSpecAny>(
}
case "select":
if (matchValues.test(value)) {
const valueKeys = Object.keys(value.values)
const valueKeys = Object.keys(value.values);
return defaultNullable(
literals(valueKeys[0], ...valueKeys),
value
@@ -270,7 +276,7 @@ export function guardAll<A extends ValueSpecAny>(
(matchRange.test(value) && matchNumberWithRange(value.range).test) ||
(() => true);
const valueKeys = Object.keys(value.values)
const valueKeys = Object.keys(value.values);
return defaultNullable(
matches
.literals(valueKeys[0], ...valueKeys)