import { MaybePromise , UserError } from "@adpt/utils" ; import pReflect , { PromiseResult } from "p-reflect" ; import { isString } from "util" ; import { InternalError } from "../error" ; import { AdaptElementOrNull } from "../jsx" ; import { AdaptContext , getAdaptContext } from "../ts" ; public export type StyleFunc = ( ) => MaybePromise < AdaptElementOrNull > ; public export type StyleInput = MaybePromise < AdaptElementOrNull > | StyleFunc ; export interface Stack { root : AdaptElementOrNull | Promise < AdaptElementOrNull > ; style : StyleFunc | Promise < PromiseResult < AdaptElementOrNull > > | null ; } export type Stacks = Map < string , Stack > ; export function stack ( stackName , root , style = null ) { const stacks = getAdaptContext ( ) . adaptStacks ; if ( isNullStack ( stackName ) ) throw new Error ( `Invalid stack name "${ stackName }"` ) ; const toStore = ( typeof style === "function" ) ? style : pReflect ( Promise . resolve ( style ) ) ; stacks . set ( stackName , { root , style : toStore } ) ; } export function nullStack ( ) { return { root : null , style : null } ; } export function isNullStack ( s ) { if ( isString ( s ) ) return s === "(null)" ; return s . root === null && s . style === null ; } export interface ResolvedStack { root : AdaptElementOrNull ; style : AdaptElementOrNull ; } export async function resolveStack ( stackName , ctx ) { const stacks = ctx . adaptStacks ; if ( ! stacks ) throw new InternalError ( `No stacks found` ) ; const stk = stacks . get ( stackName ) ; if ( ! stk ) throw new UserError ( `Adapt stack '${ stackName }' not found` ) ; let root ; let style ; try { root = await stk . root ; } catch ( err ) { err . message = `Error generated by stack root: ${ err . message }` ; throw err ; } try { const styleIn = stk . style ; if ( styleIn == null ) { style = styleIn ; } else if ( typeof styleIn === "function" ) { style = await styleIn ( ) ; } else { const settled = await styleIn ; if ( settled . isFulfilled ) style = settled . value ; else throw settled . reason ; } } catch ( err ) { err . message = `Error generated by stack style: ${ err . message }` ; throw err ; } return { root , style , } ; }