Files
start-os/sdk/base/lib/actions/input/builder/inputSpecTools.ts
Aiden McClelland 7909941b70 feat: builder-style InputSpec API, prefill plumbing, and port forward fix
- Add addKey() and add() builder methods to InputSpec with InputSpecTools
- Move OuterType to last generic param on Value, List, and all dynamic methods
- Plumb prefill through getActionInput end-to-end (core → container-runtime → SDK)
- Filter port_forwards to enabled addresses only
- Bump SDK to 0.4.0-beta.50
2026-02-19 16:44:44 -07:00

275 lines
7.1 KiB
TypeScript

import { InputSpec, LazyBuild } from './inputSpec'
import { AsRequired, FileInfo, Value } from './value'
import { List } from './list'
import { UnionRes, UnionResStaticValidatedAs, Variants } from './variants'
import {
Pattern,
RandomString,
ValueSpecDatetime,
ValueSpecText,
} from '../inputSpecTypes'
import { DefaultString } from '../inputSpecTypes'
import { Parser } from 'ts-matches'
import { ListValueSpecText } from '../inputSpecTypes'
export interface InputSpecTools<OuterType> {
Value: BoundValue<OuterType>
Variants: typeof Variants
InputSpec: typeof InputSpec
List: BoundList<OuterType>
}
export interface BoundValue<OuterType> {
// Static (non-dynamic) methods — no OuterType involved
toggle: typeof Value.toggle
text: typeof Value.text
textarea: typeof Value.textarea
number: typeof Value.number
color: typeof Value.color
datetime: typeof Value.datetime
select: typeof Value.select
multiselect: typeof Value.multiselect
object: typeof Value.object
file: typeof Value.file
list: typeof Value.list
hidden: typeof Value.hidden
union: typeof Value.union
// Dynamic methods with OuterType pre-bound (last generic param removed)
dynamicToggle(
a: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: boolean
disabled?: false | string
},
OuterType
>,
): Value<boolean, boolean, OuterType>
dynamicText<Required extends boolean>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: DefaultString | null
required: Required
masked?: boolean
placeholder?: string | null
minLength?: number | null
maxLength?: number | null
patterns?: Pattern[]
inputmode?: ValueSpecText['inputmode']
disabled?: string | false
generate?: null | RandomString
},
OuterType
>,
): Value<AsRequired<string, Required>, string | null, OuterType>
dynamicTextarea<Required extends boolean>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: string | null
required: Required
minLength?: number | null
maxLength?: number | null
patterns?: Pattern[]
minRows?: number
maxRows?: number
placeholder?: string | null
disabled?: false | string
},
OuterType
>,
): Value<AsRequired<string, Required>, string | null, OuterType>
dynamicNumber<Required extends boolean>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: number | null
required: Required
min?: number | null
max?: number | null
step?: number | null
integer: boolean
units?: string | null
placeholder?: string | null
disabled?: false | string
},
OuterType
>,
): Value<AsRequired<number, Required>, number | null, OuterType>
dynamicColor<Required extends boolean>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: string | null
required: Required
disabled?: false | string
},
OuterType
>,
): Value<AsRequired<string, Required>, string | null, OuterType>
dynamicDatetime<Required extends boolean>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: string | null
required: Required
inputmode?: ValueSpecDatetime['inputmode']
min?: string | null
max?: string | null
disabled?: false | string
},
OuterType
>,
): Value<AsRequired<string, Required>, string | null, OuterType>
dynamicSelect<Values extends Record<string, string>>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: string
values: Values
disabled?: false | string | string[]
},
OuterType
>,
): Value<keyof Values & string, keyof Values & string, OuterType>
dynamicMultiselect<Values extends Record<string, string>>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default: string[]
values: Values
minLength?: number | null
maxLength?: number | null
disabled?: false | string | string[]
},
OuterType
>,
): Value<(keyof Values & string)[], (keyof Values & string)[], OuterType>
dynamicFile<Required extends boolean>(
a: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
extensions: string[]
required: Required
},
OuterType
>,
): Value<AsRequired<FileInfo, Required>, FileInfo | null, OuterType>
dynamicUnion<
VariantValues extends {
[K in string]: {
name: string
spec: InputSpec<any>
}
},
>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
variants: Variants<VariantValues>
default: keyof VariantValues & string
disabled: string[] | false | string
},
OuterType
>,
): Value<UnionRes<VariantValues>, UnionRes<VariantValues>, OuterType>
dynamicUnion<
StaticVariantValues extends {
[K in string]: {
name: string
spec: InputSpec<any, any>
}
},
VariantValues extends StaticVariantValues,
>(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
variants: Variants<VariantValues>
default: keyof VariantValues & string
disabled: string[] | false | string
},
OuterType
>,
validator: Parser<unknown, UnionResStaticValidatedAs<StaticVariantValues>>,
): Value<
UnionRes<VariantValues>,
UnionResStaticValidatedAs<StaticVariantValues>,
OuterType
>
dynamicHidden<T>(
getParser: LazyBuild<Parser<unknown, T>, OuterType>,
): Value<T, T, OuterType>
}
export interface BoundList<OuterType> {
text: typeof List.text
obj: typeof List.obj
dynamicText(
getA: LazyBuild<
{
name: string
description?: string | null
warning?: string | null
default?: string[]
minLength?: number | null
maxLength?: number | null
disabled?: false | string
generate?: null | RandomString
spec: {
masked?: boolean
placeholder?: string | null
minLength?: number | null
maxLength?: number | null
patterns?: Pattern[]
inputmode?: ListValueSpecText['inputmode']
}
},
OuterType
>,
): List<string[], string[], OuterType>
}
export function createInputSpecTools<OuterType>(): InputSpecTools<OuterType> {
return {
Value: Value as any as BoundValue<OuterType>,
Variants,
InputSpec,
List: List as any as BoundList<OuterType>,
}
}