mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
@@ -1,8 +1,9 @@
|
||||
import { ValueSpec } from "../inputSpecTypes"
|
||||
import { PartialValue, Value } from "./value"
|
||||
import { Value } from "./value"
|
||||
import { _ } from "../../../util"
|
||||
import { Effects } from "../../../Effects"
|
||||
import { Parser, object } from "ts-matches"
|
||||
import { DeepPartial } from "../../../types"
|
||||
|
||||
export type LazyBuildOptions<Store> = {
|
||||
effects: Effects
|
||||
@@ -22,8 +23,8 @@ export type ExtractPartialInputSpecType<
|
||||
| InputSpec<Record<string, any>, any>
|
||||
| InputSpec<Record<string, any>, never>,
|
||||
> = A extends InputSpec<infer B, any> | InputSpec<infer B, never>
|
||||
? PartialValue<B>
|
||||
: PartialValue<A>
|
||||
? DeepPartial<B>
|
||||
: DeepPartial<A>
|
||||
|
||||
export type InputSpecOf<A extends Record<string, any>, Store = never> = {
|
||||
[K in keyof A]: Value<A[K], Store>
|
||||
@@ -94,7 +95,7 @@ export class InputSpec<Type extends Record<string, any>, Store = never> {
|
||||
public validator: Parser<unknown, Type>,
|
||||
) {}
|
||||
_TYPE: Type = null as any as Type
|
||||
_PARTIAL: PartialValue<Type> = null as any as PartialValue<Type>
|
||||
_PARTIAL: DeepPartial<Type> = null as any as DeepPartial<Type>
|
||||
async build(options: LazyBuildOptions<Store>) {
|
||||
const answer = {} as {
|
||||
[K in keyof Type]: ValueSpec
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { InputSpec, LazyBuild } from "./inputSpec"
|
||||
import { List } from "./list"
|
||||
import { PartialUnionRes, UnionRes, Variants } from "./variants"
|
||||
import { Variants } from "./variants"
|
||||
import {
|
||||
FilePath,
|
||||
Pattern,
|
||||
@@ -30,7 +30,7 @@ import { DeepPartial } from "../../../types"
|
||||
|
||||
type AsRequired<T, Required extends boolean> = Required extends true
|
||||
? T
|
||||
: T | null | undefined
|
||||
: T | null
|
||||
|
||||
const testForAsRequiredParser = once(
|
||||
() => object({ required: literal(true) }).test,
|
||||
@@ -38,21 +38,12 @@ const testForAsRequiredParser = once(
|
||||
function asRequiredParser<
|
||||
Type,
|
||||
Input,
|
||||
Return extends
|
||||
| Parser<unknown, Type>
|
||||
| Parser<unknown, Type | null | undefined>,
|
||||
Return extends Parser<unknown, Type> | Parser<unknown, Type | null>,
|
||||
>(parser: Parser<unknown, Type>, input: Input): Return {
|
||||
if (testForAsRequiredParser()(input)) return parser as any
|
||||
return parser.optional() as any
|
||||
return parser.nullable() as any
|
||||
}
|
||||
|
||||
export type PartialValue<T> =
|
||||
T extends UnionRes<infer A, infer B>
|
||||
? PartialUnionRes<A, B>
|
||||
: T extends {}
|
||||
? { [P in keyof T]?: PartialValue<T[P]> }
|
||||
: T
|
||||
|
||||
export class Value<Type, Store> {
|
||||
protected constructor(
|
||||
public build: LazyBuild<Store, ValueSpec>,
|
||||
@@ -196,7 +187,7 @@ export class Value<Type, Store> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
return new Value<string | null, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "text" as const,
|
||||
@@ -213,7 +204,7 @@ export class Value<Type, Store> {
|
||||
generate: a.generate ?? null,
|
||||
...a,
|
||||
}
|
||||
}, string.optional())
|
||||
}, string.nullable())
|
||||
}
|
||||
static textarea<Required extends boolean>(a: {
|
||||
name: string
|
||||
@@ -265,7 +256,7 @@ export class Value<Type, Store> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
return new Value<string | null, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
description: null,
|
||||
@@ -278,7 +269,7 @@ export class Value<Type, Store> {
|
||||
immutable: false,
|
||||
...a,
|
||||
}
|
||||
}, string.optional())
|
||||
}, string.nullable())
|
||||
}
|
||||
static number<Required extends boolean>(a: {
|
||||
name: string
|
||||
@@ -351,7 +342,7 @@ export class Value<Type, Store> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<number | null | undefined, Store>(async (options) => {
|
||||
return new Value<number | null, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "number" as const,
|
||||
@@ -366,7 +357,7 @@ export class Value<Type, Store> {
|
||||
immutable: false,
|
||||
...a,
|
||||
}
|
||||
}, number.optional())
|
||||
}, number.nullable())
|
||||
}
|
||||
static color<Required extends boolean>(a: {
|
||||
name: string
|
||||
@@ -413,7 +404,7 @@ export class Value<Type, Store> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
return new Value<string | null, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "color" as const,
|
||||
@@ -423,7 +414,7 @@ export class Value<Type, Store> {
|
||||
immutable: false,
|
||||
...a,
|
||||
}
|
||||
}, string.optional())
|
||||
}, string.nullable())
|
||||
}
|
||||
static datetime<Required extends boolean>(a: {
|
||||
name: string
|
||||
@@ -483,7 +474,7 @@ export class Value<Type, Store> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
return new Value<string | null, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "datetime" as const,
|
||||
@@ -496,7 +487,7 @@ export class Value<Type, Store> {
|
||||
immutable: false,
|
||||
...a,
|
||||
}
|
||||
}, string.optional())
|
||||
}, string.nullable())
|
||||
}
|
||||
static select<Values extends Record<string, string>>(a: {
|
||||
name: string
|
||||
@@ -690,14 +681,14 @@ export class Value<Type, Store> {
|
||||
// }
|
||||
// >,
|
||||
// ) {
|
||||
// return new Value<FilePath | null | undefined, Store>(
|
||||
// return new Value<FilePath | null, Store>(
|
||||
// async (options) => ({
|
||||
// type: "file" as const,
|
||||
// description: null,
|
||||
// warning: null,
|
||||
// ...(await a(options)),
|
||||
// }),
|
||||
// object({ filePath: string }).optional(),
|
||||
// object({ filePath: string }).nullable(),
|
||||
// )
|
||||
// }
|
||||
static union<
|
||||
@@ -822,6 +813,10 @@ export class Value<Type, Store> {
|
||||
}, parser)
|
||||
}
|
||||
|
||||
map<U>(fn: (value: Type) => U): Value<U, Store> {
|
||||
return new Value(this.build, this.validator.map(fn))
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this during the times that the input needs a more specific type.
|
||||
* Used in types that the value/ variant/ list/ inputSpec is constructed somewhere else.
|
||||
|
||||
@@ -29,27 +29,6 @@ export type UnionRes<
|
||||
}
|
||||
}[K]
|
||||
|
||||
export type PartialUnionRes<
|
||||
Store,
|
||||
VariantValues extends {
|
||||
[K in string]: {
|
||||
name: string
|
||||
spec: InputSpec<any, Store> | InputSpec<any, never>
|
||||
}
|
||||
},
|
||||
K extends keyof VariantValues & string = keyof VariantValues & string,
|
||||
> = {
|
||||
[key in keyof VariantValues]: {
|
||||
selection?: key
|
||||
value?: ExtractPartialInputSpecType<VariantValues[key]["spec"]>
|
||||
other?: {
|
||||
[key2 in Exclude<keyof VariantValues & string, key>]?: DeepPartial<
|
||||
ExtractInputSpecType<VariantValues[key2]["spec"]>
|
||||
>
|
||||
}
|
||||
}
|
||||
}[K]
|
||||
|
||||
/**
|
||||
* Used in the the Value.select { @link './value.ts' }
|
||||
* to indicate the type of select variants that are available. The key for the record passed in will be the
|
||||
|
||||
Reference in New Issue
Block a user