import * as T from "../types" import { Config, ExtractConfigType } from "../config/builder/config" import { ActionMetadata, ActionResult, Effects, ExportedAction } from "../types" export type MaybeFn = | Value | ((options: { effects: Effects }) => Promise | Value) export class CreatedAction< Manifest extends T.Manifest, Store, ConfigType extends | Record | Config | Config, Type extends Record = ExtractConfigType, > { private constructor( public readonly id: string, public readonly myMetadata: MaybeFn< Manifest, Store, Omit >, readonly fn: (options: { effects: Effects input: Type }) => Promise, readonly input: Config, public validator = input.validator, ) {} static of< Manifest extends T.Manifest, Store, ConfigType extends | Record | Config | Config, Type extends Record = ExtractConfigType, >( id: string, metadata: MaybeFn>, fn: (options: { effects: Effects; input: Type }) => Promise, inputConfig: Config | Config, ) { return new CreatedAction( id, metadata, fn, inputConfig as Config, ) } exportedAction: ExportedAction = ({ effects, input }) => { return this.fn({ effects, input: this.validator.unsafeCast(input), }) } run = async ({ effects, input }: { effects: Effects; input?: Type }) => { return this.fn({ effects, input: this.validator.unsafeCast(input), }) } async metadata(options: { effects: Effects }) { if (this.myMetadata instanceof Function) return await this.myMetadata(options) return this.myMetadata } async ActionMetadata(options: { effects: Effects }): Promise { return { ...(await this.metadata(options)), input: await this.input.build(options), } } async getConfig({ effects }: { effects: Effects }) { return this.input.build({ effects, }) } } export const createAction = CreatedAction.of