effect-machine 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -55
- package/dist/actor.d.ts +77 -179
- package/dist/actor.js +161 -113
- package/dist/cluster/entity-machine.js +5 -3
- package/dist/errors.d.ts +12 -1
- package/dist/errors.js +8 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.js +2 -7
- package/dist/internal/transition.d.ts +27 -3
- package/dist/internal/transition.js +38 -9
- package/dist/internal/utils.d.ts +7 -2
- package/dist/internal/utils.js +1 -5
- package/dist/machine.d.ts +94 -35
- package/dist/machine.js +128 -13
- package/dist/testing.js +57 -3
- package/package.json +10 -9
- package/v3/dist/actor.d.ts +210 -0
- package/{dist-v3 → v3/dist}/actor.js +198 -117
- package/{dist-v3 → v3/dist}/cluster/entity-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/entity-machine.js +8 -6
- package/{dist-v3 → v3/dist}/cluster/to-entity.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/to-entity.js +1 -1
- package/v3/dist/errors.d.ts +76 -0
- package/{dist-v3 → v3/dist}/errors.js +9 -2
- package/v3/dist/index.d.ts +9 -0
- package/v3/dist/index.js +8 -0
- package/{dist-v3 → v3/dist}/inspection.d.ts +53 -8
- package/v3/dist/inspection.js +156 -0
- package/{dist-v3 → v3/dist}/internal/brands.d.ts +1 -1
- package/{dist-v3 → v3/dist}/internal/inspection.d.ts +1 -1
- package/v3/dist/internal/inspection.js +20 -0
- package/{dist-v3 → v3/dist}/internal/transition.d.ts +35 -11
- package/{dist-v3 → v3/dist}/internal/transition.js +47 -15
- package/{dist-v3 → v3/dist}/internal/utils.d.ts +9 -4
- package/{dist-v3 → v3/dist}/internal/utils.js +2 -6
- package/{dist-v3 → v3/dist}/machine.d.ts +113 -40
- package/{dist-v3 → v3/dist}/machine.js +191 -15
- package/{dist-v3 → v3/dist}/schema.d.ts +1 -1
- package/{dist-v3 → v3/dist}/schema.js +5 -2
- package/{dist-v3 → v3/dist}/slot.d.ts +4 -3
- package/{dist-v3 → v3/dist}/slot.js +1 -1
- package/{dist-v3 → v3/dist}/testing.d.ts +14 -8
- package/{dist-v3 → v3/dist}/testing.js +60 -6
- package/dist/persistence/adapter.d.ts +0 -135
- package/dist/persistence/adapter.js +0 -25
- package/dist/persistence/adapters/in-memory.d.ts +0 -32
- package/dist/persistence/adapters/in-memory.js +0 -174
- package/dist/persistence/index.d.ts +0 -5
- package/dist/persistence/index.js +0 -5
- package/dist/persistence/persistent-actor.d.ts +0 -50
- package/dist/persistence/persistent-actor.js +0 -368
- package/dist/persistence/persistent-machine.d.ts +0 -105
- package/dist/persistence/persistent-machine.js +0 -22
- package/dist-v3/actor.d.ts +0 -291
- package/dist-v3/errors.d.ts +0 -27
- package/dist-v3/index.d.ts +0 -12
- package/dist-v3/index.js +0 -13
- package/dist-v3/inspection.js +0 -48
- package/dist-v3/internal/inspection.js +0 -13
- package/dist-v3/persistence/adapter.d.ts +0 -125
- package/dist-v3/persistence/adapter.js +0 -25
- package/dist-v3/persistence/adapters/in-memory.d.ts +0 -32
- package/dist-v3/persistence/adapters/in-memory.js +0 -174
- package/dist-v3/persistence/index.d.ts +0 -5
- package/dist-v3/persistence/index.js +0 -5
- package/dist-v3/persistence/persistent-actor.d.ts +0 -49
- package/dist-v3/persistence/persistent-actor.js +0 -365
- package/dist-v3/persistence/persistent-machine.d.ts +0 -105
- package/dist-v3/persistence/persistent-machine.js +0 -22
- /package/{dist-v3 → v3/dist}/_virtual/_rolldown/runtime.js +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.js +0 -0
- /package/{dist-v3 → v3/dist}/internal/brands.js +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
|
|
2
|
+
import { Event, MachineEventSchema, MachineStateSchema, State } from "./schema.js";
|
|
3
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
4
|
+
import { ProcessEventResult } from "./internal/transition.js";
|
|
5
|
+
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
|
|
6
|
+
import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
|
|
7
|
+
import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
8
|
+
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
9
|
+
export { type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type BuiltMachine, DuplicateActorError, type EffectEvent, type EffectSlots, type EffectsDef, type EffectsSchema, type ErrorEvent, Event, type EventReceivedEvent, type GuardHandlers, type GuardSlot, type GuardSlots, type GuardsDef, type GuardsSchema, type HandlerContext, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, type ProcessEventResult, type ProvideHandlers, ProvisionValidationError, type SimulationResult, Slot, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
package/v3/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
2
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
3
|
+
import { Slot } from "./slot.js";
|
|
4
|
+
import { machine_exports } from "./machine.js";
|
|
5
|
+
import { ActorSystem, Default } from "./actor.js";
|
|
6
|
+
import { Event, State } from "./schema.js";
|
|
7
|
+
import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
8
|
+
export { ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, Slot, SlotProvisionError, State, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Schema } from "effect";
|
|
1
|
+
import { Context, Effect, Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
//#region src
|
|
3
|
+
//#region src/inspection.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.
|
|
6
6
|
*/
|
|
@@ -45,6 +45,18 @@ interface EffectEvent<S> {
|
|
|
45
45
|
readonly state: S;
|
|
46
46
|
readonly timestamp: number;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Event emitted when a task lifecycle phase occurs
|
|
50
|
+
*/
|
|
51
|
+
interface TaskEvent<S> {
|
|
52
|
+
readonly type: "@machine.task";
|
|
53
|
+
readonly actorId: string;
|
|
54
|
+
readonly state: S;
|
|
55
|
+
readonly taskName?: string;
|
|
56
|
+
readonly phase: "start" | "success" | "failure" | "interrupt";
|
|
57
|
+
readonly error?: string;
|
|
58
|
+
readonly timestamp: number;
|
|
59
|
+
}
|
|
48
60
|
/**
|
|
49
61
|
* Event emitted when a transition handler or spawn effect fails with a defect
|
|
50
62
|
*/
|
|
@@ -69,7 +81,7 @@ interface StopEvent<S> {
|
|
|
69
81
|
/**
|
|
70
82
|
* Union of all inspection events
|
|
71
83
|
*/
|
|
72
|
-
type InspectionEvent<S, E> = SpawnEvent<S> | EventReceivedEvent<S, E> | TransitionEvent<S, E> | EffectEvent<S> | ErrorEvent<S, E> | StopEvent<S>;
|
|
84
|
+
type InspectionEvent<S, E> = SpawnEvent<S> | EventReceivedEvent<S, E> | TransitionEvent<S, E> | EffectEvent<S> | TaskEvent<S> | ErrorEvent<S, E> | StopEvent<S>;
|
|
73
85
|
/**
|
|
74
86
|
* Convenience alias for untyped inspection events.
|
|
75
87
|
* Useful for general-purpose inspectors that don't need specific state/event types.
|
|
@@ -81,19 +93,23 @@ type AnyInspectionEvent = InspectionEvent<{
|
|
|
81
93
|
}, {
|
|
82
94
|
readonly _tag: string;
|
|
83
95
|
}>;
|
|
96
|
+
/**
|
|
97
|
+
* Inspector handler — sync callback or Effect-returning callback.
|
|
98
|
+
*/
|
|
99
|
+
type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
|
|
84
100
|
/**
|
|
85
101
|
* Inspector interface for observing machine behavior
|
|
86
102
|
*/
|
|
87
103
|
interface Inspector<S, E> {
|
|
88
|
-
readonly onInspect:
|
|
104
|
+
readonly onInspect: InspectorHandler<S, E>;
|
|
89
105
|
}
|
|
90
106
|
/**
|
|
91
107
|
* Inspector service tag - optional service for machine introspection
|
|
92
108
|
* Uses `any` types to allow variance flexibility when providing the service
|
|
93
109
|
*/
|
|
94
|
-
declare const Inspector: any
|
|
110
|
+
declare const Inspector: Context.Tag<Inspector<any, any>, Inspector<any, any>>;
|
|
95
111
|
/**
|
|
96
|
-
* Create an inspector from a callback function.
|
|
112
|
+
* Create an inspector from a sync callback function.
|
|
97
113
|
*
|
|
98
114
|
* Type params accept either raw tagged types or Schema constructors:
|
|
99
115
|
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
@@ -104,7 +120,36 @@ declare const makeInspector: <S = {
|
|
|
104
120
|
readonly _tag: string;
|
|
105
121
|
}, E = {
|
|
106
122
|
readonly _tag: string;
|
|
107
|
-
}>(onInspect:
|
|
123
|
+
}>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
|
|
124
|
+
/**
|
|
125
|
+
* Create an inspector from an Effect-returning callback function.
|
|
126
|
+
*/
|
|
127
|
+
declare const makeInspectorEffect: <S = {
|
|
128
|
+
readonly _tag: string;
|
|
129
|
+
}, E = {
|
|
130
|
+
readonly _tag: string;
|
|
131
|
+
}>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void, never, never>) => Inspector<ResolveType<S>, ResolveType<E>>;
|
|
132
|
+
/**
|
|
133
|
+
* Combine multiple inspectors into one. All run concurrently per event.
|
|
134
|
+
* Individual inspector failures are swallowed.
|
|
135
|
+
*/
|
|
136
|
+
declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
|
|
137
|
+
/**
|
|
138
|
+
* Options for the tracing inspector.
|
|
139
|
+
*/
|
|
140
|
+
interface TracingInspectorOptions<S, E> {
|
|
141
|
+
readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
|
|
142
|
+
readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
|
|
143
|
+
readonly eventName?: (event: InspectionEvent<S, E>) => string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Inspector that emits OpenTelemetry spans and events for each inspection event.
|
|
147
|
+
*/
|
|
148
|
+
declare const tracingInspector: <S extends {
|
|
149
|
+
readonly _tag: string;
|
|
150
|
+
}, E extends {
|
|
151
|
+
readonly _tag: string;
|
|
152
|
+
}>(options?: TracingInspectorOptions<S, E>) => Inspector<S, E>;
|
|
108
153
|
/**
|
|
109
154
|
* Console inspector that logs events in a readable format
|
|
110
155
|
*/
|
|
@@ -122,4 +167,4 @@ declare const collectingInspector: <S extends {
|
|
|
122
167
|
readonly _tag: string;
|
|
123
168
|
}>(events: InspectionEvent<S, E>[]) => Inspector<S, E>;
|
|
124
169
|
//#endregion
|
|
125
|
-
export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, SpawnEvent, StopEvent, TransitionEvent, collectingInspector, consoleInspector, makeInspector };
|
|
170
|
+
export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Context, Effect, Option } from "effect";
|
|
2
|
+
//#region src/inspection.ts
|
|
3
|
+
/**
|
|
4
|
+
* Inspector service tag - optional service for machine introspection
|
|
5
|
+
* Uses `any` types to allow variance flexibility when providing the service
|
|
6
|
+
*/
|
|
7
|
+
const Inspector = Context.GenericTag("@effect/machine/Inspector");
|
|
8
|
+
/**
|
|
9
|
+
* Create an inspector from a sync callback function.
|
|
10
|
+
*
|
|
11
|
+
* Type params accept either raw tagged types or Schema constructors:
|
|
12
|
+
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
13
|
+
* - `makeInspector<MyState, MyEvent>(cb)` — explicit tagged types
|
|
14
|
+
* - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
|
|
15
|
+
*/
|
|
16
|
+
const makeInspector = (onInspect) => ({ onInspect });
|
|
17
|
+
/**
|
|
18
|
+
* Create an inspector from an Effect-returning callback function.
|
|
19
|
+
*/
|
|
20
|
+
const makeInspectorEffect = (onInspect) => ({ onInspect });
|
|
21
|
+
/**
|
|
22
|
+
* Run an inspector handler, handling both sync and Effect returns.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
const inspectionEffect = (inspector, event) => {
|
|
26
|
+
const result = inspector.onInspect(event);
|
|
27
|
+
return Effect.isEffect(result) ? result : Effect.void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Combine multiple inspectors into one. All run concurrently per event.
|
|
31
|
+
* Individual inspector failures are swallowed.
|
|
32
|
+
*/
|
|
33
|
+
const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
|
|
34
|
+
concurrency: "unbounded",
|
|
35
|
+
discard: true
|
|
36
|
+
}) });
|
|
37
|
+
const inspectionSpanName = (event) => {
|
|
38
|
+
switch (event.type) {
|
|
39
|
+
case "@machine.spawn": return `Machine.inspect ${event.initialState._tag}`;
|
|
40
|
+
case "@machine.event": return `Machine.inspect ${event.event._tag}`;
|
|
41
|
+
case "@machine.transition": return `Machine.inspect ${event.fromState._tag}->${event.toState._tag}`;
|
|
42
|
+
case "@machine.effect": return `Machine.inspect ${event.effectType}`;
|
|
43
|
+
case "@machine.task": return `Machine.inspect task:${event.phase}`;
|
|
44
|
+
case "@machine.error": return `Machine.inspect ${event.phase}`;
|
|
45
|
+
case "@machine.stop": return `Machine.inspect ${event.finalState._tag}`;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const inspectionTraceName = (event) => {
|
|
49
|
+
switch (event.type) {
|
|
50
|
+
case "@machine.spawn": return `machine.spawn ${event.initialState._tag}`;
|
|
51
|
+
case "@machine.event": return `machine.event ${event.event._tag}`;
|
|
52
|
+
case "@machine.transition": return `machine.transition ${event.fromState._tag}->${event.toState._tag}`;
|
|
53
|
+
case "@machine.effect": return `machine.effect ${event.effectType}`;
|
|
54
|
+
case "@machine.task": return `machine.task ${event.phase}${event.taskName === void 0 ? "" : ` ${event.taskName}`}`;
|
|
55
|
+
case "@machine.error": return `machine.error ${event.phase}`;
|
|
56
|
+
case "@machine.stop": return `machine.stop ${event.finalState._tag}`;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const inspectionAttributes = (event) => {
|
|
60
|
+
const shared = {
|
|
61
|
+
"machine.actor.id": event.actorId,
|
|
62
|
+
"machine.inspection.type": event.type
|
|
63
|
+
};
|
|
64
|
+
switch (event.type) {
|
|
65
|
+
case "@machine.spawn": return {
|
|
66
|
+
...shared,
|
|
67
|
+
"machine.state.initial": event.initialState._tag
|
|
68
|
+
};
|
|
69
|
+
case "@machine.event": return {
|
|
70
|
+
...shared,
|
|
71
|
+
"machine.state.current": event.state._tag,
|
|
72
|
+
"machine.event.tag": event.event._tag
|
|
73
|
+
};
|
|
74
|
+
case "@machine.transition": return {
|
|
75
|
+
...shared,
|
|
76
|
+
"machine.state.from": event.fromState._tag,
|
|
77
|
+
"machine.state.to": event.toState._tag,
|
|
78
|
+
"machine.event.tag": event.event._tag
|
|
79
|
+
};
|
|
80
|
+
case "@machine.effect": return {
|
|
81
|
+
...shared,
|
|
82
|
+
"machine.state.current": event.state._tag,
|
|
83
|
+
"machine.effect.kind": event.effectType
|
|
84
|
+
};
|
|
85
|
+
case "@machine.task": return {
|
|
86
|
+
...shared,
|
|
87
|
+
"machine.state.current": event.state._tag,
|
|
88
|
+
"machine.task.phase": event.phase,
|
|
89
|
+
...event.taskName === void 0 ? {} : { "machine.task.name": event.taskName }
|
|
90
|
+
};
|
|
91
|
+
case "@machine.error": return {
|
|
92
|
+
...shared,
|
|
93
|
+
"machine.phase": event.phase,
|
|
94
|
+
"machine.state.current": event.state._tag
|
|
95
|
+
};
|
|
96
|
+
case "@machine.stop": return {
|
|
97
|
+
...shared,
|
|
98
|
+
"machine.state.final": event.finalState._tag
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Inspector that emits OpenTelemetry spans and events for each inspection event.
|
|
104
|
+
*/
|
|
105
|
+
const tracingInspector = (options) => ({ onInspect: (event) => {
|
|
106
|
+
const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
|
|
107
|
+
const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
|
|
108
|
+
const attributes = {
|
|
109
|
+
...inspectionAttributes(event),
|
|
110
|
+
...options?.attributes?.(event) ?? {}
|
|
111
|
+
};
|
|
112
|
+
return Effect.gen(function* () {
|
|
113
|
+
const currentSpan = yield* Effect.option(Effect.currentSpan);
|
|
114
|
+
if (Option.isSome(currentSpan)) currentSpan.value.event(traceName, BigInt(event.timestamp) * 1000000n, {
|
|
115
|
+
actorId: event.actorId,
|
|
116
|
+
inspectionType: event.type
|
|
117
|
+
});
|
|
118
|
+
}).pipe(Effect.withSpan(spanName ?? inspectionSpanName(event), { attributes }));
|
|
119
|
+
} });
|
|
120
|
+
/**
|
|
121
|
+
* Console inspector that logs events in a readable format
|
|
122
|
+
*/
|
|
123
|
+
const consoleInspector = () => makeInspector((event) => {
|
|
124
|
+
const prefix = `[${event.actorId}]`;
|
|
125
|
+
switch (event.type) {
|
|
126
|
+
case "@machine.spawn":
|
|
127
|
+
console.log(prefix, "spawned →", event.initialState._tag);
|
|
128
|
+
break;
|
|
129
|
+
case "@machine.event":
|
|
130
|
+
console.log(prefix, "received", event.event._tag, "in", event.state._tag);
|
|
131
|
+
break;
|
|
132
|
+
case "@machine.transition":
|
|
133
|
+
console.log(prefix, event.fromState._tag, "→", event.toState._tag);
|
|
134
|
+
break;
|
|
135
|
+
case "@machine.effect":
|
|
136
|
+
console.log(prefix, event.effectType, "effect in", event.state._tag);
|
|
137
|
+
break;
|
|
138
|
+
case "@machine.task":
|
|
139
|
+
console.log(prefix, "task", event.phase, event.taskName ?? "<unnamed>", "in", event.state._tag);
|
|
140
|
+
break;
|
|
141
|
+
case "@machine.error":
|
|
142
|
+
console.log(prefix, "error in", event.phase, event.state._tag, "-", event.error);
|
|
143
|
+
break;
|
|
144
|
+
case "@machine.stop":
|
|
145
|
+
console.log(prefix, "stopped in", event.finalState._tag);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Collecting inspector that stores events in an array for testing
|
|
151
|
+
*/
|
|
152
|
+
const collectingInspector = (events) => ({ onInspect: (event) => {
|
|
153
|
+
events.push(event);
|
|
154
|
+
} });
|
|
155
|
+
//#endregion
|
|
156
|
+
export { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Clock, Effect } from "effect";
|
|
2
|
+
//#region src/internal/inspection.ts
|
|
3
|
+
/**
|
|
4
|
+
* Emit an inspection event with timestamp from Clock.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function* (inspector, makeEvent) {
|
|
8
|
+
if (inspector === void 0) return;
|
|
9
|
+
const event = makeEvent(yield* Clock.currentTimeMillis);
|
|
10
|
+
const result = yield* Effect.sync(() => {
|
|
11
|
+
try {
|
|
12
|
+
return inspector.onInspect(event);
|
|
13
|
+
} catch {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
if (result !== void 0 && Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
|
|
18
|
+
});
|
|
19
|
+
//#endregion
|
|
20
|
+
export { emitWithTimestamp };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { EffectsDef, GuardsDef } from "../slot.js";
|
|
1
|
+
import { EffectsDef, GuardsDef, MachineContext } from "../slot.js";
|
|
2
2
|
import { BuiltMachine, Machine, MachineRef, SpawnEffect, Transition } from "../machine.js";
|
|
3
3
|
import { ActorSystem } from "../actor.js";
|
|
4
4
|
import { Cause, Effect, Scope } from "effect";
|
|
5
5
|
|
|
6
|
-
//#region src
|
|
6
|
+
//#region src/internal/transition.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* Result of executing a transition.
|
|
9
9
|
*/
|
|
@@ -29,7 +29,11 @@ declare const runTransitionHandler: <S extends {
|
|
|
29
29
|
readonly _tag: string;
|
|
30
30
|
}, E extends {
|
|
31
31
|
readonly _tag: string;
|
|
32
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem) => Effect.Effect<
|
|
32
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
|
|
33
|
+
newState: S;
|
|
34
|
+
hasReply: boolean;
|
|
35
|
+
reply: unknown;
|
|
36
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
33
37
|
/**
|
|
34
38
|
* Execute a transition for a given state and event.
|
|
35
39
|
* Handles transition resolution, handler invocation, and guard/effect slot creation.
|
|
@@ -45,11 +49,13 @@ declare const executeTransition: <S extends {
|
|
|
45
49
|
readonly _tag: string;
|
|
46
50
|
}, E extends {
|
|
47
51
|
readonly _tag: string;
|
|
48
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystem) => Effect.Effect<{
|
|
52
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
|
|
49
53
|
newState: S;
|
|
50
54
|
transitioned: boolean;
|
|
51
55
|
reenter: boolean;
|
|
52
|
-
|
|
56
|
+
hasReply: boolean;
|
|
57
|
+
reply: unknown;
|
|
58
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
53
59
|
/**
|
|
54
60
|
* Optional hooks for event processing inspection/tracing.
|
|
55
61
|
*/
|
|
@@ -84,7 +90,22 @@ interface ProcessEventResult<S> {
|
|
|
84
90
|
readonly lifecycleRan: boolean;
|
|
85
91
|
/** Whether new state is final */
|
|
86
92
|
readonly isFinal: boolean;
|
|
93
|
+
/** Whether the handler provided a reply (structural, not value-based) */
|
|
94
|
+
readonly hasReply: boolean;
|
|
95
|
+
/** Domain reply value from handler (used by ask). Only meaningful when hasReply is true. */
|
|
96
|
+
readonly reply?: unknown;
|
|
97
|
+
/** Whether the event was postponed (buffered for retry after next state change) */
|
|
98
|
+
readonly postponed: boolean;
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if an event should be postponed in the current state.
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
declare const shouldPostpone: <S extends {
|
|
105
|
+
readonly _tag: string;
|
|
106
|
+
}, E extends {
|
|
107
|
+
readonly _tag: string;
|
|
108
|
+
}, R>(machine: Machine<S, E, R, any, any, any, any>, stateTag: string, eventTag: string) => boolean;
|
|
88
109
|
/**
|
|
89
110
|
* Process a single event through the machine.
|
|
90
111
|
*
|
|
@@ -103,13 +124,16 @@ declare const processEventCore: <S extends {
|
|
|
103
124
|
readonly _tag: string;
|
|
104
125
|
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, stateScopeRef: {
|
|
105
126
|
current: Scope.CloseableScope;
|
|
106
|
-
}, system: ActorSystem, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
|
|
107
|
-
newState:
|
|
127
|
+
}, system: ActorSystem, actorId: string, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
|
|
128
|
+
newState: S;
|
|
108
129
|
previousState: S;
|
|
109
130
|
transitioned: boolean;
|
|
110
|
-
lifecycleRan:
|
|
131
|
+
lifecycleRan: boolean;
|
|
111
132
|
isFinal: boolean;
|
|
112
|
-
|
|
133
|
+
hasReply: boolean;
|
|
134
|
+
reply: unknown;
|
|
135
|
+
postponed: boolean;
|
|
136
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
113
137
|
/**
|
|
114
138
|
* Run spawn effects for a state (forked into state scope, auto-cancelled on state exit).
|
|
115
139
|
*
|
|
@@ -119,7 +143,7 @@ declare const runSpawnEffects: <S extends {
|
|
|
119
143
|
readonly _tag: string;
|
|
120
144
|
}, E extends {
|
|
121
145
|
readonly _tag: string;
|
|
122
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.CloseableScope, system: ActorSystem, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never,
|
|
146
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.CloseableScope, system: ActorSystem, actorId: string, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
123
147
|
/**
|
|
124
148
|
* Resolve which transition should fire for a given state and event.
|
|
125
149
|
* Uses indexed O(1) lookup. First matching transition wins.
|
|
@@ -157,4 +181,4 @@ declare const findSpawnEffects: <S extends {
|
|
|
157
181
|
readonly _tag: string;
|
|
158
182
|
}, R, GD extends GuardsDef = Record<string, never>, EFD extends EffectsDef = Record<string, never>>(machine: Machine<S, E, R, any, any, GD, EFD>, stateTag: string) => ReadonlyArray<SpawnEffect<S, E, EFD, R>>;
|
|
159
183
|
//#endregion
|
|
160
|
-
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
|
|
184
|
+
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler, shouldPostpone };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { INTERNAL_ENTER_EVENT, isEffect } from "./utils.js";
|
|
2
2
|
import { BuiltMachine } from "../machine.js";
|
|
3
3
|
import { Cause, Effect, Exit, Scope } from "effect";
|
|
4
|
-
//#region src
|
|
4
|
+
//#region src/internal/transition.ts
|
|
5
5
|
/**
|
|
6
6
|
* Transition execution and indexing.
|
|
7
7
|
*
|
|
@@ -22,8 +22,9 @@ import { Cause, Effect, Exit, Scope } from "effect";
|
|
|
22
22
|
*
|
|
23
23
|
* @internal
|
|
24
24
|
*/
|
|
25
|
-
const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system) {
|
|
25
|
+
const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system, actorId) {
|
|
26
26
|
const ctx = {
|
|
27
|
+
actorId,
|
|
27
28
|
state,
|
|
28
29
|
event,
|
|
29
30
|
self,
|
|
@@ -36,8 +37,18 @@ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(fu
|
|
|
36
37
|
guards,
|
|
37
38
|
effects
|
|
38
39
|
};
|
|
39
|
-
const
|
|
40
|
-
|
|
40
|
+
const raw = transition.handler(handlerCtx);
|
|
41
|
+
const resolved = isEffect(raw) ? yield* raw.pipe(Effect.provideService(machine.Context, ctx)) : raw;
|
|
42
|
+
if (resolved !== null && typeof resolved === "object" && "state" in resolved && "reply" in resolved && !("_tag" in resolved)) return {
|
|
43
|
+
newState: resolved.state,
|
|
44
|
+
hasReply: true,
|
|
45
|
+
reply: resolved.reply
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
newState: resolved,
|
|
49
|
+
hasReply: false,
|
|
50
|
+
reply: void 0
|
|
51
|
+
};
|
|
41
52
|
});
|
|
42
53
|
/**
|
|
43
54
|
* Execute a transition for a given state and event.
|
|
@@ -50,20 +61,33 @@ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(fu
|
|
|
50
61
|
*
|
|
51
62
|
* @internal
|
|
52
63
|
*/
|
|
53
|
-
const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system) {
|
|
64
|
+
const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system, actorId) {
|
|
54
65
|
const transition = resolveTransition(machine, currentState, event);
|
|
55
66
|
if (transition === void 0) return {
|
|
56
67
|
newState: currentState,
|
|
57
68
|
transitioned: false,
|
|
58
|
-
reenter: false
|
|
69
|
+
reenter: false,
|
|
70
|
+
hasReply: false,
|
|
71
|
+
reply: void 0
|
|
59
72
|
};
|
|
73
|
+
const { newState, hasReply, reply } = yield* runTransitionHandler(machine, transition, currentState, event, self, system, actorId);
|
|
60
74
|
return {
|
|
61
|
-
newState
|
|
75
|
+
newState,
|
|
62
76
|
transitioned: true,
|
|
63
|
-
reenter: transition.reenter === true
|
|
77
|
+
reenter: transition.reenter === true,
|
|
78
|
+
hasReply,
|
|
79
|
+
reply
|
|
64
80
|
};
|
|
65
81
|
});
|
|
66
82
|
/**
|
|
83
|
+
* Check if an event should be postponed in the current state.
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
const shouldPostpone = (machine, stateTag, eventTag) => {
|
|
87
|
+
for (const rule of machine.postponeRules) if (rule.stateTag === stateTag && rule.eventTag === eventTag) return true;
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
67
91
|
* Process a single event through the machine.
|
|
68
92
|
*
|
|
69
93
|
* Handles:
|
|
@@ -75,8 +99,8 @@ const executeTransition = Effect.fn("effect-machine.executeTransition")(function
|
|
|
75
99
|
*
|
|
76
100
|
* @internal
|
|
77
101
|
*/
|
|
78
|
-
const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, hooks) {
|
|
79
|
-
const result = yield* executeTransition(machine, currentState, event, self, system).pipe(Effect.catchAllCause((cause) => {
|
|
102
|
+
const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, actorId, hooks) {
|
|
103
|
+
const result = yield* executeTransition(machine, currentState, event, self, system, actorId).pipe(Effect.catchAllCause((cause) => {
|
|
80
104
|
if (Cause.isInterruptedOnly(cause)) return Effect.interrupt;
|
|
81
105
|
const onError = hooks?.onError;
|
|
82
106
|
if (onError === void 0) return Effect.failCause(cause).pipe(Effect.orDie);
|
|
@@ -92,7 +116,10 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
92
116
|
previousState: currentState,
|
|
93
117
|
transitioned: false,
|
|
94
118
|
lifecycleRan: false,
|
|
95
|
-
isFinal: false
|
|
119
|
+
isFinal: false,
|
|
120
|
+
hasReply: false,
|
|
121
|
+
reply: void 0,
|
|
122
|
+
postponed: false
|
|
96
123
|
};
|
|
97
124
|
const newState = result.newState;
|
|
98
125
|
const runLifecycle = newState._tag !== currentState._tag || result.reenter;
|
|
@@ -101,14 +128,17 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
101
128
|
stateScopeRef.current = yield* Scope.make();
|
|
102
129
|
if (hooks?.onTransition !== void 0) yield* hooks.onTransition(currentState, newState, event);
|
|
103
130
|
if (hooks?.onSpawnEffect !== void 0) yield* hooks.onSpawnEffect(newState);
|
|
104
|
-
yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, hooks?.onError);
|
|
131
|
+
yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, actorId, hooks?.onError);
|
|
105
132
|
}
|
|
106
133
|
return {
|
|
107
134
|
newState,
|
|
108
135
|
previousState: currentState,
|
|
109
136
|
transitioned: true,
|
|
110
137
|
lifecycleRan: runLifecycle,
|
|
111
|
-
isFinal: machine.finalStates.has(newState._tag)
|
|
138
|
+
isFinal: machine.finalStates.has(newState._tag),
|
|
139
|
+
hasReply: result.hasReply,
|
|
140
|
+
reply: result.reply,
|
|
141
|
+
postponed: false
|
|
112
142
|
};
|
|
113
143
|
});
|
|
114
144
|
/**
|
|
@@ -116,9 +146,10 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
116
146
|
*
|
|
117
147
|
* @internal
|
|
118
148
|
*/
|
|
119
|
-
const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, onError) {
|
|
149
|
+
const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, actorId, onError) {
|
|
120
150
|
const spawnEffects = findSpawnEffects(machine, state._tag);
|
|
121
151
|
const ctx = {
|
|
152
|
+
actorId,
|
|
122
153
|
state,
|
|
123
154
|
event,
|
|
124
155
|
self,
|
|
@@ -128,6 +159,7 @@ const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (m
|
|
|
128
159
|
const reportError = onError;
|
|
129
160
|
for (const spawnEffect of spawnEffects) {
|
|
130
161
|
const effect = spawnEffect.handler({
|
|
162
|
+
actorId,
|
|
131
163
|
state,
|
|
132
164
|
event,
|
|
133
165
|
self,
|
|
@@ -233,4 +265,4 @@ const findSpawnEffects = (machine, stateTag) => {
|
|
|
233
265
|
return getIndex(machine).spawn.get(stateTag) ?? [];
|
|
234
266
|
};
|
|
235
267
|
//#endregion
|
|
236
|
-
export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
|
|
268
|
+
export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler, shouldPostpone };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActorSystem } from "../actor.js";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
|
|
4
|
-
//#region src
|
|
4
|
+
//#region src/internal/utils.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Extracts _tag from a tagged union member
|
|
7
7
|
*/
|
|
@@ -23,10 +23,15 @@ type InstanceOf<C> = C extends ((...args: unknown[]) => infer R) ? R : never;
|
|
|
23
23
|
type TaggedConstructor<T extends {
|
|
24
24
|
readonly _tag: string;
|
|
25
25
|
}> = (args: Omit<T, "_tag">) => T;
|
|
26
|
+
/** Reply tuple returned from transition handlers for ask support */
|
|
27
|
+
interface TransitionReply<State> {
|
|
28
|
+
readonly state: State;
|
|
29
|
+
readonly reply: unknown;
|
|
30
|
+
}
|
|
26
31
|
/**
|
|
27
|
-
* Transition handler result - either a new state or Effect producing one
|
|
32
|
+
* Transition handler result - either a new state, reply tuple, or Effect producing one
|
|
28
33
|
*/
|
|
29
|
-
type TransitionResult<State, R> = State | Effect.Effect<State
|
|
34
|
+
type TransitionResult<State, R> = State | TransitionReply<State> | Effect.Effect<State | TransitionReply<State>, never, R>;
|
|
30
35
|
/**
|
|
31
36
|
* Internal event tags used for lifecycle effect contexts.
|
|
32
37
|
* Prefixed with $ to distinguish from user events.
|
|
@@ -57,4 +62,4 @@ declare const isEffect: (value: unknown) => value is Effect.Effect<unknown, unkn
|
|
|
57
62
|
*/
|
|
58
63
|
declare const stubSystem: ActorSystem;
|
|
59
64
|
//#endregion
|
|
60
|
-
export { ArgsOf, INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, InstanceOf, TagOf, TaggedConstructor, TransitionResult, getTag, isEffect, stubSystem };
|
|
65
|
+
export { ArgsOf, INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, InstanceOf, TagOf, TaggedConstructor, TransitionReply, TransitionResult, getTag, isEffect, stubSystem };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Stream } from "effect";
|
|
2
|
-
//#region src
|
|
2
|
+
//#region src/internal/utils.ts
|
|
3
3
|
/**
|
|
4
4
|
* Internal event tags used for lifecycle effect contexts.
|
|
5
5
|
* Prefixed with $ to distinguish from user events.
|
|
@@ -33,17 +33,13 @@ const isEffect = (value) => typeof value === "object" && value !== null && Effec
|
|
|
33
33
|
*/
|
|
34
34
|
const stubSystem = {
|
|
35
35
|
spawn: () => Effect.die("spawn not supported in stub system"),
|
|
36
|
-
restore: () => Effect.die("restore not supported in stub system"),
|
|
37
36
|
get: () => Effect.die("get not supported in stub system"),
|
|
38
37
|
stop: () => Effect.die("stop not supported in stub system"),
|
|
39
38
|
events: Stream.empty,
|
|
40
39
|
get actors() {
|
|
41
40
|
return /* @__PURE__ */ new Map();
|
|
42
41
|
},
|
|
43
|
-
subscribe: () => () => {}
|
|
44
|
-
listPersisted: () => Effect.die("listPersisted not supported in stub system"),
|
|
45
|
-
restoreMany: () => Effect.die("restoreMany not supported in stub system"),
|
|
46
|
-
restoreAll: () => Effect.die("restoreAll not supported in stub system")
|
|
42
|
+
subscribe: () => () => {}
|
|
47
43
|
};
|
|
48
44
|
//#endregion
|
|
49
45
|
export { INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, getTag, isEffect, stubSystem };
|