effect-machine 0.16.0 → 0.17.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 (40) hide show
  1. package/README.md +4 -0
  2. package/dist/actor.d.ts +9 -7
  3. package/dist/actor.js +2 -2
  4. package/dist/cluster/adapters/in-memory.d.ts +4 -4
  5. package/dist/cluster/adapters/in-memory.js +2 -2
  6. package/dist/cluster/entity-machine.d.ts +2 -2
  7. package/dist/cluster/index.d.ts +2 -2
  8. package/dist/cluster/persistence.d.ts +4 -3
  9. package/dist/cluster/persistence.js +1 -1
  10. package/dist/cluster/to-entity.d.ts +2 -2
  11. package/dist/index.d.ts +3 -3
  12. package/dist/inspection.d.ts +11 -10
  13. package/dist/inspection.js +9 -23
  14. package/dist/internal/inspection.d.ts +2 -2
  15. package/dist/internal/runtime.d.ts +7 -7
  16. package/dist/internal/runtime.js +9 -14
  17. package/dist/internal/transition.d.ts +9 -9
  18. package/dist/internal/utils.d.ts +3 -3
  19. package/dist/internal/utils.js +1 -1
  20. package/dist/machine.d.ts +4 -4
  21. package/dist/machine.js +20 -2
  22. package/dist/schema.d.ts +24 -13
  23. package/dist/schema.js +8 -8
  24. package/dist/slot.d.ts +7 -5
  25. package/dist/slot.js +38 -3
  26. package/dist/testing.d.ts +7 -7
  27. package/package.json +14 -18
  28. package/v3/dist/actor.d.ts +1 -1
  29. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  30. package/v3/dist/cluster/entity-machine.js +4 -3
  31. package/v3/dist/cluster/to-entity.d.ts +8 -3
  32. package/v3/dist/inspection.d.ts +2 -2
  33. package/v3/dist/inspection.js +8 -22
  34. package/v3/dist/internal/runtime.d.ts +5 -5
  35. package/v3/dist/internal/runtime.js +9 -14
  36. package/v3/dist/machine.js +2 -1
  37. package/v3/dist/schema.d.ts +25 -12
  38. package/v3/dist/schema.js +8 -7
  39. package/v3/dist/slot.d.ts +3 -2
  40. package/v3/dist/slot.js +37 -2
@@ -49,16 +49,23 @@ type VariantReplyBrand<Fields extends Schema.Struct.Fields> = Fields extends {
49
49
  * Empty structs: plain values with `_tag`: `State.Idle`
50
50
  * Non-empty structs require args: `State.Loading({ url })`
51
51
  *
52
- * Each variant also has a `derive` method for constructing from a source object.
52
+ * Each variant also has a `with` method for constructing from a source object,
53
+ * copying matching fields and overriding with a partial.
53
54
  * The source type uses `object` to accept branded state types without index signature issues.
54
55
  * Reply-bearing variants carry ReplyTypeBrand<R> for ask() type inference.
55
56
  */
56
57
  type VariantConstructors<D extends Record<string, Schema.Struct.Fields>, Brand> = { readonly [K in keyof D & string]: IsEmptyFields<D[K]> extends true ? TaggedStructType<K, D[K]> & Brand & VariantReplyBrand<D[K]> & {
57
- readonly derive: (source: object) => TaggedStructType<K, D[K]> & Brand;
58
+ readonly with: (source: object) => TaggedStructType<K, D[K]> & Brand;
58
59
  } : ((args: Schema.Struct.Type<PayloadFields<D[K]>>) => TaggedStructType<K, D[K]> & Brand & VariantReplyBrand<D[K]>) & {
59
- readonly derive: (source: object, partial?: Partial<Schema.Struct.Type<PayloadFields<D[K]>>>) => TaggedStructType<K, D[K]> & Brand;
60
+ readonly with: (source: object, partial?: Partial<Schema.Struct.Type<PayloadFields<D[K]>>>) => TaggedStructType<K, D[K]> & Brand;
60
61
  readonly _tag: K;
61
62
  } };
63
+ /**
64
+ * Keys present in ALL variants (intersection of field names).
65
+ * Used by union-level `with` to accept only fields safe to update
66
+ * regardless of which variant the source is.
67
+ */
68
+ type SharedKeys<D extends Record<string, Schema.Struct.Fields>> = keyof D[keyof D & string] & string;
62
69
  /**
63
70
  * Pattern matching cases type
64
71
  */
@@ -87,19 +94,23 @@ interface MachineSchemaBase<D extends Record<string, Schema.Struct.Fields>, Bran
87
94
  <R>(value: VariantsUnion<D> & Brand, cases: MatchCases<D, R>): R;
88
95
  };
89
96
  /**
90
- * Union-level derive: copies fields from `source` into the same variant,
91
- * overriding with `partial`. Preserves the specific variant subtype.
97
+ * Copy fields from `source` into the same variant, overriding with `partial`.
98
+ * Preserves the specific variant subtype in the return.
92
99
  *
93
- * Dispatches to the per-variant `derive` based on `source._tag`.
100
+ * The partial accepts fields common to all variants, so it works safely
101
+ * when `S` is a generic type parameter (e.g., `<S extends MyState>`).
94
102
  *
95
103
  * @example
96
104
  * ```ts
97
- * // Instead of switching on _tag to call per-variant derive:
98
- * const updated = AgentLoopState.derive(state, { queue: newQueue })
99
- * // If state is StreamingState, returns StreamingState (not LoopState)
105
+ * // Per-variant field update
106
+ * const next = MyState.Streaming.with(state, { draft: newDraft })
107
+ *
108
+ * // Cross-variant shared field — works with generic state
109
+ * const updateQueue = <S extends MyState>(state: S, queue: Queue): S =>
110
+ * MyState.with(state, { queue })
100
111
  * ```
101
112
  */
102
- readonly derive: <S extends VariantsUnion<D> & Brand>(source: S, partial?: Partial<Omit<S, "_tag">>) => S;
113
+ readonly with: <S extends VariantsUnion<D> & Brand>(source: S, partial?: Partial<Record<SharedKeys<D>, unknown>>) => S;
103
114
  /**
104
115
  * Reply schemas per variant tag. Only populated for event schemas
105
116
  * with variants defined via `Event.reply()`.
@@ -116,14 +127,16 @@ interface MachineSchemaBase<D extends Record<string, Schema.Struct.Fields>, Bran
116
127
  * The D type parameter captures the definition, creating a unique brand
117
128
  * per distinct schema definition shape.
118
129
  */
119
- type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullStateBrand<D>, unknown, never> & MachineSchemaBase<D, FullStateBrand<D>> & VariantConstructors<D, FullStateBrand<D>>;
130
+ type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullStateBrand<D>, unknown> & MachineSchemaBase<D, FullStateBrand<D>> & VariantConstructors<D, FullStateBrand<D>> & {
131
+ /** Schema for persistence, config, and registration. */readonly schema: Schema.Schema<VariantsUnion<D> & FullStateBrand<D>>;
132
+ };
120
133
  /**
121
134
  * Schema-first event definition (same structure as state, different brand)
122
135
  *
123
136
  * The D type parameter captures the definition, creating a unique brand
124
137
  * per distinct schema definition shape.
125
138
  */
126
- type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullEventBrand<D>, unknown, never> & MachineSchemaBase<D, FullEventBrand<D>> & VariantConstructors<D, FullEventBrand<D>>;
139
+ type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullEventBrand<D>, unknown> & MachineSchemaBase<D, FullEventBrand<D>> & VariantConstructors<D, FullEventBrand<D>>;
127
140
  /**
128
141
  * Create a schema-first State definition.
129
142
  *
package/v3/dist/schema.js CHANGED
@@ -62,7 +62,7 @@ const buildMachineSchema = (definition) => {
62
62
  _tag: tag
63
63
  });
64
64
  constructor._tag = tag;
65
- constructor.derive = (source, partial) => {
65
+ constructor.with = (source, partial) => {
66
66
  const result = { _tag: tag };
67
67
  for (const key of fieldNames) if (key in source) result[key] = source[key];
68
68
  if (partial !== void 0) for (const [key, value] of Object.entries(partial)) {
@@ -75,7 +75,7 @@ const buildMachineSchema = (definition) => {
75
75
  constructors[tag] = constructor;
76
76
  } else constructors[tag] = {
77
77
  _tag: tag,
78
- derive: () => ({ _tag: tag })
78
+ with: () => ({ _tag: tag })
79
79
  };
80
80
  }
81
81
  const variantArray = Object.values(variants);
@@ -112,20 +112,21 @@ const buildMachineSchema = (definition) => {
112
112
  */
113
113
  const createMachineSchema = (definition) => {
114
114
  const { schema, variants, constructors, _definition, replySchemas, $is, $match } = buildMachineSchema(definition);
115
- const derive = (source, partial) => {
115
+ const withFn = (source, partial) => {
116
116
  const ctor = constructors[source._tag];
117
117
  if (ctor === void 0) throw new MissingMatchHandlerError({ tag: source._tag });
118
- const deriveFn = ctor.derive;
119
- if (deriveFn === void 0) throw new MissingMatchHandlerError({ tag: source._tag });
120
- return deriveFn(source, partial);
118
+ const fn = ctor.with;
119
+ if (fn === void 0) throw new MissingMatchHandlerError({ tag: source._tag });
120
+ return fn(source, partial);
121
121
  };
122
122
  return Object.assign(Object.create(schema), {
123
123
  variants,
124
124
  _definition,
125
125
  _replySchemas: replySchemas,
126
+ schema,
126
127
  $is,
127
128
  $match,
128
- derive,
129
+ with: withFn,
129
130
  ...constructors
130
131
  });
131
132
  };
package/v3/dist/slot.d.ts CHANGED
@@ -40,7 +40,7 @@ interface SlotFnDef<F extends Fields = Fields, _Return = void> {
40
40
  */
41
41
  declare const fn: {
42
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, void>;
43
+ <F extends Fields>(fields: F): SlotFnDef<F>;
44
44
  };
45
45
  /**
46
46
  * Record of slot definitions. Keys are slot names, values are SlotFnDef.
@@ -149,9 +149,10 @@ declare const define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
149
149
  declare const Slot: {
150
150
  readonly fn: {
151
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, void>;
152
+ <F extends Fields>(fields: F): SlotFnDef<F>;
153
153
  };
154
154
  readonly define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
155
+ readonly of: <D extends SlotsDef>(slotsSchema: SlotsSchema<D>, provided: ProvideSlots<D>) => SlotCalls<D>;
155
156
  };
156
157
  //#endregion
157
158
  export { HasSlotKeys, MachineContext, MachineContextTag, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema, define, fn };
package/v3/dist/slot.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Context, Schema } from "effect";
1
+ import { Context, Effect, Schema } from "effect";
2
2
  //#region src/slot.ts
3
3
  /**
4
4
  * Slot module — unified, schema-based parameterized slots.
@@ -122,9 +122,44 @@ const define = (definitions) => {
122
122
  }
123
123
  };
124
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
+ };
125
159
  const Slot = {
126
160
  fn,
127
- define
161
+ define,
162
+ of
128
163
  };
129
164
  //#endregion
130
165
  export { MachineContextTag, Slot, define, fn };