effect-machine 0.17.1 → 0.18.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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -54
  3. package/dist/actor.d.ts +8 -45
  4. package/dist/actor.js +157 -231
  5. package/dist/cluster/adapters/in-memory.d.ts +0 -1
  6. package/dist/cluster/adapters/in-memory.js +10 -5
  7. package/dist/cluster/entity-actor-ref.d.ts +2 -3
  8. package/dist/cluster/entity-actor-ref.js +14 -17
  9. package/dist/cluster/entity-machine.d.ts +2 -8
  10. package/dist/cluster/entity-machine.js +57 -34
  11. package/dist/cluster/index.js +1 -1
  12. package/dist/cluster/persistence.d.ts +0 -1
  13. package/dist/cluster/to-entity.d.ts +19 -21
  14. package/dist/cluster/to-entity.js +18 -19
  15. package/dist/errors.d.ts +11 -37
  16. package/dist/errors.js +12 -30
  17. package/dist/index.d.ts +4 -5
  18. package/dist/index.js +4 -5
  19. package/dist/inspection.d.ts +0 -1
  20. package/dist/inspection.js +24 -13
  21. package/dist/internal/brands.d.ts +0 -1
  22. package/dist/internal/event-advancement.d.ts +50 -0
  23. package/dist/internal/event-advancement.js +79 -0
  24. package/dist/internal/inspection.d.ts +5 -9
  25. package/dist/internal/inspection.js +31 -10
  26. package/dist/internal/machine-definition.d.ts +16 -0
  27. package/dist/internal/runtime.d.ts +1 -161
  28. package/dist/internal/runtime.js +191 -150
  29. package/dist/internal/transition.d.ts +4 -135
  30. package/dist/internal/transition.js +82 -157
  31. package/dist/internal/utils.d.ts +3 -40
  32. package/dist/internal/utils.js +2 -2
  33. package/dist/machine.d.ts +47 -137
  34. package/dist/machine.js +147 -215
  35. package/dist/schema.d.ts +42 -21
  36. package/dist/schema.js +28 -18
  37. package/dist/supervision.d.ts +1 -24
  38. package/dist/supervision.js +2 -3
  39. package/dist/testing.d.ts +15 -29
  40. package/dist/testing.js +76 -95
  41. package/package.json +19 -38
  42. package/dist/slot.d.ts +0 -159
  43. package/dist/slot.js +0 -165
  44. package/v3/dist/_virtual/_rolldown/runtime.js +0 -13
  45. package/v3/dist/actor.d.ts +0 -250
  46. package/v3/dist/actor.js +0 -577
  47. package/v3/dist/cluster/adapters/in-memory.d.ts +0 -15
  48. package/v3/dist/cluster/adapters/in-memory.js +0 -62
  49. package/v3/dist/cluster/entity-actor-ref.d.ts +0 -49
  50. package/v3/dist/cluster/entity-actor-ref.js +0 -19
  51. package/v3/dist/cluster/entity-machine.d.ts +0 -74
  52. package/v3/dist/cluster/entity-machine.js +0 -166
  53. package/v3/dist/cluster/index.d.ts +0 -6
  54. package/v3/dist/cluster/index.js +0 -6
  55. package/v3/dist/cluster/persistence.d.ts +0 -48
  56. package/v3/dist/cluster/persistence.js +0 -14
  57. package/v3/dist/cluster/to-entity.d.ts +0 -69
  58. package/v3/dist/cluster/to-entity.js +0 -59
  59. package/v3/dist/errors.d.ts +0 -95
  60. package/v3/dist/errors.js +0 -54
  61. package/v3/dist/index.d.ts +0 -11
  62. package/v3/dist/index.js +0 -9
  63. package/v3/dist/inspection.d.ts +0 -151
  64. package/v3/dist/inspection.js +0 -128
  65. package/v3/dist/internal/brands.d.ts +0 -50
  66. package/v3/dist/internal/inspection.d.ts +0 -11
  67. package/v3/dist/internal/inspection.js +0 -20
  68. package/v3/dist/internal/runtime.d.ts +0 -161
  69. package/v3/dist/internal/runtime.js +0 -360
  70. package/v3/dist/internal/transition.d.ts +0 -190
  71. package/v3/dist/internal/transition.js +0 -278
  72. package/v3/dist/internal/utils.d.ts +0 -101
  73. package/v3/dist/internal/utils.js +0 -75
  74. package/v3/dist/machine.d.ts +0 -398
  75. package/v3/dist/machine.js +0 -487
  76. package/v3/dist/schema.d.ts +0 -174
  77. package/v3/dist/schema.js +0 -206
  78. package/v3/dist/slot.d.ts +0 -158
  79. package/v3/dist/slot.js +0 -165
  80. package/v3/dist/supervision.d.ts +0 -97
  81. package/v3/dist/supervision.js +0 -42
  82. package/v3/dist/testing.d.ts +0 -151
  83. package/v3/dist/testing.js +0 -189
  84. /package/{v3/dist/internal/brands.js → dist/internal/machine-definition.js} +0 -0
package/v3/dist/schema.js DELETED
@@ -1,206 +0,0 @@
1
- import { InvalidSchemaError, MissingMatchHandlerError } from "./errors.js";
2
- import { Schema } from "effect";
3
- //#region src/schema.ts
4
- /**
5
- * Schema-first State/Event definitions for effect-machine.
6
- *
7
- * MachineSchema provides a single source of truth that combines:
8
- * - Schema for validation/serialization
9
- * - Variant constructors (like Data.taggedEnum)
10
- * - $is and $match helpers for pattern matching
11
- * - Brand integration for compile-time safety
12
- *
13
- * @example
14
- * ```ts
15
- * import { State, Event, Machine } from "effect-machine"
16
- *
17
- * // Define schema-first state
18
- * const OrderState = State({
19
- * Pending: { orderId: Schema.String },
20
- * Shipped: { trackingId: Schema.String },
21
- * })
22
- *
23
- * // Infer type from schema
24
- * type OrderState = typeof OrderState.Type
25
- *
26
- * // Use constructors
27
- * const pending = OrderState.Pending({ orderId: "123" })
28
- *
29
- * // Pattern match
30
- * OrderState.$match(state, {
31
- * Pending: (s) => `Order ${s.orderId} pending`,
32
- * Shipped: (s) => `Shipped: ${s.trackingId}`,
33
- * })
34
- *
35
- * // Use as Schema for persistence/cluster
36
- * machine.pipe(Machine.persist({ stateSchema: OrderState, ... }))
37
- * ```
38
- *
39
- * @module
40
- */
41
- const ReplySchemaSymbol = Symbol.for("effect-machine/ReplySchema");
42
- /**
43
- * Build a schema-first definition from a record of tag -> fields
44
- */
45
- const RESERVED_DERIVE_KEYS = new Set(["_tag"]);
46
- const buildMachineSchema = (definition) => {
47
- const variants = {};
48
- const constructors = {};
49
- const replySchemas = /* @__PURE__ */ new Map();
50
- for (const tag of Object.keys(definition)) {
51
- const fields = definition[tag];
52
- if (fields === void 0) continue;
53
- if (ReplySchemaSymbol in fields) {
54
- const rs = fields[ReplySchemaSymbol];
55
- if (rs !== void 0) replySchemas.set(tag, rs);
56
- }
57
- variants[tag] = Schema.TaggedStruct(tag, fields);
58
- const fieldNames = new Set(Object.keys(fields));
59
- if (fieldNames.size > 0) {
60
- const constructor = (args) => ({
61
- ...args,
62
- _tag: tag
63
- });
64
- constructor._tag = tag;
65
- constructor.with = (source, partial) => {
66
- const result = { _tag: tag };
67
- for (const key of fieldNames) if (key in source) result[key] = source[key];
68
- if (partial !== void 0) for (const [key, value] of Object.entries(partial)) {
69
- if (RESERVED_DERIVE_KEYS.has(key)) continue;
70
- if (!fieldNames.has(key)) continue;
71
- result[key] = value;
72
- }
73
- return result;
74
- };
75
- constructors[tag] = constructor;
76
- } else constructors[tag] = {
77
- _tag: tag,
78
- with: () => ({ _tag: tag })
79
- };
80
- }
81
- const variantArray = Object.values(variants);
82
- if (variantArray.length === 0) throw new InvalidSchemaError({ message: "Schema must have at least one variant" });
83
- const unionSchema = variantArray.length === 1 ? variantArray[0] : Schema.Union(...variantArray);
84
- const $is = (tag) => (u) => typeof u === "object" && u !== null && "_tag" in u && u._tag === tag;
85
- const $match = (valueOrCases, maybeCases) => {
86
- if (maybeCases !== void 0) {
87
- const value = valueOrCases;
88
- const handler = maybeCases[value._tag];
89
- if (handler === void 0) throw new MissingMatchHandlerError({ tag: value._tag });
90
- return handler(value);
91
- }
92
- const cases = valueOrCases;
93
- return (value) => {
94
- const handler = cases[value._tag];
95
- if (handler === void 0) throw new MissingMatchHandlerError({ tag: value._tag });
96
- return handler(value);
97
- };
98
- };
99
- return {
100
- schema: unionSchema,
101
- variants,
102
- constructors,
103
- _definition: definition,
104
- replySchemas,
105
- $is,
106
- $match
107
- };
108
- };
109
- /**
110
- * Internal helper to create a machine schema (shared by State and Event).
111
- * Builds the schema object with variants, constructors, $is, and $match.
112
- */
113
- const createMachineSchema = (definition) => {
114
- const { schema, variants, constructors, _definition, replySchemas, $is, $match } = buildMachineSchema(definition);
115
- const withFn = (source, partial) => {
116
- const ctor = constructors[source._tag];
117
- if (ctor === void 0) throw new MissingMatchHandlerError({ tag: source._tag });
118
- const fn = ctor.with;
119
- if (fn === void 0) throw new MissingMatchHandlerError({ tag: source._tag });
120
- return fn(source, partial);
121
- };
122
- return Object.assign(Object.create(schema), {
123
- variants,
124
- _definition,
125
- _replySchemas: replySchemas,
126
- schema,
127
- $is,
128
- $match,
129
- with: withFn,
130
- ...constructors
131
- });
132
- };
133
- /**
134
- * Create a schema-first State definition.
135
- *
136
- * The schema's definition type D creates a unique brand, preventing
137
- * accidental use of constructors from different state schemas
138
- * (unless they have identical definitions).
139
- *
140
- * @example
141
- * ```ts
142
- * const OrderState = MachineSchema.State({
143
- * Pending: { orderId: Schema.String },
144
- * Shipped: { trackingId: Schema.String },
145
- * })
146
- *
147
- * type OrderState = typeof OrderState.Type
148
- *
149
- * // Construct
150
- * const s = OrderState.Pending({ orderId: "123" })
151
- *
152
- * // Pattern match
153
- * OrderState.$match(s, {
154
- * Pending: (v) => v.orderId,
155
- * Shipped: (v) => v.trackingId,
156
- * })
157
- *
158
- * // Validate
159
- * Schema.decodeUnknownSync(OrderState)(rawJson)
160
- * ```
161
- */
162
- const State = (definition) => createMachineSchema(definition);
163
- /**
164
- * Create a schema-first Event definition.
165
- *
166
- * The schema's definition type D creates a unique brand, preventing
167
- * accidental use of constructors from different event schemas
168
- * (unless they have identical definitions).
169
- *
170
- * Use `Event.reply(fields, replySchema)` to define events that support
171
- * typed `ask()` replies.
172
- *
173
- * @example
174
- * ```ts
175
- * const OrderEvent = Event({
176
- * Ship: { trackingId: Schema.String },
177
- * Cancel: {},
178
- * GetTotal: Event.reply({}, Schema.Number),
179
- * })
180
- *
181
- * type OrderEvent = typeof OrderEvent.Type
182
- *
183
- * // Construct
184
- * const e = OrderEvent.Ship({ trackingId: "abc" })
185
- *
186
- * // Typed ask
187
- * const total = yield* actor.ask(OrderEvent.GetTotal) // number
188
- * ```
189
- */
190
- const EventImpl = (definition) => createMachineSchema(definition);
191
- /**
192
- * Annotate event fields with a reply schema.
193
- * Events defined with `Event.reply(fields, replySchema)` enable typed `ask()`.
194
- */
195
- const replyFieldsFn = (fields, replySchema) => {
196
- const annotated = { ...fields };
197
- Object.defineProperty(annotated, ReplySchemaSymbol, {
198
- value: replySchema,
199
- enumerable: false,
200
- writable: false
201
- });
202
- return annotated;
203
- };
204
- const Event = Object.assign(EventImpl, { reply: replyFieldsFn });
205
- //#endregion
206
- export { Event, State };
package/v3/dist/slot.d.ts DELETED
@@ -1,158 +0,0 @@
1
- import { ActorSystem } from "./actor.js";
2
- import { Context, Effect, Schema } from "effect";
3
-
4
- //#region src/slot.d.ts
5
- /** Schema fields definition (like Schema.Struct.Fields) */
6
- type Fields = Record<string, Schema.Schema.All>;
7
- /** Extract the type from schema fields (used for parameters) */
8
- type FieldsToParams<F extends Fields> = keyof F extends never ? void : Schema.Schema.Type<Schema.Struct<F>>;
9
- /**
10
- * Definition of a single slot function.
11
- * Created via `Slot.fn(params, returnSchema?)`.
12
- *
13
- * Carries both type-level information and materialized schemas
14
- * for runtime validation and serialization.
15
- */
16
- interface SlotFnDef<F extends Fields = Fields, _Return = void> {
17
- readonly _tag: "SlotFnDef";
18
- readonly fields: F;
19
- /** Return schema — undefined means void */
20
- readonly returnSchema: Schema.Schema.Any | undefined;
21
- /** Materialized input schema (Schema.Struct of fields, or Schema.Void for empty) */
22
- readonly inputSchema: Schema.Schema.Any;
23
- /** Materialized output schema (returnSchema or Schema.Void) */
24
- readonly outputSchema: Schema.Schema.Any;
25
- }
26
- /**
27
- * Define a single slot function with parameter schema and optional return schema.
28
- *
29
- * @example
30
- * ```ts
31
- * // Guard-like: returns boolean
32
- * Slot.fn({ max: Schema.Number }, Schema.Boolean)
33
- *
34
- * // Effect-like: returns void (default)
35
- * Slot.fn({ url: Schema.String })
36
- *
37
- * // No params, returns boolean
38
- * Slot.fn({}, Schema.Boolean)
39
- * ```
40
- */
41
- declare const fn: {
42
- <F extends Fields, S extends Schema.Schema.Any>(fields: F, returnSchema: S): SlotFnDef<F, Schema.Schema.Type<S>>;
43
- <F extends Fields>(fields: F): SlotFnDef<F>;
44
- };
45
- /**
46
- * Record of slot definitions. Keys are slot names, values are SlotFnDef.
47
- */
48
- type SlotsDef = Record<string, SlotFnDef<Fields, unknown>>;
49
- /**
50
- * Slots schema — returned by `Slot.define()`. Passed to `Machine.make({ slots })`.
51
- */
52
- interface SlotsSchema<D extends SlotsDef> {
53
- readonly _tag: "SlotsSchema";
54
- readonly definitions: D;
55
- /** Schema for slot requests `{ _tag: "SlotRequest", name, params }`. For RPC request payloads. */
56
- readonly requestSchema: Schema.Schema<SlotRequest<D>>;
57
- /** Schema for slot results `{ _tag: "SlotResult", name, result }`. For RPC response payloads. */
58
- readonly resultSchema: Schema.Schema<SlotResult<D>>;
59
- /** Schema for slot invocations `{ _tag: "SlotInvocation", name, params, result }`. For persistence/logging. */
60
- readonly invocationSchema: Schema.Schema<SlotInvocation<D>>;
61
- /** Create callable slot proxies (used by Machine internally) */
62
- readonly _createSlots: (resolve: <N extends keyof D & string>(name: N, params: SlotParams<D[N]>) => Effect.Effect<SlotReturn<D[N]>>) => SlotCalls<D>;
63
- }
64
- /**
65
- * A serialized slot request — captures name and params (no result).
66
- * Used for RPC request payloads.
67
- */
68
- type SlotRequest<D extends SlotsDef> = { readonly [K in keyof D & string]: {
69
- readonly _tag: "SlotRequest";
70
- readonly name: K;
71
- readonly params: SlotParams<D[K]>;
72
- } }[keyof D & string];
73
- /**
74
- * A serialized slot result — captures name and result (no params).
75
- * Used for RPC response payloads.
76
- */
77
- type SlotResult<D extends SlotsDef> = { readonly [K in keyof D & string]: {
78
- readonly _tag: "SlotResult";
79
- readonly name: K;
80
- readonly result: SlotReturn<D[K]>;
81
- } }[keyof D & string];
82
- /**
83
- * A serialized slot invocation — captures name, params, and result.
84
- * Used for persistence, logging, and audit trails.
85
- */
86
- type SlotInvocation<D extends SlotsDef> = { readonly [K in keyof D & string]: {
87
- readonly _tag: "SlotInvocation";
88
- readonly name: K;
89
- readonly params: SlotParams<D[K]>;
90
- readonly result: SlotReturn<D[K]>;
91
- } }[keyof D & string];
92
- /** Extract params type from a SlotFnDef */
93
- type SlotParams<D extends SlotFnDef<Fields, unknown>> = D extends SlotFnDef<infer F, unknown> ? FieldsToParams<F> : never;
94
- /** Extract return type from a SlotFnDef */
95
- type SlotReturn<D extends SlotFnDef<Fields, unknown>> = D extends SlotFnDef<Fields, infer R> ? R : never;
96
- /**
97
- * A callable slot — function that takes params and returns Effect<Return>.
98
- */
99
- interface SlotCall<Name extends string, Params, Return> {
100
- readonly _tag: "Slot";
101
- readonly name: Name;
102
- (params: Params): Effect.Effect<Return>;
103
- }
104
- /**
105
- * Convert slot definitions to callable slot proxies.
106
- */
107
- type SlotCalls<D extends SlotsDef> = { readonly [K in keyof D & string]: SlotCall<K, SlotParams<D[K]>, SlotReturn<D[K]>> };
108
- /**
109
- * Slot handler implementation.
110
- * Receives only params — use `yield* machine.Context` for machine context.
111
- */
112
- type SlotHandler<Params, Return, R = never> = (params: Params) => Return | Effect.Effect<Return, never, R>;
113
- /**
114
- * Handler implementations for all slots in a definition.
115
- */
116
- type ProvideSlots<D extends SlotsDef, R = never> = { readonly [K in keyof D & string]: SlotHandler<SlotParams<D[K]>, SlotReturn<D[K]>, R> };
117
- /** Check if a SlotsDef has any actual keys */
118
- type HasSlotKeys<SD extends SlotsDef> = [keyof SD] extends [never] ? false : SD extends Record<string, never> ? false : true;
119
- /**
120
- * Type for machine context — state, event, and self reference.
121
- * Shared across all machines via MachineContextTag.
122
- */
123
- interface MachineContext<State, Event, Self> {
124
- readonly actorId: string;
125
- readonly state: State;
126
- readonly event: Event;
127
- readonly self: Self;
128
- readonly system: ActorSystem;
129
- }
130
- /**
131
- * Shared Context tag for all machines.
132
- * Single module-level tag instead of per-machine allocation.
133
- * @internal
134
- */
135
- declare const MachineContextTag: Context.Tag<MachineContext<any, any, any>, MachineContext<any, any, any>>;
136
- /**
137
- * Define a set of slots with parameter and return schemas.
138
- *
139
- * @example
140
- * ```ts
141
- * const MySlots = Slot.define({
142
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
143
- * fetchData: Slot.fn({ url: Schema.String }),
144
- * notify: Slot.fn({ message: Schema.String }),
145
- * })
146
- * ```
147
- */
148
- declare const define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
149
- declare const Slot: {
150
- readonly fn: {
151
- <F extends Fields, S extends Schema.Schema.Any>(fields: F, returnSchema: S): SlotFnDef<F, Schema.Schema.Type<S>>;
152
- <F extends Fields>(fields: F): SlotFnDef<F>;
153
- };
154
- readonly define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
155
- readonly of: <D extends SlotsDef>(slotsSchema: SlotsSchema<D>, provided: ProvideSlots<D>) => SlotCalls<D>;
156
- };
157
- //#endregion
158
- export { HasSlotKeys, MachineContext, MachineContextTag, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema, define, fn };
package/v3/dist/slot.js DELETED
@@ -1,165 +0,0 @@
1
- import { Context, Effect, Schema } from "effect";
2
- //#region src/slot.ts
3
- /**
4
- * Slot module — unified, schema-based parameterized slots.
5
- *
6
- * Replaces the split Guards/Effects API with a single `Slot.define` + `Slot.fn`.
7
- * Each slot declares its parameter schema and (optional) return schema.
8
- * Handlers receive only params — machine context is accessed via `yield* machine.Context`.
9
- *
10
- * @example
11
- * ```ts
12
- * import { Slot } from "effect-machine"
13
- * import { Schema } from "effect"
14
- *
15
- * const MySlots = Slot.define({
16
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
17
- * isValid: Slot.fn({}, Schema.Boolean),
18
- * fetchData: Slot.fn({ url: Schema.String }),
19
- * notify: Slot.fn({ message: Schema.String }),
20
- * })
21
- *
22
- * // Used in handlers:
23
- * .on(State.X, Event.Y, ({ slots }) =>
24
- * Effect.gen(function* () {
25
- * if (yield* slots.canRetry({ max: 3 })) {
26
- * yield* slots.fetchData({ url: "/api" })
27
- * return State.Next
28
- * }
29
- * return state
30
- * })
31
- * )
32
- * ```
33
- *
34
- * @module
35
- */
36
- /**
37
- * Define a single slot function with parameter schema and optional return schema.
38
- *
39
- * @example
40
- * ```ts
41
- * // Guard-like: returns boolean
42
- * Slot.fn({ max: Schema.Number }, Schema.Boolean)
43
- *
44
- * // Effect-like: returns void (default)
45
- * Slot.fn({ url: Schema.String })
46
- *
47
- * // No params, returns boolean
48
- * Slot.fn({}, Schema.Boolean)
49
- * ```
50
- */
51
- const fn = (fields, returnSchema) => {
52
- return {
53
- _tag: "SlotFnDef",
54
- fields,
55
- returnSchema,
56
- inputSchema: Object.keys(fields).length > 0 ? Schema.Struct(fields) : Schema.Void,
57
- outputSchema: returnSchema ?? Schema.Void
58
- };
59
- };
60
- /**
61
- * Shared Context tag for all machines.
62
- * Single module-level tag instead of per-machine allocation.
63
- * @internal
64
- */
65
- const MachineContextTag = Context.GenericTag("@effect-machine/Context");
66
- /**
67
- * Define a set of slots with parameter and return schemas.
68
- *
69
- * @example
70
- * ```ts
71
- * const MySlots = Slot.define({
72
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
73
- * fetchData: Slot.fn({ url: Schema.String }),
74
- * notify: Slot.fn({ message: Schema.String }),
75
- * })
76
- * ```
77
- */
78
- const define = (definitions) => {
79
- const names = Object.keys(definitions);
80
- const requestSchemas = [];
81
- const resultSchemas = [];
82
- const invocationSchemas = [];
83
- for (const name of names) {
84
- const def = definitions[name];
85
- if (def === void 0) continue;
86
- requestSchemas.push(Schema.TaggedStruct("SlotRequest", {
87
- name: Schema.Literal(name),
88
- params: def.inputSchema
89
- }));
90
- resultSchemas.push(Schema.TaggedStruct("SlotResult", {
91
- name: Schema.Literal(name),
92
- result: def.outputSchema
93
- }));
94
- invocationSchemas.push(Schema.TaggedStruct("SlotInvocation", {
95
- name: Schema.Literal(name),
96
- params: def.inputSchema,
97
- result: def.outputSchema
98
- }));
99
- }
100
- const buildUnion = (schemas) => schemas.length === 0 ? Schema.Never : Schema.Union(...schemas);
101
- return {
102
- _tag: "SlotsSchema",
103
- definitions,
104
- requestSchema: buildUnion(requestSchemas),
105
- resultSchema: buildUnion(resultSchemas),
106
- invocationSchema: buildUnion(invocationSchemas),
107
- _createSlots: (resolve) => {
108
- const slots = {};
109
- for (const name of names) {
110
- const slot = (params) => resolve(name, params);
111
- Object.defineProperty(slot, "_tag", {
112
- value: "Slot",
113
- enumerable: true
114
- });
115
- Object.defineProperty(slot, "name", {
116
- value: name,
117
- enumerable: true
118
- });
119
- slots[name] = slot;
120
- }
121
- return slots;
122
- }
123
- };
124
- };
125
- /**
126
- * Convert raw slot handler implementations into the callable `SlotCalls` form.
127
- *
128
- * Handlers that return plain values are wrapped in `Effect.succeed`.
129
- * Handlers that return Effects are called directly inside `Effect.suspend`.
130
- *
131
- * @example
132
- * ```ts
133
- * const provided = yield* myExtension.slots(ctx)
134
- * const slots = Slot.of(slotsSchema, provided)
135
- * // slots.mySlot({ param: 1 }) returns Effect<ReturnType>
136
- * ```
137
- */
138
- const of = (slotsSchema, provided) => {
139
- const slots = {};
140
- for (const name of Object.keys(slotsSchema.definitions)) {
141
- const handler = provided[name];
142
- if (handler === void 0) continue;
143
- const call = (params) => Effect.suspend(() => {
144
- const result = handler(params);
145
- return Effect.isEffect(result) ? result : Effect.succeed(result);
146
- });
147
- Object.defineProperty(call, "_tag", {
148
- value: "Slot",
149
- enumerable: true
150
- });
151
- Object.defineProperty(call, "name", {
152
- value: name,
153
- enumerable: true
154
- });
155
- slots[name] = call;
156
- }
157
- return slots;
158
- };
159
- const Slot = {
160
- fn,
161
- define,
162
- of
163
- };
164
- //#endregion
165
- export { MachineContextTag, Slot, define, fn };
@@ -1,97 +0,0 @@
1
- import { Cause, Duration, Schedule } from "effect";
2
-
3
- //#region src/supervision.d.ts
4
- /**
5
- * Where in the actor lifecycle a defect occurred.
6
- *
7
- * - `transition` — during event handler execution
8
- * - `spawn` — during state spawn effect execution
9
- * - `background` — in a background effect fiber
10
- * - `initial-spawn` — during initial state spawn effects (before event loop)
11
- */
12
- type DefectPhase = "transition" | "spawn" | "background" | "initial-spawn";
13
- /**
14
- * Terminal exit reason for an actor generation.
15
- *
16
- * - `Final` — machine reached a final state normally
17
- * - `Stopped` — explicit `actor.stop` or `actor.drain`
18
- * - `Defect` — unhandled error in the runtime
19
- */
20
- type ActorExit<S> = {
21
- readonly _tag: "Final";
22
- readonly state: S;
23
- } | {
24
- readonly _tag: "Stopped";
25
- } | {
26
- readonly _tag: "Defect";
27
- readonly cause: Cause.Cause<unknown>;
28
- readonly phase: DefectPhase;
29
- };
30
- /** Constructors for ActorExit */
31
- declare const ActorExit: {
32
- readonly Final: <S>(state: S) => ActorExit<S>;
33
- readonly Stopped: ActorExit<never>;
34
- readonly Defect: <S = never>(cause: Cause.Cause<unknown>, phase: DefectPhase) => ActorExit<S>;
35
- };
36
- /**
37
- * Phase state for supervised actors. Serializes concurrent stop/restart/drain.
38
- *
39
- * Transitions:
40
- * - `Running` → crash → `Restarting` → new runtime → `Running`
41
- * - `Running` → explicit stop/drain → `Stopping` → `Terminated`
42
- * - `Restarting` → explicit stop → `Stopping` → `Terminated`
43
- *
44
- * @internal
45
- */
46
- type CellPhase<S> = {
47
- readonly _tag: "Running";
48
- readonly generation: number;
49
- } | {
50
- readonly _tag: "Restarting";
51
- readonly generation: number;
52
- } | {
53
- readonly _tag: "Stopping";
54
- } | {
55
- readonly _tag: "Terminated";
56
- readonly exit: ActorExit<S>;
57
- };
58
- declare namespace Supervision {
59
- /**
60
- * Supervision policy for actor restart behavior.
61
- *
62
- * `schedule` controls restart timing and budget — schedule exhaustion means terminal stop.
63
- * `shouldRestart` optionally classifies defects — return `false` to stop immediately
64
- * without consuming the schedule.
65
- */
66
- interface Policy {
67
- /** Schedule that controls restart timing. Exhaustion = terminal stop. */
68
- readonly schedule: Schedule.Schedule<unknown>;
69
- /**
70
- * Optional classifier: given a defect exit, decide whether to restart or stop immediately.
71
- * Default: always restart (let schedule handle budget).
72
- */
73
- readonly shouldRestart?: (exit: Extract<ActorExit<unknown>, {
74
- readonly _tag: "Defect";
75
- }>) => boolean;
76
- }
77
- /** No supervision — crashes are terminal. */
78
- const none: Policy;
79
- /**
80
- * Restart on defect with max restarts within a window, optional backoff.
81
- *
82
- * @example
83
- * ```ts
84
- * Supervision.restart() // unlimited restarts, no backoff
85
- * Supervision.restart({ maxRestarts: 3 }) // 3 restarts then terminal
86
- * Supervision.restart({ maxRestarts: 3, within: "1 minute" }) // 3 within 1 min
87
- * Supervision.restart({ backoff: Schedule.exponential("100 millis") })
88
- * ```
89
- */
90
- const restart: (options?: {
91
- readonly maxRestarts?: number;
92
- readonly within?: Duration.DurationInput;
93
- readonly backoff?: Schedule.Schedule<unknown>;
94
- }) => Policy;
95
- }
96
- //#endregion
97
- export { ActorExit, CellPhase, DefectPhase, Supervision };
@@ -1,42 +0,0 @@
1
- import { Schedule } from "effect";
2
- //#region src/supervision.ts
3
- /**
4
- * Supervision types for actor lifecycle management.
5
- *
6
- * Core concepts:
7
- * - `ActorExit<S>` — why an actor stopped (final, explicit stop, or defect)
8
- * - `DefectPhase` — where in the lifecycle a defect occurred
9
- * - `Supervision.Policy` — Schedule-based restart policy
10
- * - `CellPhase<S>` — internal phase machine for serializing stop/restart/drain
11
- *
12
- * @module
13
- */
14
- /** Constructors for ActorExit */
15
- const ActorExit = {
16
- Final: (state) => ({
17
- _tag: "Final",
18
- state
19
- }),
20
- Stopped: { _tag: "Stopped" },
21
- Defect: (cause, phase) => ({
22
- _tag: "Defect",
23
- cause,
24
- phase
25
- })
26
- };
27
- let Supervision;
28
- (function(_Supervision) {
29
- _Supervision.none = { schedule: Schedule.recurs(0) };
30
- _Supervision.restart = (options) => {
31
- let schedule = Schedule.forever;
32
- if (options?.maxRestarts !== void 0) {
33
- const recurs = Schedule.recurs(options.maxRestarts);
34
- if (options.within !== void 0) schedule = Schedule.intersect(recurs, Schedule.windowed(options.within));
35
- else schedule = recurs;
36
- }
37
- if (options?.backoff !== void 0) schedule = Schedule.intersect(schedule, options.backoff);
38
- return { schedule };
39
- };
40
- })(Supervision || (Supervision = {}));
41
- //#endregion
42
- export { ActorExit, Supervision };