@nwire/hooks 0.7.1 → 0.8.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/dist/hook.d.ts CHANGED
@@ -5,30 +5,47 @@
5
5
  * attachments. `.run()` fires the chain first (sequential, can short-circuit),
6
6
  * then fires listeners in parallel via Promise.allSettled.
7
7
  *
8
- * Behavior matrix is locked by architecture-sketch.html §07.
8
+ * On top of that core, every hook is:
9
+ * - introspectable — listed by `listHooks()`, keyed by `id` + `name`
10
+ * - traceable — `.tap()` receives a StepObservation per phase
11
+ * - linked — nested runs auto-pick a `parentRunId`
12
+ * - source-located — `hook("x")` captures its call site
13
+ * - cancellable — `.run(ctx, { signal })` propagates an AbortSignal
14
+ * - prioritised — `.use(fn, { priority })` orders the chain
15
+ * - filterable — `.on(fn, { when: "success" | "failure" })`
16
+ * - replayable — `.runDetailed()` returns the full step trace
17
+ */
18
+ import type { ChainFn, HookOptions, ListenerFn, OnOptions, RunOptions, RunResult, TapFn, UseOptions } from "./types.js";
19
+ /**
20
+ * The public Hook surface.
21
+ *
22
+ * The signatures stay backward-compatible: `.use(fn)`, `.on(fn)`, `.run(ctx)`
23
+ * work exactly as before. Each method accepts new optional arguments —
24
+ * priority, name, when, signal — that opt into the richer behavior.
9
25
  */
10
- import type { ChainFn, HookOptions, ListenerFn } from "./types.js";
11
- /** The public Hook surface. See architecture-sketch.html §06. */
12
26
  export interface Hook<Ctx> {
13
27
  /** Hook name. Stable for logging + telemetry. */
14
28
  readonly name: string;
29
+ /** Process-wide unique id for this hook instance. */
30
+ readonly id: string;
15
31
  /** Attach a chain middleware (sequential, can short-circuit). */
16
- use(fn: ChainFn<Ctx>): this;
32
+ use(fn: ChainFn<Ctx>, opts?: UseOptions): this;
17
33
  /** Attach a listener (parallel, observes final ctx, cannot mutate). */
18
- on(fn: ListenerFn<Ctx>): this;
34
+ on(fn: ListenerFn<Ctx>, opts?: OnOptions): this;
19
35
  /** Detach a previously attached `.use()` or `.on()` fn. No-op if unknown. */
20
36
  off(fn: ChainFn<Ctx> | ListenerFn<Ctx>): this;
21
37
  /** Run the chain, then fire listeners. Returns the (possibly mutated) ctx. */
22
- run(ctx: Ctx): Promise<Ctx>;
38
+ run(ctx: Ctx, opts?: RunOptions): Promise<Ctx>;
39
+ /** Same as `.run()`, but returns the full observation trace + outcome. */
40
+ runDetailed(ctx: Ctx, opts?: RunOptions): Promise<RunResult<Ctx>>;
41
+ /** Subscribe to per-step observations. Returns an unsubscribe handle. */
42
+ tap(observer: TapFn): () => void;
43
+ /** Step counts — `{ chain, listeners }`. Used by the registry + tests. */
44
+ stepCounts(): {
45
+ readonly chain: number;
46
+ readonly listeners: number;
47
+ };
23
48
  }
24
- /**
25
- * Create a new hook.
26
- *
27
- * @example
28
- * const request = hook<RequestCtx>("http.request");
29
- * request.use(async (ctx, next) => { ctx.start = Date.now(); await next(); });
30
- * request.on(async (ctx) => { await analytics.track(ctx); });
31
- * await request.run(ctx);
32
- */
49
+ /** Create a new hook. */
33
50
  export declare function hook<Ctx>(name: string, options?: HookOptions<Ctx>): Hook<Ctx>;
34
51
  //# sourceMappingURL=hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAWhE,iEAAiE;AACjE,MAAM,WAAW,IAAI,CAAC,GAAG;IACvB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,iEAAiE;IACjE,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAE5B,uEAAuE;IACvE,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAE9B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAE9C,8EAA8E;IAC9E,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAW,CAAC,GAAG,CAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAEjF"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EAEV,SAAS,EAET,KAAK,EACL,UAAU,EACX,MAAM,SAAS,CAAC;AAIjB;;;;;;GAMG;AACH,MAAM,WAAW,IAAI,CAAC,GAAG;IACvB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,EAAI,MAAM,CAAC;IAEtB,iEAAiE;IACjE,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAE/C,uEAAuE;IACvE,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhD,6EAA6E;IAC7E,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAE9C,8EAA8E;IAC9E,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE/C,0EAA0E;IAC1E,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAElE,yEAAyE;IACzE,GAAG,CAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,IAAI,CAAC;IAEjC,0EAA0E;IAC1E,UAAU,IAAI;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,yBAAyB;AACzB,wBAAgB,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAW,CAAC,GAAG,CAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAKjF"}
package/dist/hook.js CHANGED
@@ -5,144 +5,244 @@
5
5
  * attachments. `.run()` fires the chain first (sequential, can short-circuit),
6
6
  * then fires listeners in parallel via Promise.allSettled.
7
7
  *
8
- * Behavior matrix is locked by architecture-sketch.html §07.
8
+ * On top of that core, every hook is:
9
+ * - introspectable — listed by `listHooks()`, keyed by `id` + `name`
10
+ * - traceable — `.tap()` receives a StepObservation per phase
11
+ * - linked — nested runs auto-pick a `parentRunId`
12
+ * - source-located — `hook("x")` captures its call site
13
+ * - cancellable — `.run(ctx, { signal })` propagates an AbortSignal
14
+ * - prioritised — `.use(fn, { priority })` orders the chain
15
+ * - filterable — `.on(fn, { when: "success" | "failure" })`
16
+ * - replayable — `.runDetailed()` returns the full step trace
9
17
  */
10
18
  import Emittery from "emittery";
11
19
  import { compose } from "./compose.js";
12
- /**
13
- * Internal emittery event name. We piggy-back on emittery for typed
14
- * subscription bookkeeping (and as the documented foundation of @nwire/hooks),
15
- * but we iterate listeners ourselves via a parallel Set so we can apply the
16
- * contract-mandated `Promise.allSettled` semantics — emittery's `.emit()`
17
- * uses Promise.all which fails fast on the first rejection.
18
- */
20
+ import { captureSourceLocation, nextHookId, nextRunId, registerHook, withRunContext, currentRun, } from "./registry.js";
19
21
  const RUN_EVENT = "__nwire_hooks_run__";
20
- /**
21
- * Create a new hook.
22
- *
23
- * @example
24
- * const request = hook<RequestCtx>("http.request");
25
- * request.use(async (ctx, next) => { ctx.start = Date.now(); await next(); });
26
- * request.on(async (ctx) => { await analytics.track(ctx); });
27
- * await request.run(ctx);
28
- */
22
+ /** Create a new hook. */
29
23
  export function hook(name, options = {}) {
30
- return new HookImpl(name, options);
24
+ const source = captureSourceLocation(2);
25
+ const h = new HookImpl(name, options);
26
+ registerHook(h, source);
27
+ return h;
31
28
  }
32
29
  class HookImpl {
33
30
  name;
31
+ id;
34
32
  chain = [];
35
- /** Iteration store — we run these in parallel via Promise.allSettled. */
36
- listeners = new Set();
37
- /** Bookkeeping mirror — emittery is the documented foundation. */
33
+ listeners = [];
38
34
  emitter = new Emittery();
39
- /** Map user fn → emittery-shaped adapter, for `.off()`. */
40
- adapters = new WeakMap();
35
+ taps = new Set();
36
+ stepCounter = 0;
41
37
  strictListeners;
42
38
  onListenerError;
43
39
  constructor(name, options) {
44
40
  this.name = name;
41
+ this.id = nextHookId();
45
42
  this.strictListeners = options.strictListeners === true;
46
43
  this.onListenerError =
47
44
  options.onListenerError ??
48
45
  ((err, _ctx, hookName) => {
49
- // Conservative default — log + continue. Hosts (createHooks)
50
- // override this to route through their `lifecycle.error` hook.
51
46
  // eslint-disable-next-line no-console
52
47
  console.error(`[@nwire/hooks] listener error in "${hookName}":`, err);
53
48
  });
54
49
  }
55
- use(fn) {
56
- this.chain.push(fn);
50
+ stepCounts() {
51
+ return { chain: this.chain.length, listeners: this.listeners.length };
52
+ }
53
+ use(fn, opts) {
54
+ const entry = {
55
+ fn,
56
+ stepId: this.stepCounter++,
57
+ name: opts?.name,
58
+ priority: opts?.priority ?? 0,
59
+ };
60
+ this.chain.push(entry);
61
+ // Higher priority runs first (outermost). Stable sort preserves insertion
62
+ // order for equal priorities.
63
+ this.chain.sort((a, b) => b.priority - a.priority || a.stepId - b.stepId);
57
64
  return this;
58
65
  }
59
- on(fn) {
60
- if (this.listeners.has(fn))
66
+ on(fn, opts) {
67
+ if (this.listeners.find((l) => l.fn === fn))
61
68
  return this;
62
- this.listeners.add(fn);
63
- const adapter = async (ctx) => {
64
- await fn(ctx);
69
+ const adapter = async (ctx) => { await fn(ctx); };
70
+ const entry = {
71
+ fn,
72
+ stepId: this.stepCounter++,
73
+ name: opts?.name,
74
+ priority: opts?.priority ?? 0,
75
+ when: opts?.when ?? "always",
76
+ adapter,
65
77
  };
66
- this.adapters.set(fn, adapter);
78
+ this.listeners.push(entry);
79
+ this.listeners.sort((a, b) => b.priority - a.priority || a.stepId - b.stepId);
67
80
  this.emitter.on(RUN_EVENT, adapter);
68
81
  return this;
69
82
  }
70
83
  off(fn) {
71
- // Try chain first.
72
- const chainIdx = this.chain.indexOf(fn);
84
+ const chainIdx = this.chain.findIndex((c) => c.fn === fn);
73
85
  if (chainIdx >= 0) {
74
86
  this.chain.splice(chainIdx, 1);
75
87
  return this;
76
88
  }
77
- // Otherwise treat as listener.
78
- const listenerFn = fn;
79
- if (this.listeners.delete(listenerFn)) {
80
- const adapter = this.adapters.get(listenerFn);
81
- if (adapter) {
82
- this.emitter.off(RUN_EVENT, adapter);
83
- this.adapters.delete(listenerFn);
84
- }
89
+ const listenerIdx = this.listeners.findIndex((l) => l.fn === fn);
90
+ if (listenerIdx >= 0) {
91
+ const entry = this.listeners[listenerIdx];
92
+ this.emitter.off(RUN_EVENT, entry.adapter);
93
+ this.listeners.splice(listenerIdx, 1);
85
94
  }
86
95
  return this;
87
96
  }
88
- async run(ctx) {
89
- // 1. Run the chain. If it throws, capture before listeners fire so they
90
- // can observe the failure mode via ctx.error.
91
- const composed = compose(this.chain);
92
- let chainError = undefined;
93
- try {
94
- await composed(ctx, async () => {
95
- // Tail — nothing to do. The chain itself decides whether to call
96
- // next() or short-circuit.
97
- });
98
- }
99
- catch (err) {
100
- chainError = err;
101
- // Stash on ctx so listeners can observe failure mode. Mutating even
102
- // when `Ctx` doesn't declare an `error` field is the documented
103
- // contract (§07 row 2 + row 11).
104
- ctx.error = err;
97
+ tap(observer) {
98
+ this.taps.add(observer);
99
+ return () => { this.taps.delete(observer); };
100
+ }
101
+ async run(ctx, opts) {
102
+ const result = await this.runDetailed(ctx, opts);
103
+ if (result.outcome === "failed" && result.error !== undefined) {
104
+ throw result.error;
105
105
  }
106
- // 2. Fire listeners in parallel via Promise.allSettled — contract row 4.
107
- if (this.listeners.size > 0) {
108
- const snapshot = Array.from(this.listeners);
109
- const results = await Promise.allSettled(snapshot.map(async (listener) => listener(ctx)));
110
- const failures = results.filter((r) => r.status === "rejected");
111
- if (failures.length > 0) {
112
- if (this.strictListeners) {
113
- // Strict mode: opt-in escape hatch (§07 closing note). Surface
114
- // the first failure; attach the rest via `cause` for debug.
115
- const primary = failures[0].reason;
116
- if (failures.length > 1 &&
117
- primary instanceof Error &&
118
- primary.cause === undefined) {
119
- Object.defineProperty(primary, "cause", {
120
- value: failures.slice(1).map((f) => f.reason),
121
- configurable: true,
122
- writable: true,
123
- });
124
- }
125
- throw primary;
126
- }
127
- // Default mode: report each, never fail the run.
128
- for (const failure of failures) {
129
- try {
130
- this.onListenerError(failure.reason, ctx, this.name);
131
- }
132
- catch {
133
- // Reporter itself blew up — swallow. Listener-error reporting
134
- // must never crash the hook.
135
- }
106
+ return result.ctx;
107
+ }
108
+ async runDetailed(ctx, opts) {
109
+ const runId = nextRunId();
110
+ const parentRunId = opts?.parentRunId ?? currentRun()?.runId;
111
+ const signal = opts?.signal;
112
+ const steps = [];
113
+ const startedAt = nowMs();
114
+ const emit = (obs) => {
115
+ steps.push(obs);
116
+ for (const tap of this.taps) {
117
+ try {
118
+ tap(obs);
136
119
  }
120
+ catch { /* tap throws are swallowed */ }
121
+ }
122
+ };
123
+ // Inject abort signal onto ctx (only if ctx is an object). Domain code
124
+ // can read `ctx.signal` to bail early. We don't overwrite a user-provided
125
+ // signal on ctx; user wins.
126
+ if (signal && ctx && typeof ctx === "object" && !ctx.signal) {
127
+ ctx.signal = signal;
128
+ }
129
+ const composed = compose(this.chain.map((entry) => wrapChain(this, entry, runId, parentRunId, signal, emit)));
130
+ // A chain step that doesn't call its `next()` short-circuits — the tail
131
+ // is the only place that *reliably* signals "every step yielded down to
132
+ // me." We toggle a flag inside the tail; if it stays false after the
133
+ // compose resolves without throwing, the chain was prevented.
134
+ let chainError = undefined;
135
+ let reachedTail = false;
136
+ await withRunContext({ runId, hookId: this.id, parentRunId }, async () => {
137
+ try {
138
+ await composed(ctx, async () => { reachedTail = true; });
139
+ }
140
+ catch (err) {
141
+ chainError = err;
142
+ ctx.error = err;
143
+ }
144
+ });
145
+ // Empty chain — nothing to short-circuit, treat as completed.
146
+ if (this.chain.length === 0)
147
+ reachedTail = true;
148
+ const outcome = chainError !== undefined ? "failed" : reachedTail ? "completed" : "prevented";
149
+ await this.fireListeners(ctx, outcome, runId, parentRunId, emit);
150
+ return {
151
+ ctx,
152
+ outcome,
153
+ runId,
154
+ parentRunId,
155
+ steps,
156
+ durationMs: nowMs() - startedAt,
157
+ error: chainError,
158
+ };
159
+ }
160
+ async fireListeners(ctx, outcome, runId, parentRunId, emit) {
161
+ const eligible = this.listeners.filter((l) => {
162
+ if (l.when === "always")
163
+ return true;
164
+ if (l.when === "success")
165
+ return outcome === "completed";
166
+ if (l.when === "failure")
167
+ return outcome === "failed";
168
+ return true;
169
+ });
170
+ if (eligible.length === 0)
171
+ return;
172
+ const results = await Promise.allSettled(eligible.map(async (entry) => {
173
+ const startTs = nowMs();
174
+ emit(makeObs(this, entry.stepId, "listener", entry.name, "start", startTs, runId, parentRunId));
175
+ try {
176
+ await entry.fn(ctx);
177
+ emit(makeObs(this, entry.stepId, "listener", entry.name, "end", nowMs(), runId, parentRunId, nowMs() - startTs));
178
+ }
179
+ catch (err) {
180
+ emit(makeObs(this, entry.stepId, "listener", entry.name, "error", nowMs(), runId, parentRunId, nowMs() - startTs, err));
181
+ throw err;
182
+ }
183
+ }));
184
+ const failures = results.filter((r) => r.status === "rejected");
185
+ if (failures.length === 0)
186
+ return;
187
+ if (this.strictListeners) {
188
+ const primary = failures[0].reason;
189
+ if (failures.length > 1 &&
190
+ primary instanceof Error &&
191
+ primary.cause === undefined) {
192
+ Object.defineProperty(primary, "cause", {
193
+ value: failures.slice(1).map((f) => f.reason),
194
+ configurable: true,
195
+ writable: true,
196
+ });
137
197
  }
198
+ throw primary;
138
199
  }
139
- // 3. Propagate chain failure to the caller of `.run()`. Listeners have
140
- // already observed it via ctx.error; this is the actionable signal
141
- // for whatever called the hook.
142
- if (chainError !== undefined) {
143
- throw chainError;
200
+ for (const f of failures) {
201
+ try {
202
+ this.onListenerError(f.reason, ctx, this.name);
203
+ }
204
+ catch { /* reporter blew up — swallow */ }
144
205
  }
145
- return ctx;
146
206
  }
147
207
  }
208
+ // ─── Helpers ──────────────────────────────────────────────────────────
209
+ function wrapChain(hook, entry, runId, parentRunId, signal, emit) {
210
+ return async function instrumented(ctx, next) {
211
+ if (signal?.aborted) {
212
+ throw signal.reason ?? new Error("hook aborted");
213
+ }
214
+ const startTs = nowMs();
215
+ emit(makeObs(hook, entry.stepId, "chain", entry.name, "start", startTs, runId, parentRunId));
216
+ try {
217
+ await entry.fn(ctx, next);
218
+ const endTs = nowMs();
219
+ emit(makeObs(hook, entry.stepId, "chain", entry.name, "end", endTs, runId, parentRunId, endTs - startTs));
220
+ }
221
+ catch (err) {
222
+ const endTs = nowMs();
223
+ emit(makeObs(hook, entry.stepId, "chain", entry.name, "error", endTs, runId, parentRunId, endTs - startTs, err));
224
+ throw err;
225
+ }
226
+ };
227
+ }
228
+ function makeObs(hook, stepId, stepKind, stepName, phase, ts, runId, parentRunId, durationMs, error) {
229
+ return {
230
+ hookName: hook.name,
231
+ hookId: hook.id,
232
+ runId,
233
+ parentRunId,
234
+ stepId,
235
+ stepKind,
236
+ stepName,
237
+ phase,
238
+ ts,
239
+ durationMs,
240
+ error,
241
+ };
242
+ }
243
+ // performance.now() is available in Node 16+; fall back to Date.now() only
244
+ // if a host VM lacks it (vitest can stub it).
245
+ const nowMs = typeof performance !== "undefined" && typeof performance.now === "function"
246
+ ? () => performance.now()
247
+ : () => Date.now();
148
248
  //# sourceMappingURL=hook.js.map
package/dist/hook.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  /**
2
- * @nwire/hooks — the universal dispatch primitive
2
+ * @nwire/hooks — the universal dispatch primitive.
3
3
  *
4
- * One `hook()` accepts BOTH `.use()` (chain) and `.on()` (parallel listener)
5
- * attachments. Chain runs first (sequential, can short-circuit), then listeners
6
- * fire in parallel via Promise.allSettled. See architecture-sketch.html §06–§07.
4
+ * One `hook()` accepts both `.use()` (chain middleware) and `.on()` (parallel
5
+ * listener) attachments. Every run is observable end-to-end via `.tap()`,
6
+ * yields a runId that links nested runs into a topology tree, and can be
7
+ * recorded for replay.
8
+ *
9
+ * See README.md for the full contract + recipes.
7
10
  */
8
11
  export { hook, type Hook } from "./hook.js";
9
12
  export { createHooks, type Host, type HookMap, type Plugin, type PluginEntry, } from "./create-hooks.js";
10
13
  export { compose } from "./compose.js";
11
14
  export { pipe, withTimeout, withRetry } from "./pipe.js";
12
- export type { ChainFn, HookOptions, ListenerFn, RetryOpts } from "./types.js";
15
+ export { record, replay, type RecordOptions, type ReplayResult } from "./record.js";
16
+ export { listHooks, currentRun, captureSourceLocation, } from "./registry.js";
17
+ export type { ChainFn, HookOptions, ListenerFn, OnOptions, Recording, RetryOpts, RunOptions, RunOutcome, RunResult, SourceLocation, StepKind, StepObservation, StepPhase, TapFn, UseOptions, } from "./types.js";
13
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,WAAW,EACX,KAAK,IAAI,EACT,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACtD,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,WAAW,EACX,KAAK,IAAI,EACT,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EACL,SAAS,EACT,UAAU,EACV,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,SAAS,EACT,KAAK,EACL,UAAU,GACX,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,12 +1,17 @@
1
1
  /**
2
- * @nwire/hooks — the universal dispatch primitive
2
+ * @nwire/hooks — the universal dispatch primitive.
3
3
  *
4
- * One `hook()` accepts BOTH `.use()` (chain) and `.on()` (parallel listener)
5
- * attachments. Chain runs first (sequential, can short-circuit), then listeners
6
- * fire in parallel via Promise.allSettled. See architecture-sketch.html §06–§07.
4
+ * One `hook()` accepts both `.use()` (chain middleware) and `.on()` (parallel
5
+ * listener) attachments. Every run is observable end-to-end via `.tap()`,
6
+ * yields a runId that links nested runs into a topology tree, and can be
7
+ * recorded for replay.
8
+ *
9
+ * See README.md for the full contract + recipes.
7
10
  */
8
11
  export { hook } from "./hook.js";
9
12
  export { createHooks, } from "./create-hooks.js";
10
13
  export { compose } from "./compose.js";
11
14
  export { pipe, withTimeout, withRetry } from "./pipe.js";
15
+ export { record, replay } from "./record.js";
16
+ export { listHooks, currentRun, captureSourceLocation, } from "./registry.js";
12
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,WAAW,GAKZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,WAAW,GAKZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAyC,MAAM,UAAU,CAAC;AACjF,OAAO,EACL,SAAS,EACT,UAAU,EACV,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Recording + replay.
3
+ *
4
+ * Recording a hook run produces a {@link Recording} — the full step trace
5
+ * plus user-supplied ctx snapshots taken before and after. Replays the
6
+ * recording later (or in another process) and assert step-by-step shape
7
+ * matches. This is the substrate Studio's "replay this trace" button and
8
+ * the deterministic debug flow are built on.
9
+ *
10
+ * Two scopes:
11
+ *
12
+ * record(hook, ctx, opts?) one-shot: run the hook, snapshot ctx, return Recording
13
+ * replay(hook, recording, opts) re-run with the recorded ctxIn; compare shapes
14
+ *
15
+ * The clone strategy is pluggable; default is `structuredClone`. Pass
16
+ * `clone: (x) => JSON.parse(JSON.stringify(x))` for non-clonable shapes.
17
+ */
18
+ import type { Hook } from "./hook.js";
19
+ import type { Recording, RunOptions } from "./types.js";
20
+ export interface RecordOptions extends RunOptions {
21
+ /** Custom ctx-cloner for snapshotting. Default: `structuredClone`. */
22
+ readonly clone?: <T>(ctx: T) => T;
23
+ }
24
+ /**
25
+ * Run the hook once, capture ctx-in/out + every observation. Result is a
26
+ * self-contained {@link Recording} that can be persisted (JSON-safe if the
27
+ * caller's clone yields JSON-safe shapes), shipped to Studio, or fed back
28
+ * into `replay()`.
29
+ */
30
+ export declare function record<Ctx>(hook: Hook<Ctx>, ctx: Ctx, opts?: RecordOptions): Promise<Recording>;
31
+ /** Comparison result returned by {@link replay}. */
32
+ export interface ReplayResult<Ctx> {
33
+ readonly matches: boolean;
34
+ readonly drift: ReadonlyArray<string>;
35
+ readonly recorded: Recording;
36
+ readonly replayed: {
37
+ readonly ctx: Ctx;
38
+ readonly stepCount: number;
39
+ readonly outcome: string;
40
+ };
41
+ }
42
+ /**
43
+ * Replay a recording. Re-runs the hook with `recording.ctxIn` (cloned),
44
+ * compares the resulting step sequence + outcome against the recording,
45
+ * and reports drift. This is observational — it does not stub side effects.
46
+ * Pure / idempotent chains should match; non-deterministic chains report
47
+ * their drift so a human can decide whether it's expected.
48
+ */
49
+ export declare function replay<Ctx>(hook: Hook<Ctx>, recording: Recording, opts?: RecordOptions): Promise<ReplayResult<Ctx>>;
50
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;CACnC;AAQD;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EACf,GAAG,EAAE,GAAG,EACR,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,SAAS,CAAC,CAepB;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY,CAAC,GAAG;IAC/B,QAAQ,CAAC,OAAO,EAAG,OAAO,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAK,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAChG;AAED;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EACf,SAAS,EAAE,SAAS,EACpB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAoC5B"}