import Sociably, { SociablyNode, SociablyEmpty, SociablyElement, SociablyThread, ContainerComponent } from '@sociably/core'; import type { MaybeContainer } from '@sociably/core/service'; import { SOCIABLY_SCRIPT_TYPE } from './constant.js'; import type { IF, ELSE, ELSE_IF, WHILE, PROMPT, LABEL, CALL, EFFECT, RETURN } from './keyword.js'; type StartScriptProps = { params?: Params; goto?: string; }; export type ScriptLibrary = { $$typeof: typeof SOCIABLY_SCRIPT_TYPE; Start: ContainerComponent>; commands: ScriptCommand[]; initVars: (params: Params) => Vars; name: string; stopPointIndex: Map; meta: Meta; }; export type AnyScriptLibrary = ScriptLibrary; export type ScriptCircs = { platform: string; thread: SociablyThread; vars: Vars; meta: Meta; }; export type ContentFn = (circs: ScriptCircs) => SociablyNode | Promise; export type ContentNode = MaybeContainer>; export type ConditionMatchFn = (circs: ScriptCircs) => boolean | Promise; export type ConditionMatcher = MaybeContainer>; /** * @category Keyword Props */ export type IfProps = { condition: ConditionMatcher; children: ScriptNode; }; /** * @category Keyword Element */ export type IfElement = SociablyElement, typeof IF>; /** * @category Keyword Props */ export type BlockProps = { children: ScriptNode; }; /** * @category Keyword Element */ export type ElseElement = SociablyElement, typeof ELSE>; /** * @category Keyword Element */ export type ElseIfElement = SociablyElement, typeof ELSE_IF>; /** * @category Keyword Props */ export type WhileProps = { condition: ConditionMatcher; children: ScriptNode; }; /** * @category Keyword Element */ export type WhileElement = SociablyElement, typeof WHILE>; export type PromptSetFn = (circs: ScriptCircs, input: Input) => Vars | Promise; export type PromptSetter = MaybeContainer>; /** * @category Keyword Props */ export type PromptProps = { key: string; set?: PromptSetter; }; /** * @category Keyword Element */ export type PromptElement = SociablyElement, typeof PROMPT>; /** * @category Keyword Props */ export type LabelProps = { key: string; }; /** * @category Keyword Element */ export type LabelElement = SociablyElement; export type CallParamsFn = (circs: ScriptCircs) => Params | Promise; export type CallParamsGetter = MaybeContainer>; export type CallReturnSetFn = (circs: ScriptCircs, returnValue: Return) => Vars | Promise; export type CallReturnSetter = MaybeContainer>; /** * @category Keyword Props */ export type CallProps = Script extends ScriptLibrary ? { script: Script; key: string; params?: CallParamsGetter; set?: CallReturnSetter; goto?: string; } : never; /** * @category Keyword Element */ export type CallElement = SociablyElement, typeof CALL>; export type EffectSetFn = (circs: ScriptCircs) => Vars | Promise; export type EffectSetter = MaybeContainer>; export type EffectYieldFn = (circs: ScriptCircs, prevValue: undefined | Yield) => Yield | Promise; export type EffectYielder = MaybeContainer>; /** * @category Keyword Props */ export type EffectProps = { set?: EffectSetter; yield?: EffectYielder; }; /** * @category Keyword Element */ export type EffectElement = SociablyElement, typeof EFFECT>; export type ReturnValueFn = (circs: ScriptCircs) => Return | Promise; export type ReturnValueGetter = MaybeContainer>; /** * @category Keyword Props */ export type ReturnProps = { value?: ReturnValueGetter; }; /** * @category Keyword Element */ export type ReturnElement = SociablyElement, typeof RETURN>; export type ScriptElement = IfElement | WhileElement | PromptElement | LabelElement | CallElement | ReturnElement; export type ScriptNode = SociablyEmpty | ContentNode | ScriptElement | ScriptNode[] | SociablyElement<{ children: ScriptNode; }, typeof Sociably.Fragment>; export type ConditionsSegment = { type: 'conditions'; branches: { condition: ConditionMatcher; body: ScriptSegment[]; }[]; fallbackBody: null | ScriptSegment[]; }; export type WhileSegment = { type: 'while'; condition: ConditionMatcher; body: ScriptSegment[]; }; export type LabelSegment = { type: 'label'; key: string; }; export type ContentCommand = { type: 'content'; getContent: ContentNode; }; export type PromptCommand = { type: 'prompt'; key: string; setVars?: PromptSetter; }; export type CallCommand = { type: 'call'; key: string; script: ScriptLibrary; withParams?: CallParamsGetter; setVars?: CallReturnSetter; goto?: string; }; export type JumpCommand = { type: 'jump'; offset: number; }; export type JumpCondCommand = { type: 'jump_cond'; offset: number; condition: ConditionMatcher; isNot: boolean; }; export type EffectCommand = { type: 'effect'; setVars?: EffectSetter; yieldValue?: EffectYielder; }; export type ReturnCommand = { type: 'return'; getValue?: ReturnValueGetter; }; export type ScriptSegment = ContentCommand | ConditionsSegment | WhileSegment | PromptCommand | CallCommand | EffectCommand | LabelSegment | ReturnCommand; export type ScriptCommand = ContentCommand | JumpCommand | JumpCondCommand | PromptCommand | CallCommand | EffectCommand | ReturnCommand; export type CallStatus = { script: ScriptLibrary; vars: Vars; stopAt: undefined | string; }; export type SerializedCallStatus = { name: string; vars: Vars; stopAt: string; }; export type ScriptRuntimeState = { version: '0'; timestamp: number; callStack: SerializedCallStatus[]; }; export type ParamsOfScript