import { ConfigSpec, Tag, ValueSpecAny, ValueSpecList } from "../types.ts";
import * as T from "../types.ts";
import { BuilderExtract, IBuilder } from "./builder.ts";
import { Config } from "./config.ts";
import { List } from "./list.ts";
import { Pointer } from "./pointer.ts";
export type DefaultString =
| string
| {
charset: string | null | undefined;
len: number;
};
export type Description = {
name: string;
description: string | null;
warning: string | null;
};
export type Default = {
default: A;
};
export type NullableDefault = {
default?: A;
};
export type StringSpec = {
copyable: boolean | null;
masked: boolean | null;
placeholder: string | null;
} & (
| {
pattern: string;
"pattern-description": string;
}
// deno-lint-ignore ban-types
| {}
);
export type NumberSpec = {
range: string | null;
integral: boolean | null;
units: string | null;
placeholder: number | null;
};
export type Nullable = {
nullable: boolean;
};
type _UniqueBy =
| string
| {
any: _UniqueBy[];
};
export class Value extends IBuilder {
static boolean>(a: A) {
return new Value({
type: "boolean" as const,
...a,
});
}
static string & Nullable & StringSpec>(a: A) {
return new Value({
type: "string" as const,
...a,
} as Tag<"string", T.WithDescription, DefaultString>>>);
}
static number & Nullable & NumberSpec>(a: A) {
return new Value({
type: "number" as const,
...a,
} as Tag<"number", T.WithDescription, number>>>);
}
static enum<
A extends Description &
Default & { values: readonly string[] | string[]; "value-names": Record }
>(a: A) {
return new Value({
type: "enum" as const,
...a,
});
}
static objectV<
A extends Description &
NullableDefault<{ [k: string]: unknown }> & {
"display-as": null | string;
"unique-by": null | string;
spec: Config;
"value-names": Record;
},
B extends ConfigSpec
>(a: A) {
const { spec: previousSpec, ...rest } = a;
const spec = previousSpec.build();
return new Value({
type: "object" as const,
...rest,
spec,
});
}
static union<
A extends Description &
Default & {
tag: {
id: string;
name: string | null;
description: string | null;
"variant-names": {
[key: string]: string;
};
};
variants: Variants;
"display-as": string | null;
"unique-by": _UniqueBy | null;
},
Variants extends {
[key: string]: Config;
},
B extends ConfigSpec
>(a: A) {
const { variants: previousVariants, ...rest } = a;
// deno-lint-ignore no-explicit-any
const variants: { [K in keyof Variants]: BuilderExtract } = {} as any;
for (const key in previousVariants) {
// deno-lint-ignore no-explicit-any
variants[key] = previousVariants[key].build() as any;
}
return new Value({
type: "union" as const,
...rest,
variants,
});
}
static pointer(a: Pointer) {
return new Value(a.build());
}
static list, B extends Tag<"list", ValueSpecList>>(a: A) {
return new Value(a.build());
}
}