diff --git a/.changeset/typed-planner-transitions.md b/.changeset/typed-planner-transitions.md new file mode 100644 index 0000000..e641568 --- /dev/null +++ b/.changeset/typed-planner-transitions.md @@ -0,0 +1,5 @@ +--- +"@typeonce/effect-machine": patch +--- + +Internal: check planner target resolution, invocation sources, and runtime child operations at compile time instead of through `any` casts. Machine behavior and the public API are unchanged. diff --git a/packages/effect-machine/src/internal/machine/configuration.ts b/packages/effect-machine/src/internal/machine/configuration.ts index 3f6da38..d77d706 100644 --- a/packages/effect-machine/src/internal/machine/configuration.ts +++ b/packages/effect-machine/src/internal/machine/configuration.ts @@ -577,9 +577,9 @@ export const normalizeConfiguration = ): ActiveConfiguration => configurationFromSnapshot(machine, state) -export const normalizeConfigurationSync = ( +export const normalizeConfigurationSync = ( machine: Machine.Any, - state: Machine.Snapshot + state: Machine.AtomicSnapshot ): ActiveConfiguration => { try { return configurationFromSnapshot(machine, state) @@ -1095,10 +1095,11 @@ const configurationFromTargetSnapshotSync = ( } } -export const normalizeTargetConfigurationSync = ( +/** Applies a transition target, failing for anything other than a target builder result or snapshot. */ +export const normalizeTargetConfigurationSync = ( machine: Machine.Any, current: ActiveConfiguration, - target: Machine.Snapshot | Machine.Target> + target: unknown ): ActiveConfiguration => { if (isTarget(target)) { const snapshot = target[TargetSnapshotTypeId] diff --git a/packages/effect-machine/src/internal/machine/invocation.ts b/packages/effect-machine/src/internal/machine/invocation.ts index b9cea39..19ca664 100644 --- a/packages/effect-machine/src/internal/machine/invocation.ts +++ b/packages/effect-machine/src/internal/machine/invocation.ts @@ -7,7 +7,7 @@ import * as Cause from "effect/Cause" import * as Effect from "effect/Effect" import * as Stream from "effect/Stream" -import type { ChildMachine, ChildOwner, Inspection, Logic, Machine } from "../../Machine.js" +import type { ChildMachine, ChildOwner, Inspection, Machine } from "../../Machine.js" import * as ChildRegistry from "./childRegistry.js" import * as Configuration from "./configuration.js" import { ChildAlreadyExistsError, InfiniteTransitionError, MachineSchemaDecodeError, StoppedError } from "./errors.js" @@ -37,7 +37,9 @@ export const makeKey = (path: string, id: string): string => `${path.length}:${p export const makeChildId = (path: string, id: string): string => `${ChildRegistry.invocationChildIdPrefix}${makeKey(path, id)}` -const oneShot = (effect: Effect.Effect): Logic => ({ +const oneShot = ( + effect: Effect.Effect +): Runtime.ProcessLogic => ({ initial: () => Effect.void, run: () => effect }) @@ -46,7 +48,7 @@ const streamLogic = ( stream: Stream.Stream, path: string, id: string -): Runtime.ProcessLogic => ({ +): Runtime.ProcessLogic => ({ initial: () => Effect.void, run: ({ parent }) => { const send = parent?.[Runtime.acknowledgedSend] @@ -68,9 +70,10 @@ const resolveValue = (value: unknown, context: Omit): ChildOwner => ({ - spawn: - ((descriptor: ChildMachine.Any, options?: { readonly input?: unknown }) => - (scope.spawn as any)(descriptor, options)) as ChildOwner["spawn"], + spawn: ( + child: Child & ChildMachine.Executable & ChildMachine.ParentCompatibility, + ...options: ChildMachine.SpawnArgs + ) => scope.spawn(child, ...options), sendTo: ((descriptor: ChildMachine.Any, event: unknown) => scope.sendTo(descriptor, event)) as ChildOwner< any >["sendTo"], @@ -86,15 +89,7 @@ const resolveOne = ( return { id: String(raw.id), sourceName: raw.sourceName, - src: () => - oneShot(raw.effect(context) as Effect.Effect) as unknown as Runtime.ProcessLogic< - any, - any, - any, - any, - any, - any - >, + src: () => oneShot(raw.effect(context)), onDone: raw.onDone, onFailure: raw.onFailure, onSnapshot: raw.onSnapshot, @@ -105,15 +100,7 @@ const resolveOne = ( return { id: String(raw.id), sourceName: raw.sourceName, - src: () => - oneShot(Effect.sleep(resolveValue(raw.after, context) as any)) as unknown as Runtime.ProcessLogic< - any, - any, - any, - any, - any, - any - >, + src: () => oneShot(Effect.sleep(typeof raw.after === "function" ? raw.after(context) : raw.after)), onDone: raw.onDone, activityKind: "Timer" } @@ -123,8 +110,7 @@ const resolveOne = ( return { id, sourceName: raw.sourceName, - src: () => - streamLogic(raw.stream(context), path, id) as unknown as Runtime.ProcessLogic, + src: () => streamLogic(raw.stream(context), path, id), onDone: raw.onDone, onFailure: raw.onFailure, activityKind: "Stream" diff --git a/packages/effect-machine/src/internal/machine/machine.ts b/packages/effect-machine/src/internal/machine/machine.ts index b6a6d73..6f5f833 100644 --- a/packages/effect-machine/src/internal/machine/machine.ts +++ b/packages/effect-machine/src/internal/machine/machine.ts @@ -4,7 +4,6 @@ import * as Option from "effect/Option" import { Prototype as PipeablePrototype } from "effect/Pipeable" import { hasProperty } from "effect/Predicate" import * as Schema from "effect/Schema" -import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import type { ChildAddress, @@ -26,7 +25,7 @@ import * as Activities from "./activities.js" import * as Configuration from "./configuration.js" import * as Construction from "./construction.js" import * as Declaration from "./declaration.js" -import type { ChildAlreadyExistsError, PlanningError, StartupError } from "./errors.js" +import type { PlanningError, StartupError } from "./errors.js" import type { CapturedStateConfig } from "./implementation.js" import * as InitialDeclaration from "./initialDeclaration.js" import * as InvocationDefinition from "./invocationDefinition.js" @@ -59,18 +58,6 @@ export const InvokeTypeId: unique symbol = Symbol.for("effect/Machine/Invoke") const ChildMachineTypeId = "~effect/Machine/ChildMachine" type MachineRuntimeRequirement = internalRuntime.MachineRuntime -type SpawnRequirements = Exclude -type SpawnIdError = "id" extends keyof Options ? Options extends { - readonly id?: infer Id - } ? [Id] extends [undefined] ? never : ChildAlreadyExistsError - : ChildAlreadyExistsError - : never -type SpawnError = SpawnIdError -type SpawnResult = Effect.Effect< - MachineRef, - SpawnError | InitialError, - MachineRuntimeRequirement | SpawnRequirements -> const Proto = { ...Inspectable.BaseProto, ...PipeablePrototype, @@ -829,7 +816,7 @@ const makeStateHelpers = (): Machine.StateAccessors<{ readonly "": Machine.State Option.map((snapshot) => ({ value: snapshot.value, parents })) ) }) as Machine.StateAccessors<{ readonly "": Machine.StateNodeConfig }>["getWithParents"], - getSnapshot: Topology.getSnapshotByPath as unknown as Machine.StateAccessors< + getSnapshot: Topology.getSnapshotByPath as Machine.StateAccessors< { readonly "": Machine.StateNodeConfig } >["getSnapshot"], matches: @@ -965,6 +952,8 @@ export const planInitial: ( ...args: ReadonlyArray ) => Effect.Effect = internalPlanner.planInitial +// Erased boundary: compiled nodes are stored with string paths; the generic +// machine type is the only source of their literal identifiers. export const stateNodes = ( machine: M ): ReadonlyArray< @@ -1122,73 +1111,31 @@ export const childFamily = (machine: M): ChildMachine.Fam export const childAddress = (id: string): ChildAddress => id as ChildAddress -export const spawn: { - ( - logic: Logic< - ChildState, - ChildEvent, - ChildError, - ChildRequirements, - ChildOutput, - ChildInitialError - > - ): SpawnResult - < - ChildState, - ChildEvent, - ChildError, - ChildRequirements, - ChildOutput, - Options extends SpawnOptions, - ChildInitialError = never - >( - logic: Logic< - ChildState, - ChildEvent, - ChildError, - ChildRequirements, - ChildOutput, - ChildInitialError - >, - options: Options & ChildAddress.OptionsCompatibility - ): SpawnResult< - ChildState, - ChildEvent, - ChildError, - ChildRequirements, - ChildOutput, - SpawnError, - ChildInitialError - > -} = ((logic: Logic, options?: SpawnOptions) => +// The public `Machine` module declares the typed overloads and checks these +// erased implementations against them structurally. +export const spawn = (logic: Logic, options?: SpawnOptions) => Effect.flatMap( internalRuntime.MachineRuntime, - (runtime) => options === undefined ? runtime.spawn(logic) : (runtime.spawn as any)(logic, options) - )) as any - -export const sendTo: { - ( - child: Child, - event: ChildMachine.Event - ): Effect.Effect -
>( - id: Address, - event: ChildAddress.Event
- ): Effect.Effect -} = ((child: string | ChildMachine.Any, event: unknown) => + // `SpawnOptions` declares only `id`; an absent id spawns an anonymous child. + (runtime) => options?.id === undefined ? runtime.spawn(logic) : runtime.spawn(logic, { id: options.id }) + ) + +export const sendTo = ( + child: string | ChildMachine.Any, + event: unknown +): Effect.Effect => Effect.flatMap( internalRuntime.MachineRuntime, (runtime) => runtime.sendTo(child, event) - )) as any + ) -export const stopChild: { - (child: ChildAddress): Effect.Effect - (child: Child): Effect.Effect -} = ((child: string | ChildMachine.Any) => +export const stopChild = ( + child: string | ChildMachine.Any +): Effect.Effect => Effect.flatMap( internalRuntime.MachineRuntime, (runtime) => runtime.stopChild(child) - )) as any + ) export const watch = ( ref: MachineRef diff --git a/packages/effect-machine/src/internal/machine/planner.ts b/packages/effect-machine/src/internal/machine/planner.ts index 6bf0636..c51627b 100644 --- a/packages/effect-machine/src/internal/machine/planner.ts +++ b/packages/effect-machine/src/internal/machine/planner.ts @@ -48,6 +48,7 @@ import { decodeEventSync, decodeInputSync, decodeStateValueSync } from "./protoc import { InitialEventTypeId } from "./symbols.js" import { getNode, + type HistoryTarget, type InitialTarget as InitialTargetInstruction, isChoiceTarget, isCombinedTarget, @@ -59,6 +60,7 @@ import { isStateUpdate, isTarget, makeChoiceTarget, + makeResolvedTarget, makeStateInput, makeTarget, TargetSnapshotTypeId @@ -313,7 +315,7 @@ const completeHistoryConfiguration = ( next = normalizeTargetConfigurationSync( machine, next, - (resolved?.target ?? routed) as Machine.Snapshot | Machine.Target + resolved?.target ?? routed ) if (resolved !== undefined) { commands.push(...resolved.commands) @@ -460,7 +462,7 @@ export function resolveInitialConfiguration( partial = normalizeTargetConfigurationSync( machine, partial, - (resolved?.target ?? routed) as Machine.Target + resolved?.target ?? routed ) if (resolved !== undefined) { commands.push(...resolved.commands) @@ -494,10 +496,7 @@ export function resolveInitialTarget( const completed = resolveInitialConfiguration(machine, configuration, target, event) const snapshot = snapshotFromConfigurationAtPath(machine, completed.configuration, target.path) return { - target: makeTarget(target.path as any, snapshot.value as any, { - snapshot: snapshot as any, - values: target.values as any - }), + target: makeResolvedTarget(target.path, snapshot.value, { snapshot, values: target.values }), commands: completed.commands, raisedEvents: completed.raisedEvents, emittedEvents: completed.emittedEvents, @@ -526,10 +525,7 @@ function resolveHistoryTarget( const values = Object.fromEntries(completed.configuration.values) if (target.parent !== "" && configuration.active.has("")) delete values[""] return { - target: makeTarget(target.parent as any, snapshot.value as any, { - snapshot: snapshot as any, - values: values as any - }), + target: makeResolvedTarget(target.parent, snapshot.value, { snapshot, values }), commands: completed.commands, raisedEvents: completed.raisedEvents, emittedEvents: completed.emittedEvents, @@ -565,20 +561,18 @@ function resolveHistoryTarget( event ) let fallbackConfiguration = choiceResolution === undefined - ? normalizeConfigurationSync(machine, collected.state as any) + ? normalizeConfigurationSync(machine, collected.state) : normalizeTargetConfigurationSync(machine, { active: new Set(), values: new Map(), outputs: new Map(), history: configuration.history - }, choiceResolution.target as any) + }, choiceResolution.target) for (const additionalTarget of choiceResolution?.additionalTargets ?? []) { fallbackConfiguration = normalizeTargetConfigurationSync( machine, fallbackConfiguration, - additionalTarget as - | Machine.Snapshot - | Machine.Target + additionalTarget ) } if (!fallbackConfiguration.active.has(target.parent)) { @@ -590,10 +584,7 @@ function resolveHistoryTarget( const values = Object.fromEntries(fallbackConfiguration.values) if (target.parent !== "" && configuration.active.has("")) delete values[""] return { - target: makeTarget(target.parent as any, snapshot.value as any, { - snapshot: snapshot as any, - values: values as any - }), + target: makeResolvedTarget(target.parent, snapshot.value, { snapshot, values }), commands: [...collected.commands, ...(choiceResolution?.commands ?? [])], raisedEvents: [...collected.raisedEvents, ...(choiceResolution?.raisedEvents ?? [])], emittedEvents: [...collected.emittedEvents, ...(choiceResolution?.emittedEvents ?? [])], @@ -885,12 +876,7 @@ const selectAlwaysTransitions = < sourcePath: path, leafPath: leaf, trigger: { type: "always" }, - transition: always as unknown as MicrostepTransition< - States, - E, - R, - ConstructionContext>> - >, + transition: always, context: { ...resolveMachineReferences(machine, configuration), state: configuration.values.get(path) as Machine.StateByIdentifier< @@ -961,12 +947,7 @@ const selectDoneTransitions = < sourcePath: completion.path, leafPath: getActiveLeafPathFrom(machine, configuration, completion.path), trigger: { type: "done" }, - transition: onDone as unknown as MicrostepTransition< - States, - E, - R, - ConstructionContext>> - >, + transition: onDone, context: makeDoneContext>( machine, configuration, @@ -1042,29 +1023,14 @@ const selectEventTransitions = < sourcePath: path, leafPath: leaf, trigger: { type: "event", event: event._tag }, - transition: transition as unknown as MicrostepTransition< - States, - E, - R, - ConstructionContext< - Machine.HandlerContext< - States, - Events, - Emits, - Machine.StateIdentifier, - Machine.TagOf, - E, - R - > - > - >, + transition, context: makeTransitionContext< States, Events, Emits, Machine.StateIdentifier, Machine.TagOf - >(machine as any, configuration, path, event, capturedSnapshot()) + >(machine, configuration, path, event, capturedSnapshot()) }) evaluatedSources.set(path, candidate) } @@ -1127,19 +1093,14 @@ const selectInvocationTransition = < sourcePath: event.path, leafPath: getActiveLeafPathFrom(machine, configuration, event.path), trigger: { type: "invoke", id: event.id, outcome: event.type }, - transition: transition as unknown as MicrostepTransition, + transition, context }) return candidate === undefined ? [] : [candidate] } -export const getTargetNodePath = ( - target: - | Machine.Snapshot - | Machine.Target> - | Machine.HistoryTarget> - | Machine.ChoiceTarget> -): string => { +/** Reads the state path addressed by a transition result, failing for any other value. */ +export const getTargetNodePath = (target: unknown): string => { if (isHistoryTarget(target) || isChoiceTarget(target)) { return String(target.path) } @@ -1304,6 +1265,12 @@ interface ResolvedChoiceTransition { readonly updates: ReadonlyArray } +/** A target resolved to concrete state paths, before configuration normalization. */ +type ResolvedTarget = Machine.Target | Machine.AtomicSnapshot + +/** A route selected by choice resolution; initial and history routes are resolved by the caller. */ +type ChoiceRoute = ResolvedTarget | HistoryTarget | InitialTargetInstruction + function resolveChoiceTarget( machine: Machine.Any, configuration: ActiveConfiguration, @@ -1311,7 +1278,7 @@ function resolveChoiceTarget( event: unknown ) { const pending: Array = [initialTarget] - const resolvedTargets: Array = [] + const resolvedTargets: Array = [] const commands: Array = [] const raisedEvents: Array = [] const emittedEvents: Array = [] @@ -1373,7 +1340,7 @@ function resolveChoiceTarget( throw new Error(`Machine choice resolver for "${node.path}" must return a target`) } validateDeclaredTransitionTarget(node.path, { type: "choice" }, choice.targets, collected.state) - const returnedPath = getTargetNodePath(collected.state as any) + const returnedPath = getTargetNodePath(collected.state) current = withChoiceValues(collected.state, extracted.values) const nested = choiceFromTarget(current) transitions.push({ @@ -1412,7 +1379,7 @@ const collectEvaluatedTransition = < Event, E, R, - Context + Context extends { readonly event?: unknown } >( machine: Machine.Any, state: ActiveConfiguration, @@ -1471,11 +1438,11 @@ const collectEvaluatedTransition = < machine, constructionState, unresolvedTarget, - (selection.context as any).event + selection.context.event ) const choiceResolvedTarget = choiceResolution?.target ?? unresolvedTarget const initialResolution = choiceResolvedTarget !== undefined && isInitialTarget(choiceResolvedTarget) - ? resolveInitialTarget(machine, constructionState, choiceResolvedTarget, (selection.context as any).event) + ? resolveInitialTarget(machine, constructionState, choiceResolvedTarget, selection.context.event) : undefined const routedTarget = initialResolution?.target ?? choiceResolvedTarget let historyResolution: { @@ -1509,7 +1476,7 @@ const collectEvaluatedTransition = < machine, stateAtHistoryResolution, routedTarget, - (selection.context as any).event + selection.context.event ) } const target: Machine.Snapshot | Machine.Target> | undefined = @@ -1525,18 +1492,16 @@ const collectEvaluatedTransition = < const additionalTargetRaisedEvents: Array = [] const additionalTargetEmittedEvents: Array = [] const additionalTargetChoiceTransitions: Array = [] - const additionalChoiceTargets: Array< - Machine.Snapshot | Machine.Target> - > = [] + const additionalChoiceTargets: Array = [] for (const additionalTarget of choiceResolution?.additionalTargets ?? []) { if (isInitialTarget(additionalTarget)) { const resolved = resolveInitialTarget( machine, state, additionalTarget, - (selection.context as any).event + selection.context.event ) - additionalChoiceTargets.push(resolved.target as any) + additionalChoiceTargets.push(resolved.target) additionalTargetActions.push(...resolved.commands) additionalTargetRaisedEvents.push(...resolved.raisedEvents) additionalTargetEmittedEvents.push(...resolved.emittedEvents) @@ -1544,16 +1509,16 @@ const collectEvaluatedTransition = < continue } if (!isHistoryTarget(additionalTarget)) { - additionalChoiceTargets.push(additionalTarget as any) + additionalChoiceTargets.push(additionalTarget) continue } const resolved = resolveHistoryTarget( machine, state, additionalTarget, - (selection.context as any).event + selection.context.event ) - additionalChoiceTargets.push(resolved.target as any) + additionalChoiceTargets.push(resolved.target) additionalTargetActions.push(...resolved.commands) additionalTargetRaisedEvents.push(...resolved.raisedEvents) additionalTargetEmittedEvents.push(...resolved.emittedEvents) @@ -1569,9 +1534,9 @@ const collectEvaluatedTransition = < ...state, values: new Map(state.values).set(update.path, update.value) } - : normalizeTargetConfigurationSync(machine, state, target) + : normalizeTargetConfigurationSync(machine, state, target) for (const additionalTarget of additionalChoiceTargets) { - stateAfterTransition = normalizeTargetConfigurationSync( + stateAfterTransition = normalizeTargetConfigurationSync( machine, stateAfterTransition, additionalTarget @@ -1838,7 +1803,7 @@ const canSync = ( const decodedEvent = decodeEventSync(machine, event) if (isFinalState(machine, state)) return false const configuration = normalizeConfigurationSync(machine, state) - return selectEventTransitions(machine, configuration, decodedEvent as any).length > 0 + return selectEventTransitions(machine, configuration, decodedEvent).length > 0 } const microstep = ( @@ -2041,7 +2006,7 @@ const settle = ( throw new Error("Machine reached a terminal configuration without a completed root output") } completedTerminal = true - finalOutput = currentState.outputs.get(root) as any + finalOutput = currentState.outputs.get(root) break } @@ -2104,7 +2069,7 @@ const settle = ( microsteps } return completedTerminal - ? { ...result, done: true as const, output: finalOutput as any } + ? { ...result, done: true as const, output: finalOutput } : { ...result, done: false as const, output: undefined } } @@ -2115,6 +2080,8 @@ const macrostepConfiguration = ( ) => { const decodedEvent = InvocationEvent.isInvocationEvent(event) ? event : decodeEventSync(machine, event) if (isActiveFinalConfiguration(machine, configuration)) { + // Completion contexts receive the triggering event, including private invocation events + // that the public lifecycle event type does not model. const completed = completeConfigurationSync(machine, configuration, decodedEvent as any) const root = getRootPath(machine, completed.configuration) if (!completed.configuration.outputs.has(root)) { @@ -2127,7 +2094,7 @@ const macrostepConfiguration = ( emittedEvents: [], microsteps: [], done: true as const, - output: completed.configuration.outputs.get(root) as any + output: completed.configuration.outputs.get(root) } } @@ -2152,7 +2119,7 @@ const macrostepConfiguration = ( const step = microstep( machine, configuration, - decodedEvent as any, + decodedEvent, selections ) const commands = [...step.commands] @@ -2160,7 +2127,7 @@ const macrostepConfiguration = ( const emittedEvents = [...step.emittedEvents] const microsteps = [step] return { - ...settle(machine, step.next, decodedEvent as any, commands, raisedEvents, emittedEvents, microsteps), + ...settle(machine, step.next, decodedEvent, commands, raisedEvents, emittedEvents, microsteps), event: decodedEvent } } diff --git a/packages/effect-machine/src/internal/machine/topology.ts b/packages/effect-machine/src/internal/machine/topology.ts index 997c74c..31f33bd 100644 --- a/packages/effect-machine/src/internal/machine/topology.ts +++ b/packages/effect-machine/src/internal/machine/topology.ts @@ -613,6 +613,28 @@ export const makeTarget = < values: options?.values }) as Machine.Target +/** + * Builds a target from a planned configuration whose path, value, snapshot, + * and ancestor values were already decoded, so no state schema type applies. + * It keeps the same own-property shape as `makeTarget`, including `values` + * when undefined, which the optional public `values` field cannot express. + */ +export const makeResolvedTarget = ( + path: string, + value: unknown, + options: { + readonly snapshot: Machine.AtomicSnapshot + readonly values: Readonly> | undefined + } +): Machine.Target => + ({ + [TargetTypeId]: TargetTypeId, + [TargetSnapshotTypeId]: options.snapshot, + path, + value, + values: options.values + }) as Machine.Target + export const isTarget = (u: unknown): u is Machine.Target => hasProperty(u, TargetTypeId) export const makeStateInput = (input: unknown): StateInput => ({ diff --git a/packages/effect-machine/src/internal/testing/machine/finiteModel.ts b/packages/effect-machine/src/internal/testing/machine/finiteModel.ts index ca24f43..e7f0d2a 100644 --- a/packages/effect-machine/src/internal/testing/machine/finiteModel.ts +++ b/packages/effect-machine/src/internal/testing/machine/finiteModel.ts @@ -1456,6 +1456,8 @@ export const compileModel = (model: FiniteModel): Machine.Machine.Any => { const flattened = validateModel(model) const byPath = new Map(flattened.map((state) => [state.path, state])) const stateTree = makeStateTree(model.roots, undefined) + // Erased boundary: the public constructors infer literal state and event types, + // but a finite model builds its schema tree and handlers at runtime. const defined = Machine.state({ states: stateTree } as any) const eventSchemas = model.events.map((event) => Schema.TaggedStruct(event, {})) const initial = byPath.get(model.initial)! @@ -1468,7 +1470,7 @@ export const compileModel = (model: FiniteModel): Machine.Machine.Any => { const machine = Machine.make({ root: defined, branches, - events: Machine.eventsFromSchemas(...eventSchemas) as any + events: Machine.eventsFromSchemas(...eventSchemas) } as any) return machine.handle( { diff --git a/packages/effect-machine/test/internal/machine/ProtocolValidation.test.ts b/packages/effect-machine/test/internal/machine/ProtocolValidation.test.ts index e859429..6872357 100644 --- a/packages/effect-machine/test/internal/machine/ProtocolValidation.test.ts +++ b/packages/effect-machine/test/internal/machine/ProtocolValidation.test.ts @@ -37,7 +37,7 @@ describe("event validation across execution strategies", () => { const selected = ExecutionPlan.selectExecutionPlanForTesting(machine, strategy) assert.strictEqual(selected.strategy, strategy === "auto" ? "indexed-flat" : "generic") const state = selected.plan.fromConfiguration( - Configuration.normalizeConfigurationSync>(machine, initial.state) + Configuration.normalizeConfigurationSync(machine, initial.state) ) selected.plan.plan(state, events.Set({ value: 1 }), true) Object.assign(retained as object, { value: "invalid" }) diff --git a/packages/effect-machine/test/internal/machine/strategyDifferential.test.ts b/packages/effect-machine/test/internal/machine/strategyDifferential.test.ts index bdc6785..d778521 100644 --- a/packages/effect-machine/test/internal/machine/strategyDifferential.test.ts +++ b/packages/effect-machine/test/internal/machine/strategyDifferential.test.ts @@ -397,7 +397,7 @@ describe("machine planner and runtime strategies", () => { const machine = makeFlatMachine() const initial = yield* Machine.planInitial(machine) const selected = ExecutionPlan.selectExecutionPlanForTesting(machine, "indexed-flat").plan - const active = Configuration.normalizeConfigurationSync>( + const active = Configuration.normalizeConfigurationSync( machine, initial.state )