effect-machine 0.2.1 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-machine",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cevr/effect-machine.git"
package/src/actor.ts CHANGED
@@ -364,12 +364,14 @@ export const buildActorRefCore = <
364
364
  const waitFor = Effect.fn("effect-machine.actor.waitFor")(function* (
365
365
  predicate: (state: S) => boolean,
366
366
  ) {
367
- const current = yield* SubscriptionRef.get(stateRef);
368
- if (predicate(current)) {
369
- return current;
370
- }
371
- const next = yield* stateRef.changes.pipe(Stream.filter(predicate), Stream.runHead);
372
- return Option.getOrElse(next, () => current);
367
+ // Use stateRef.changes directly — it emits the current value as its first
368
+ // element inside the SubscriptionRef semaphore, so this is atomic and
369
+ // race-free (no gap between "check current" and "subscribe").
370
+ const result = yield* stateRef.changes.pipe(Stream.filter(predicate), Stream.runHead);
371
+ if (Option.isSome(result)) return result.value;
372
+ // Unreachable: changes always emits at least the current value.
373
+ // Fallback to snapshot for type completeness.
374
+ return yield* SubscriptionRef.get(stateRef);
373
375
  });
374
376
 
375
377
  const awaitFinal = waitFor((state) => machine.finalStates.has(state._tag)).pipe(
package/src/index.ts CHANGED
@@ -63,6 +63,7 @@ export type { SimulationResult, TestHarness, TestHarnessOptions } from "./testin
63
63
 
64
64
  // Inspection
65
65
  export type {
66
+ AnyInspectionEvent,
66
67
  EffectEvent,
67
68
  ErrorEvent,
68
69
  EventReceivedEvent,
package/src/inspection.ts CHANGED
@@ -82,6 +82,17 @@ export type InspectionEvent<S, E> =
82
82
  | ErrorEvent<S, E>
83
83
  | StopEvent<S>;
84
84
 
85
+ /**
86
+ * Convenience alias for untyped inspection events.
87
+ * Useful for general-purpose inspectors that don't need specific state/event types.
88
+ * State and event fields are typed as `{ readonly _tag: string }` so discriminated
89
+ * access to `_tag` works without casting.
90
+ */
91
+ export type AnyInspectionEvent = InspectionEvent<
92
+ { readonly _tag: string },
93
+ { readonly _tag: string }
94
+ >;
95
+
85
96
  // ============================================================================
86
97
  // Inspector Service
87
98
  // ============================================================================
@@ -101,9 +112,14 @@ export interface Inspector<S, E> {
101
112
  export const Inspector = Context.GenericTag<Inspector<any, any>>("@effect/machine/Inspector");
102
113
 
103
114
  /**
104
- * Create an inspector from a callback function
115
+ * Create an inspector from a callback function.
116
+ * Defaults to `AnyInspectionEvent` when type params are not provided,
117
+ * giving access to `_tag` on state/event fields without casts.
105
118
  */
106
- export const makeInspector = <S, E>(
119
+ export const makeInspector = <
120
+ S extends { readonly _tag: string } = { readonly _tag: string },
121
+ E extends { readonly _tag: string } = { readonly _tag: string },
122
+ >(
107
123
  onInspect: (event: InspectionEvent<S, E>) => void,
108
124
  ): Inspector<S, E> => ({ onInspect });
109
125
 
@@ -115,10 +131,10 @@ export const makeInspector = <S, E>(
115
131
  * Console inspector that logs events in a readable format
116
132
  */
117
133
  export const consoleInspector = <
118
- S extends { readonly _tag: string },
119
- E extends { readonly _tag: string },
134
+ S extends { readonly _tag: string } = { readonly _tag: string },
135
+ E extends { readonly _tag: string } = { readonly _tag: string },
120
136
  >(): Inspector<S, E> =>
121
- makeInspector((event) => {
137
+ makeInspector<S, E>((event) => {
122
138
  const prefix = `[${event.actorId}]`;
123
139
  switch (event.type) {
124
140
  case "@machine.spawn":
@@ -145,5 +161,9 @@ export const consoleInspector = <
145
161
  /**
146
162
  * Collecting inspector that stores events in an array for testing
147
163
  */
148
- export const collectingInspector = <S, E>(events: InspectionEvent<S, E>[]): Inspector<S, E> =>
149
- makeInspector((event) => events.push(event));
164
+ export const collectingInspector = <
165
+ S extends { readonly _tag: string },
166
+ E extends { readonly _tag: string },
167
+ >(
168
+ events: InspectionEvent<S, E>[],
169
+ ): Inspector<S, E> => makeInspector<S, E>((event) => events.push(event));