From a917709371a2d32d89811695a9f2f2b86113410d Mon Sep 17 00:00:00 2001 From: David Khourshid Date: Thu, 12 Sep 2024 00:32:12 -0400 Subject: [PATCH 1/2] POC --- packages/core/src/invoke.ts | 160 ++++++++++++++++++++++++++++++ packages/core/src/types.ts | 20 +++- packages/core/test/invoke.test.ts | 25 +++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/invoke.ts diff --git a/packages/core/src/invoke.ts b/packages/core/src/invoke.ts new file mode 100644 index 0000000000..301d9ead7f --- /dev/null +++ b/packages/core/src/invoke.ts @@ -0,0 +1,160 @@ +import { + ActorLogic, + AnyActorLogic, + DoneActorEvent, + DoNotInfer, + ErrorActorEvent, + EventObject, + InputFrom, + MachineContext, + Mapper, + MetaObject, + NonReducibleUnknown, + OutputFrom, + ParameterizedObject, + ProvidedActor, + SingleOrArray, + SnapshotEvent, + SnapshotFrom, + TransitionConfigOrTarget +} from './types'; + +export type InvokeObject< + TContext extends MachineContext, + TEvent extends EventObject, + TActor extends ProvidedActor, + TAction extends ParameterizedObject, + TGuard extends ParameterizedObject, + TDelay extends string, + TEmitted extends EventObject, + TMeta extends MetaObject +> = { + (context: TContext): void; + id?: string; + systemId?: string; + src: AnyActorLogic; + input?: + | Mapper + | NonReducibleUnknown; + onDone?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + DoneActorEvent, // TODO: consider replacing with `unknown` + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + onError?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + ErrorActorEvent, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + + onSnapshot?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + SnapshotEvent, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; +}; + +export function createInvoke< + TContext extends MachineContext, + TEvent extends EventObject, + TActor extends ProvidedActor, + TAction extends ParameterizedObject, + TGuard extends ParameterizedObject, + TDelay extends string, + TEmitted extends EventObject, + TMeta extends MetaObject, + // Logic-specific types + TSrc extends AnyActorLogic +>(_config: { + id?: string; + systemId?: string; + src: TSrc; + input?: Mapper, TEvent> | InputFrom; + onDone?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + DoneActorEvent>, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + onError?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + ErrorActorEvent, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + + onSnapshot?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + SnapshotFrom, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; +}): InvokeObject< + TContext, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta +> { + return null!; +} diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index c84c91281d..8e903aa559 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -8,6 +8,7 @@ import type { Actor, ProcessingStatus } from './createActor.ts'; import { Spawner } from './spawn.ts'; import { AnyActorSystem, Clock } from './system.js'; import { InspectionEvent } from './inspection.ts'; +import { InvokeObject } from './invoke.ts'; export type Identity = { [K in keyof T]: T[K] }; @@ -901,7 +902,23 @@ export interface StateNodeConfig< * be stopped upon exiting this state node. */ invoke?: SingleOrArray< - InvokeConfig< + | InvokeConfig< + TContext, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + | { + id?: string; + } + >; + + invoke2?: SingleOrArray< + InvokeObject< TContext, TEvent, TActor, @@ -912,6 +929,7 @@ export interface StateNodeConfig< TMeta > >; + /** The mapping of event types to their potential transition(s). */ on?: TransitionsConfig< TContext, diff --git a/packages/core/test/invoke.test.ts b/packages/core/test/invoke.test.ts index 344b67cfe2..db613a13fc 100644 --- a/packages/core/test/invoke.test.ts +++ b/packages/core/test/invoke.test.ts @@ -24,6 +24,7 @@ import { AnyEventObject } from '../src/index.ts'; import { sleep } from '@xstate-repo/jest-utils'; +import { createInvoke } from '../src/invoke.ts'; const user = { name: 'David' }; @@ -3437,3 +3438,27 @@ describe('invoke input', () => { createActor(machine).start(); }); }); + +const machine = createMachine({ + context: { number: 42 }, + invoke2: createInvoke({ + id: 'double', + input: ({ context }) => ({ + count: context.number + }), + src: fromPromise(async ({ input }: { input: { count: number } }) => { + return input.count * 2; + }), + onDone: { + actions: ({ context, event }) => { + context.number satisfies number; + // @ts-expect-error + context.number satisfies string; + + event.output satisfies number; + // @ts-expect-error + event.output satisfies string; + } + } + }) +}); From 8f60e2e22c3c8dc037e69be52acd7bfdb3996d8a Mon Sep 17 00:00:00 2001 From: David Khourshid Date: Fri, 20 Sep 2024 12:15:02 +0200 Subject: [PATCH 2/2] Formatting --- packages/core/src/types.ts | 700 +++++++++++++++++++------------------ 1 file changed, 354 insertions(+), 346 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 8e903aa559..cffce11607 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -62,11 +62,12 @@ export type IndexByProp, P extends keyof T> = { export type IndexByType = IndexByProp; -export type Equals = (() => A extends A2 - ? true - : false) extends () => A extends A1 ? true : false - ? true - : false; +export type Equals = + (() => A extends A2 ? true : false) extends () => A extends A1 + ? true + : false + ? true + : false; export type IsAny = Equals; export type Cast = A extends B ? A : B; // @TODO: Replace with native `NoInfer` when TS issue gets fixed: @@ -128,44 +129,46 @@ export interface ActionArgs< TEvent extends EventObject > extends UnifiedArg {} -export type InputFrom = T extends StateMachine< - infer _TContext, - infer _TEvent, - infer _TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, - infer _TStateValue, - infer _TTag, - infer TInput, - infer _TOutput, - infer _TEmitted, - infer _TMeta, - infer _TStateSchema -> - ? TInput - : T extends ActorLogic< - infer _TSnapshot, - infer _TEvent, - infer TInput, - infer _TSystem, - infer _TEmitted - > +export type InputFrom = + T extends StateMachine< + infer _TContext, + infer _TEvent, + infer _TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer _TStateValue, + infer _TTag, + infer TInput, + infer _TOutput, + infer _TEmitted, + infer _TMeta, + infer _TStateSchema + > ? TInput - : never; + : T extends ActorLogic< + infer _TSnapshot, + infer _TEvent, + infer TInput, + infer _TSystem, + infer _TEmitted + > + ? TInput + : never; -export type OutputFrom = T extends ActorLogic< - infer TSnapshot, - infer _TEvent, - infer _TInput, - infer _TSystem, - infer _TEmitted -> - ? (TSnapshot & { status: 'done' })['output'] - : T extends ActorRef +export type OutputFrom = + T extends ActorLogic< + infer TSnapshot, + infer _TEvent, + infer _TInput, + infer _TSystem, + infer _TEmitted + > ? (TSnapshot & { status: 'done' })['output'] - : never; + : T extends ActorRef + ? (TSnapshot & { status: 'done' })['output'] + : never; export type ActionFunction< TContext extends MachineContext, @@ -754,87 +757,88 @@ export type InvokeConfig< TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject -> = IsLiteralString extends true - ? DistributeActors< - TContext, - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TEmitted, - TMeta, - TActor - > - : { - /** - * The unique identifier for the invoked machine. If not specified, this - * will be the machine's own `id`, or the URL (from `src`). - */ - id?: string; - - systemId?: string; - /** The source of the machine to be invoked, or the machine itself. */ - src: AnyActorLogic | string; // TODO: fix types - - input?: - | Mapper - | NonReducibleUnknown; - /** - * The transition to take upon the invoked child machine reaching its - * final top-level state. - */ - onDone?: - | string - | SingleOrArray< - TransitionConfigOrTarget< - TContext, - DoneActorEvent, // TODO: consider replacing with `unknown` - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TEmitted, - TMeta - > - >; - /** - * The transition to take upon the invoked child machine sending an error - * event. - */ - onError?: - | string - | SingleOrArray< - TransitionConfigOrTarget< - TContext, - ErrorActorEvent, - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TEmitted, - TMeta - > - >; +> = + IsLiteralString extends true + ? DistributeActors< + TContext, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta, + TActor + > + : { + /** + * The unique identifier for the invoked machine. If not specified, this + * will be the machine's own `id`, or the URL (from `src`). + */ + id?: string; - onSnapshot?: - | string - | SingleOrArray< - TransitionConfigOrTarget< - TContext, - SnapshotEvent, - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TEmitted, - TMeta - > - >; - }; + systemId?: string; + /** The source of the machine to be invoked, or the machine itself. */ + src: AnyActorLogic | string; // TODO: fix types + + input?: + | Mapper + | NonReducibleUnknown; + /** + * The transition to take upon the invoked child machine reaching its + * final top-level state. + */ + onDone?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + DoneActorEvent, // TODO: consider replacing with `unknown` + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + /** + * The transition to take upon the invoked child machine sending an + * error event. + */ + onError?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + ErrorActorEvent, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + + onSnapshot?: + | string + | SingleOrArray< + TransitionConfigOrTarget< + TContext, + SnapshotEvent, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > + >; + }; export type AnyInvokeConfig = InvokeConfig< any, @@ -902,19 +906,16 @@ export interface StateNodeConfig< * be stopped upon exiting this state node. */ invoke?: SingleOrArray< - | InvokeConfig< - TContext, - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TEmitted, - TMeta - > - | { - id?: string; - } + InvokeConfig< + TContext, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TEmitted, + TMeta + > >; invoke2?: SingleOrArray< @@ -2006,73 +2007,75 @@ export type ActorRefLike = Pick< export type UnknownActorRef = ActorRef, EventObject>; -export type ActorLogicFrom = ReturnTypeOrValue extends infer R - ? R extends StateMachine< - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, // TMeta - any // TStateSchema - > - ? R - : R extends Promise - ? PromiseActorLogic - : never - : never; +export type ActorLogicFrom = + ReturnTypeOrValue extends infer R + ? R extends StateMachine< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, // TMeta + any // TStateSchema + > + ? R + : R extends Promise + ? PromiseActorLogic + : never + : never; // TODO: in v6, this should only accept AnyActorLogic, like ActorRefFromLogic -export type ActorRefFrom = ReturnTypeOrValue extends infer R - ? R extends StateMachine< - infer TContext, - infer TEvent, - infer TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, - infer TStateValue, - infer TTag, - infer _TInput, - infer TOutput, - infer TEmitted, - infer TMeta, - infer TStateSchema - > - ? ActorRef< - MachineSnapshot< - TContext, - TEvent, - TChildren, - TStateValue, - TTag, - TOutput, - TMeta, - TStateSchema - >, - TEvent, - TEmitted +export type ActorRefFrom = + ReturnTypeOrValue extends infer R + ? R extends StateMachine< + infer TContext, + infer TEvent, + infer TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer TStateValue, + infer TTag, + infer _TInput, + infer TOutput, + infer TEmitted, + infer TMeta, + infer TStateSchema > - : R extends Promise - ? ActorRefFrom> - : R extends ActorLogic< - infer TSnapshot, - infer TEvent, - infer _TInput, - infer _TSystem, - infer TEmitted - > - ? ActorRef - : never - : never; + ? ActorRef< + MachineSnapshot< + TContext, + TEvent, + TChildren, + TStateValue, + TTag, + TOutput, + TMeta, + TStateSchema + >, + TEvent, + TEmitted + > + : R extends Promise + ? ActorRefFrom> + : R extends ActorLogic< + infer TSnapshot, + infer TEvent, + infer _TInput, + infer _TSystem, + infer TEmitted + > + ? ActorRef + : never + : never; export type ActorRefFromLogic = ActorRef< SnapshotFrom, @@ -2085,73 +2088,75 @@ export type DevToolsAdapter = (service: AnyActor) => void; /** @deprecated Use `Actor` instead. */ export type InterpreterFrom< T extends AnyStateMachine | ((...args: any[]) => AnyStateMachine) -> = ReturnTypeOrValue extends StateMachine< - infer TContext, - infer TEvent, - infer TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, - infer TStateValue, - infer TTag, - infer TInput, - infer TOutput, - infer TEmitted, - infer TMeta, - infer TStateSchema -> - ? Actor< - ActorLogic< - MachineSnapshot< - TContext, +> = + ReturnTypeOrValue extends StateMachine< + infer TContext, + infer TEvent, + infer TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer TStateValue, + infer TTag, + infer TInput, + infer TOutput, + infer TEmitted, + infer TMeta, + infer TStateSchema + > + ? Actor< + ActorLogic< + MachineSnapshot< + TContext, + TEvent, + TChildren, + TStateValue, + TTag, + TOutput, + TMeta, + TStateSchema + >, TEvent, - TChildren, - TStateValue, - TTag, - TOutput, - TMeta, - TStateSchema - >, - TEvent, - TInput, - AnyActorSystem, - TEmitted + TInput, + AnyActorSystem, + TEmitted + > > - > - : never; + : never; export type MachineImplementationsFrom< T extends AnyStateMachine | ((...args: any[]) => AnyStateMachine) -> = ReturnTypeOrValue extends StateMachine< - infer TContext, - infer TEvent, - infer _TChildren, - infer TActor, - infer TAction, - infer TGuard, - infer TDelay, - infer _TStateValue, - infer TTag, - infer _TInput, - infer _TOutput, - infer TEmitted, - infer _TMeta, - infer _TStateSchema -> - ? InternalMachineImplementations< - ResolvedStateMachineTypes< - TContext, - TEvent, - TActor, - TAction, - TGuard, - TDelay, - TTag, - TEmitted +> = + ReturnTypeOrValue extends StateMachine< + infer TContext, + infer TEvent, + infer _TChildren, + infer TActor, + infer TAction, + infer TGuard, + infer TDelay, + infer _TStateValue, + infer TTag, + infer _TInput, + infer _TOutput, + infer TEmitted, + infer _TMeta, + infer _TStateSchema + > + ? InternalMachineImplementations< + ResolvedStateMachineTypes< + TContext, + TEvent, + TActor, + TAction, + TGuard, + TDelay, + TTag, + TEmitted + > > - > - : never; + : never; export interface ActorScope< TSnapshot extends Snapshot, @@ -2294,28 +2299,29 @@ export type UnknownActorLogic = ActorLogic< any // emitted >; -export type SnapshotFrom = ReturnTypeOrValue extends infer R - ? R extends ActorRef - ? TSnapshot - : R extends Actor - ? SnapshotFrom - : R extends ActorLogic< - infer _TSnapshot, - infer _TEvent, - infer _TInput, - infer _TEmitted, - infer _TSystem - > - ? ReturnType - : R extends ActorScope< - infer TSnapshot, +export type SnapshotFrom = + ReturnTypeOrValue extends infer R + ? R extends ActorRef + ? TSnapshot + : R extends Actor + ? SnapshotFrom + : R extends ActorLogic< + infer _TSnapshot, infer _TEvent, + infer _TInput, infer _TEmitted, infer _TSystem > - ? TSnapshot - : never - : never; + ? ReturnType + : R extends ActorScope< + infer TSnapshot, + infer _TEvent, + infer _TEmitted, + infer _TSystem + > + ? TSnapshot + : never + : never; export type EventFromLogic = TLogic extends ActorLogic< @@ -2339,39 +2345,40 @@ export type EmittedFrom = ? TEmitted : never; -type ResolveEventType = ReturnTypeOrValue extends infer R - ? R extends StateMachine< - infer _TContext, - infer TEvent, - infer _TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, - infer _TStateValue, - infer _TTag, - infer _TInput, - infer _TOutput, - infer _TEmitted, - infer _TMeta, - infer _TStateSchema - > - ? TEvent - : R extends MachineSnapshot< - infer _TContext, - infer TEvent, - infer _TChildren, - infer _TStateValue, - infer _TTag, - infer _TOutput, - infer _TMeta, - infer _TStateSchema - > +type ResolveEventType = + ReturnTypeOrValue extends infer R + ? R extends StateMachine< + infer _TContext, + infer TEvent, + infer _TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer _TStateValue, + infer _TTag, + infer _TInput, + infer _TOutput, + infer _TEmitted, + infer _TMeta, + infer _TStateSchema + > ? TEvent - : R extends ActorRef + : R extends MachineSnapshot< + infer _TContext, + infer TEvent, + infer _TChildren, + infer _TStateValue, + infer _TTag, + infer _TOutput, + infer _TMeta, + infer _TStateSchema + > ? TEvent - : never - : never; + : R extends ActorRef + ? TEvent + : never + : never; export type EventFrom< T, @@ -2379,56 +2386,57 @@ export type EventFrom< TEvent extends EventObject = ResolveEventType > = IsNever extends true ? TEvent : ExtractEvent; -export type ContextFrom = ReturnTypeOrValue extends infer R - ? R extends StateMachine< - infer TContext, - infer _TEvent, - infer _TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, - infer _TStateValue, - infer _TTag, - infer _TInput, - infer _TOutput, - infer _TEmitted, - infer _TMeta, - infer _TStateSchema - > - ? TContext - : R extends MachineSnapshot< - infer TContext, - infer _TEvent, - infer _TChildren, - infer _TStateValue, - infer _TTag, - infer _TOutput, - infer _TMeta, - infer _TStateSchema - > +export type ContextFrom = + ReturnTypeOrValue extends infer R + ? R extends StateMachine< + infer TContext, + infer _TEvent, + infer _TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer _TStateValue, + infer _TTag, + infer _TInput, + infer _TOutput, + infer _TEmitted, + infer _TMeta, + infer _TStateSchema + > ? TContext - : R extends Actor - ? TActorLogic extends StateMachine< + : R extends MachineSnapshot< infer TContext, infer _TEvent, infer _TChildren, - infer _TActor, - infer _TAction, - infer _TGuard, - infer _TDelay, infer _TStateValue, infer _TTag, - infer _TInput, infer _TOutput, - infer _TEmitted, infer _TMeta, infer _TStateSchema > - ? TContext + ? TContext + : R extends Actor + ? TActorLogic extends StateMachine< + infer TContext, + infer _TEvent, + infer _TChildren, + infer _TActor, + infer _TAction, + infer _TGuard, + infer _TDelay, + infer _TStateValue, + infer _TTag, + infer _TInput, + infer _TOutput, + infer _TEmitted, + infer _TMeta, + infer _TStateSchema + > + ? TContext + : never : never - : never - : never; + : never; export type InferEvent = { [T in E['type']]: { type: T } & Extract;