@mantaq/traversal 0.0.2 → 0.1.1

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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyActor, Context, Snapshot } from "@mantaq/core";
1
+ import { AnyActor, Context, Snapshot, TransitionInfo } from "@mantaq/core";
2
2
  //#region src/types.d.ts
3
3
  interface GraphNode {
4
4
  id: string;
@@ -49,7 +49,7 @@ interface HistoryEntry {
49
49
  //#region src/graph.d.ts
50
50
  declare const INITIAL_NODE_ID = "__initial__";
51
51
  declare function collectActiveStates(snapshot: Snapshot, prefix: string, activeSet: Set<string>): void;
52
- declare function buildGraph(actor: AnyActor, options?: {
52
+ declare function buildGraph<C>(actor: AnyActor<C>, options?: {
53
53
  internalIds?: Set<string>;
54
54
  sampleContext?: Record<string, unknown>;
55
55
  sampleContexts?: Record<string, Record<string, unknown>>;
@@ -73,21 +73,25 @@ declare class History {
73
73
  }
74
74
  //#endregion
75
75
  //#region src/instrument.d.ts
76
- interface InstrumentedActor {
76
+ interface InstrumentedActor<C = Record<string, unknown>> {
77
77
  history: History;
78
78
  send(event: unknown): void;
79
79
  state: AnyActor["state"];
80
- snapshot(): Snapshot<Record<string, unknown>>;
80
+ snapshot(): Snapshot<C>;
81
81
  regions: Record<string, AnyActor>;
82
- context?: Record<string, unknown>;
82
+ context?: C;
83
83
  clock: AnyActor["clock"];
84
- on(event: "change", fn: (snapshot: Snapshot<Record<string, unknown>>, prev: Snapshot<Record<string, unknown>>) => void): () => void;
85
- on(event: "error", fn: (error: unknown) => void): () => void;
84
+ on(event: "change", fn: (snapshot: Snapshot<C>, prev: Snapshot<C>) => void): () => void;
85
+ on(event: "transition", fn: (info: TransitionInfo) => void): () => void;
86
86
  on(event: "done", fn: () => void): () => void;
87
+ recover(target: {
88
+ state: AnyActor["state"];
89
+ context: C;
90
+ }): void;
87
91
  settled(): Promise<void>;
88
92
  options?: AnyActor["options"];
89
93
  }
90
- declare function instrument(actor: AnyActor): InstrumentedActor;
94
+ declare function instrument<C>(actor: AnyActor<C>): InstrumentedActor<C>;
91
95
  //#endregion
92
96
  //#region src/algorithms.d.ts
93
97
  declare function reachable(graph: ActorGraph, fromId: string, toId: string): boolean;
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ function collectActiveStates(snapshot, prefix, activeSet) {
8
8
  if (!currentName) return;
9
9
  const fullId = nodeId(prefix, currentName);
10
10
  activeSet.add(fullId);
11
- if (snapshot.regions && !snapshot.done) for (const [regionName, regionSnap] of Object.entries(snapshot.regions)) collectActiveStates(regionSnap, regionName, activeSet);
11
+ if (snapshot.regions && !snapshot.done && !snapshot.error) for (const [regionName, regionSnap] of Object.entries(snapshot.regions)) collectActiveStates(regionSnap, regionName, activeSet);
12
12
  }
13
13
  function nodeId(prefix, name) {
14
14
  return prefix ? `${prefix}.${name}` : name;
@@ -26,13 +26,16 @@ function buildNodesFromStates(states, activeSet, pathPrefix) {
26
26
  }
27
27
  function invokeHandler(handler, eventId, context, actor) {
28
28
  return Either.from(() => {
29
- const result = handler({ id: eventId }, {
29
+ const result = handler({
30
+ type: eventId,
31
+ payload: {}
32
+ }, {
30
33
  context: new Context(() => context, () => {}),
31
34
  actor
32
35
  });
33
36
  return {
34
37
  targetName: result?.state?.name,
35
- emitNames: result?.emit?.map((e) => e.id).filter((id) => Boolean(id)) ?? []
38
+ emitNames: result?.emit?.map((e) => e.type).filter((type) => Boolean(type)) ?? []
36
39
  };
37
40
  });
38
41
  }
@@ -220,11 +223,7 @@ function buildGraph(actor, options) {
220
223
  edges
221
224
  };
222
225
  }), (error) => {
223
- console.error("[mantaq/traversal] buildGraph failed:", error);
224
- return {
225
- nodes: [],
226
- edges: []
227
- };
226
+ throw error;
228
227
  }, (result) => result);
229
228
  }
230
229
  //#endregion
@@ -272,8 +271,8 @@ var History = class {
272
271
  };
273
272
  //#endregion
274
273
  //#region src/instrument.ts
275
- function wrapWithProxy(actor, hooks) {
276
- const { history, origSend, pendingEventId } = hooks;
274
+ function wrapWithProxy(actor, history) {
275
+ const origSend = actor.send.bind(actor);
277
276
  return {
278
277
  get history() {
279
278
  return history;
@@ -294,48 +293,45 @@ function wrapWithProxy(actor, hooks) {
294
293
  return actor.options;
295
294
  },
296
295
  send(event) {
297
- const { id: eventId } = trackSendEvent(history, event);
298
- pendingEventId.value = eventId;
299
- try {
300
- origSend(event);
301
- } finally {
302
- pendingEventId.value = void 0;
303
- }
296
+ trackSendEvent(history, event);
297
+ origSend(event);
304
298
  },
305
299
  snapshot() {
306
300
  return actor.snapshot();
307
301
  },
308
302
  on: actor.on.bind(actor),
303
+ recover: actor.recover.bind(actor),
309
304
  settled: actor.settled.bind(actor)
310
305
  };
311
306
  }
312
- function recordTransition(history, from, to, eventId) {
307
+ function recordTransition(history, rec) {
313
308
  history.append({
314
309
  type: "transition",
315
310
  data: {
316
- from,
317
- event: eventId,
318
- to,
311
+ from: rec.from,
312
+ event: rec.event,
313
+ to: rec.to,
319
314
  timestamp: Date.now()
320
315
  }
321
316
  });
317
+ if (!rec.transitioned) return;
322
318
  history.append({
323
319
  type: "state_visit",
324
320
  data: {
325
- stateName: to,
321
+ stateName: rec.to,
326
322
  timestamp: Date.now()
327
323
  }
328
324
  });
329
- history.append({
325
+ if ((rec.effects[rec.to] ?? []).length > 0) history.append({
330
326
  type: "effect",
331
327
  data: {
332
- stateName: to,
328
+ stateName: rec.to,
333
329
  timestamp: Date.now()
334
330
  }
335
331
  });
336
332
  }
337
333
  function trackSendEvent(history, event) {
338
- const eventId = event?.id ?? "unknown";
334
+ const eventId = event?.type ?? "unknown";
339
335
  history.append({
340
336
  type: "send",
341
337
  data: {
@@ -343,13 +339,9 @@ function trackSendEvent(history, event) {
343
339
  timestamp: Date.now()
344
340
  }
345
341
  });
346
- return { id: eventId };
347
342
  }
348
343
  function instrument(actor) {
349
344
  const history = new History();
350
- const origSend = actor.send.bind(actor);
351
- let prevStateName = actor.state.name;
352
- const pendingEventId = { value: void 0 };
353
345
  history.append({
354
346
  type: "state_visit",
355
347
  data: {
@@ -357,17 +349,16 @@ function instrument(actor) {
357
349
  timestamp: Date.now()
358
350
  }
359
351
  });
360
- const wrapped = wrapWithProxy(actor, {
361
- history,
362
- origSend,
363
- pendingEventId
364
- });
365
- actor.on("change", () => {
366
- const currentName = actor.state.name;
367
- if (currentName !== prevStateName) {
368
- recordTransition(history, prevStateName, currentName, pendingEventId.value ?? "unknown");
369
- prevStateName = currentName;
370
- }
352
+ const wrapped = wrapWithProxy(actor, history);
353
+ const effectsByState = actor.options?.effects ?? {};
354
+ actor.on("transition", ({ event, from, to, transitioned }) => {
355
+ recordTransition(history, {
356
+ from,
357
+ to,
358
+ event: event.type,
359
+ transitioned,
360
+ effects: effectsByState
361
+ });
371
362
  });
372
363
  return wrapped;
373
364
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mantaq/traversal",
3
- "version": "0.0.2",
3
+ "version": "0.1.1",
4
4
  "description": "Graph extraction, traversal algorithms, and runtime tracking for mantaq actors.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,8 +20,8 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "@mantaq/core": "0.0.2",
24
- "@mantaq/utils": "0.0.1"
23
+ "@mantaq/core": "0.2.0",
24
+ "@mantaq/utils": "0.0.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^26.2.0",