nanoeffects 0.31.2 → 0.33.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/{action-creator-6rlBTmH9.d.ts → action-creator-DprJV-pN.d.ts} +6 -2
- package/dist/actions.d.ts +3 -3
- package/dist/actions.js +1 -1
- package/dist/{bus-DFlmNJ6h.js → bus-Cmk4U1hQ.js} +1 -1
- package/dist/caller-DULg_ZYV.js +1 -0
- package/dist/context-Dp_QRXzb.js +1 -0
- package/dist/{context-types-DKNc5mkS.d.ts → context-types-BiTMp_lW.d.ts} +1 -1
- package/dist/context.d.ts +2 -2
- package/dist/dev.d.ts +2 -2
- package/dist/dev.js +2 -2
- package/dist/effects.d.ts +2 -2
- package/dist/effects.js +1 -1
- package/dist/guard.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/match.d.ts +1 -1
- package/dist/match.js +1 -1
- package/dist/{module-G39MaVOt.d.ts → module-DPKjzfRk.d.ts} +2 -2
- package/dist/notrace/{action-creator-BrMSO3RP.d.ts → action-creator-BWd9FWt6.d.ts} +2 -2
- package/dist/notrace/actions.d.ts +2 -2
- package/dist/notrace/actions.js +1 -1
- package/dist/notrace/effects.d.ts +2 -2
- package/dist/notrace/index.d.ts +1 -1
- package/dist/notrace/{plugin-7GUL2EW5.d.ts → plugin-DmAYT3Xk.d.ts} +1 -1
- package/dist/notrace/policies.d.ts +1 -1
- package/dist/notrace/redux.d.ts +1 -1
- package/dist/observable.d.ts +1 -1
- package/dist/oop.d.ts +1 -1
- package/dist/oop.js +1 -1
- package/dist/{plugin-BWNP23hr.d.ts → plugin-2d3uuW7o.d.ts} +2 -2
- package/dist/policies.d.ts +2 -2
- package/dist/policies.js +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/redux.d.ts +1 -1
- package/dist/scope.d.ts +2 -2
- package/dist/signal.d.ts +2 -2
- package/dist/signal.js +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/testing.d.ts +80 -0
- package/dist/testing.js +1 -0
- package/dist/trace.d.ts +227 -44
- package/dist/trace.js +3 -3
- package/dist/tracer-v7m-Qah_.js +2 -0
- package/dist/{types-N_cdRr1r.d.ts → types-DxPZDzZG.d.ts} +2 -2
- package/dist/vue.d.ts +1 -1
- package/dist/{with-policy-CeM1rtES.js → with-policy-BmL0eRU3.js} +1 -1
- package/dist/{with-policy-CthiBp_z.d.ts → with-policy-Y12d-yx6.d.ts} +1 -1
- package/docs/debugging-cases.md +122 -0
- package/docs/debugging-loops.md +79 -0
- package/docs/migrating-from-rxjs.md +1 -1
- package/docs/package.md +2 -1
- package/docs/recipes.md +35 -0
- package/docs/ru/debugging-cases.md +122 -0
- package/docs/ru/debugging-loops.md +79 -0
- package/docs/ru/migrating-from-rxjs.md +1 -1
- package/docs/ru/package.md +2 -1
- package/docs/ru/recipes.md +35 -0
- package/docs/ru/testing.md +92 -0
- package/docs/ru/tracing.md +189 -3
- package/docs/testing.md +92 -0
- package/docs/tracing.md +189 -3
- package/llms-full.txt +528 -5
- package/llms.txt +4 -2
- package/package.json +12 -3
- package/dist/context-B5Z2RpJt.js +0 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { H as EventMap, v as Bus, y as BusOptions } from "./action-creator-DprJV-pN.js";
|
|
2
|
+
//#region src/testing/clock.d.ts
|
|
3
|
+
/** What the runner needs from time: move it forward, and read it. */
|
|
4
|
+
type Clock = {
|
|
5
|
+
/** Moves time forward by `ms` and lets the timers and the promises of that time run. */
|
|
6
|
+
advance(ms: number): void | Promise<void>;
|
|
7
|
+
/** The time now, in milliseconds. */
|
|
8
|
+
now(): number;
|
|
9
|
+
};
|
|
10
|
+
/** The part of `vi` (Vitest) and `jest` (Jest) that `fakeTimersClock` uses. */
|
|
11
|
+
type FakeTimers = {
|
|
12
|
+
advanceTimersByTimeAsync(ms: number): Promise<unknown>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A clock over fake timers. The test turns them on itself (`vi.useFakeTimers()`), and leaves `Date`
|
|
16
|
+
* faked, which is the default, because the clock reads `Date.now()`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { vi } from "vitest";
|
|
21
|
+
* import { fakeTimersClock } from "nanoeffects/testing";
|
|
22
|
+
*
|
|
23
|
+
* vi.useFakeTimers();
|
|
24
|
+
* const clock = fakeTimersClock(vi);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const fakeTimersClock: (timers: FakeTimers) => Clock;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/testing/runner.d.ts
|
|
30
|
+
type MarbleOptions<E extends EventMap> = Omit<BusOptions<E>, "trace"> & {
|
|
31
|
+
/** Moves time and tells it. `fakeTimersClock(vi)` is one. */
|
|
32
|
+
clock: Clock;
|
|
33
|
+
/** The length of a frame in milliseconds. Default 10. */
|
|
34
|
+
frame?: number;
|
|
35
|
+
};
|
|
36
|
+
/** What to emit for one event: a diagram, and the value of each character (the character itself by default). */
|
|
37
|
+
type EmitMarble = {
|
|
38
|
+
marble: string;
|
|
39
|
+
values?: Record<string, unknown>;
|
|
40
|
+
};
|
|
41
|
+
type RunOptions = {
|
|
42
|
+
/** Event name → what to emit. */
|
|
43
|
+
emits?: Record<string, EmitMarble>;
|
|
44
|
+
/** How many frames to run. Default: the length of the longest diagram of `emits`. */
|
|
45
|
+
frames?: number;
|
|
46
|
+
};
|
|
47
|
+
type MarbleResult = {
|
|
48
|
+
/** The number of frames that were run. */
|
|
49
|
+
frames: number;
|
|
50
|
+
/** The phases of every traced task as diagrams, by `type:effect`. */
|
|
51
|
+
rows(): Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* Throws when a row differs, with both diagrams. A key with `:` is one row (`search:run`), a key
|
|
54
|
+
* without it is the effect (`latest`) and must match one row. Returns the result.
|
|
55
|
+
*/
|
|
56
|
+
expect(expected: Record<string, string>): MarbleResult;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* A bus that records its trace, and a `run` that moves time frame by frame, emits what the
|
|
60
|
+
* diagrams say at the start of each frame, and gives the phases of the tasks back as diagrams.
|
|
61
|
+
* Register the listeners on `bus`, then `run`. It needs a tracer, so there is no `notrace` build.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const marbles = createMarbleBus({ clock: fakeTimersClock(vi) });
|
|
66
|
+
* marbles.bus.on("search/changed", latest(search), { traceId: "search" });
|
|
67
|
+
*
|
|
68
|
+
* const result = await marbles.run({
|
|
69
|
+
* emits: { "search/changed": { marble: "a-b---", values: { a: "x", b: "xy" } } },
|
|
70
|
+
* frames: 12,
|
|
71
|
+
* });
|
|
72
|
+
* result.expect({ latest: "s-c-d-" });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare const createMarbleBus: <E extends EventMap = EventMap>(options: MarbleOptions<E>) => {
|
|
76
|
+
bus: Bus<E>;
|
|
77
|
+
run: ({ emits, frames }?: RunOptions) => Promise<MarbleResult>;
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export type { Clock, EmitMarble, FakeTimers, MarbleOptions, MarbleResult, RunOptions };
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./bus-Cmk4U1hQ.js";import{n as t,t as n}from"./tracer-v7m-Qah_.js";const r=e=>({advance:t=>e.advanceTimersByTimeAsync(t).then(()=>{}),now:()=>Date.now()}),i={start:`s`,done:`d`,error:`e`,cancel:`c`,drop:`x`},a=new Set(Object.values(i)),o=e=>i[e],s=(e,t,n)=>{throw Error(`marble "${e}": ${n} at position ${t}`)},c=(e,t,n)=>{for(let r=0;r<n.length;r+=1){let i=n.charAt(r);(/\s/.test(i)||i===`|`)&&s(e,t+r,`"${i.trim()||`space`}" is not part of a diagram`)}},l=(e,t)=>{let n=e.indexOf(`)`,t);n<0&&s(e,t,`a group that is not closed with ")"`);let r=e.slice(t+1,n);r===``&&s(e,t,`an empty group`);let i=r.indexOf(`(`);i>=0&&s(e,t+1+i,`a group inside a group`);let a=r.indexOf(`-`);return a>=0&&s(e,t+1+a,`"-" inside a group`),c(e,t+1,r),{frame:[...r],next:n+1}},u=(e,t)=>{let n=e.charAt(t);return n===`(`?l(e,t):(n===`)`&&s(e,t,`")" without "("`),c(e,t,n),{frame:n===`-`?[]:[n],next:t+1})},d=e=>{let t=[],n=0;for(;n<e.length;){let{frame:r,next:i}=u(e,n);t.push(r),n=i}return t},f=e=>{let t=d(e),n=0;for(let r of t){for(let t of r)a.has(t)||s(e,n,`"${t}" is not a phase (s d e c x)`);n+=r.length||1}return t},p=(e,t)=>{let n=``;for(let r=0;r<t;r+=1){let t=e[r]??[];t.length===0?n+=`-`:t.length===1?n+=t[0]:n+=`(${t.join(``)})`}return n},m=(e,t)=>e&&Object.hasOwn(e,t)?e[t]:t,h=(e,t,n,r,i)=>{let a=Array.from({length:i},()=>[]);for(let o of e){let e=Math.floor((o.at-n)/r);o.key===t&&e>=0&&e<i&&a[e]?.push(o.letter)}return a},g=(e,t)=>t.includes(`:`)?e.includes(t)?[t]:[]:e.filter(e=>e.endsWith(`:${t}`)),_=(e,t,n)=>`marble row "${e}" differs\n expected ${t}\n received ${n}`,v=(e,t,n,r)=>{let i=[...new Set(e.map(e=>e.key))],a=()=>Object.fromEntries(i.map(i=>[i,p(h(e,i,t,n,r),r)])),o={frames:r,rows:a,expect:e=>{let t=a();for(let[n,a]of Object.entries(e)){let e=g(i,n),[o]=e;if(o===void 0)throw Error(`marble row "${n}" matches no task; rows: ${i.join(`, `)||`none`}`);if(e.length>1)throw Error(`marble row "${n}" matches more than one task (${e.join(`, `)}): give the full key`);let s=p(f(a),r);if(s!==t[o])throw Error(_(o,s,t[o]??``))}return o}};return o},y=r=>{let{clock:i,frame:a=10,...s}=r,c=[],l=e=>{e.effect!==`emit`&&c.push({key:`${e.type}:${e.effect}`,letter:o(e.phase),at:i.now()})},u=e({...s,trace:n(l)});return u.use(t()),{bus:u,run:async({emits:e={},frames:t}={})=>{let n=Object.entries(e).map(([e,t])=>({event:e,frames:d(t.marble),values:t.values})),r=t??Math.max(0,...n.map(e=>e.frames.length));c.length=0;let o=i.now();for(let e=0;e<r;e+=1){for(let t of n)for(let n of t.frames[e]??[])Reflect.apply(u.emit,u,[t.event,m(t.values,n)]);await i.advance(a)}return v(c,o,a,r)}}};export{y as createMarbleBus,r as fakeTimersClock};
|
package/dist/trace.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as Tracer, H as EventMap, J as TaskInfo, K as Phase, V as EffectName, X as TraceEvent, Y as Trace, Z as TraceLogger, v as Bus } from "./action-creator-
|
|
1
|
+
import { B as Tracer, H as EventMap, J as TaskInfo, K as Phase, V as EffectName, X as TraceEvent, Y as Trace, Z as TraceLogger, v as Bus } from "./action-creator-DprJV-pN.js";
|
|
2
2
|
//#region src/graph/serialize.d.ts
|
|
3
3
|
type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
4
4
|
[key: string]: JsonValue;
|
|
@@ -136,12 +136,151 @@ type GraphLogger = TraceLogger & {
|
|
|
136
136
|
*/
|
|
137
137
|
export declare const graphLogger: (options?: GraphLoggerOptions) => GraphLogger;
|
|
138
138
|
//#endregion
|
|
139
|
+
//#region src/graph/merge.d.ts
|
|
140
|
+
/**
|
|
141
|
+
* Joins the graphs of several runs (tests, e2e, a manual session) into one, so a
|
|
142
|
+
* listener or an edge that no single run reached can still be seen by another.
|
|
143
|
+
* Counts add up, nodes and edges are the union, and a cycle found twice is one
|
|
144
|
+
* cycle. The snapshots you pass are not changed.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { mergeGraphs } from "nanoeffects/trace";
|
|
149
|
+
*
|
|
150
|
+
* // each run wrote `graph.toJSON()` to a file
|
|
151
|
+
* const all = mergeGraphs(unitRun, e2eRun);
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare const mergeGraphs: (...snapshots: GraphSnapshot[]) => GraphSnapshot;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/graph/orphans.d.ts
|
|
157
|
+
/**
|
|
158
|
+
* A listener that the graph never saw run. `unemitted`: the graph has no node for
|
|
159
|
+
* the event, so nobody emitted it. `unrun`: the event was emitted, this listener
|
|
160
|
+
* did not run.
|
|
161
|
+
*/
|
|
162
|
+
type Orphan = {
|
|
163
|
+
event: string;
|
|
164
|
+
listener: string;
|
|
165
|
+
kind: "unemitted" | "unrun";
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Compares the listeners a bus has with the graph of what ran, and lists the
|
|
169
|
+
* listeners the graph never saw. Pass `describeBus(bus)` (with or without `source`) and
|
|
170
|
+
* `graph.toJSON()`, or the result of `mergeGraphs` for wider coverage. A listener
|
|
171
|
+
* is a node of the graph once it has run, by its `traceId` or function name;
|
|
172
|
+
* anonymous listeners have no node and are left out. One run shows many false
|
|
173
|
+
* orphans: read the list as a hint, not as a failure.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { describeBus, findOrphans } from "nanoeffects/trace";
|
|
178
|
+
*
|
|
179
|
+
* const described = describeBus(bus);
|
|
180
|
+
* const orphans = findOrphans(described, graph.toJSON());
|
|
181
|
+
* // [{ event: "cart/cleared", listener: "reset", kind: "unemitted" }]
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export declare const findOrphans: (described: Readonly<Record<string, readonly string[]>>, snapshot: GraphSnapshot) => Orphan[];
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/trace/task-index.d.ts
|
|
187
|
+
/** What the `task` hook told about one task, also a task that reports no event. */
|
|
188
|
+
type KnownTask = {
|
|
189
|
+
type: string;
|
|
190
|
+
parentId?: number;
|
|
191
|
+
source?: string;
|
|
192
|
+
traceGroupId?: string;
|
|
193
|
+
};
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/trace/recorder.d.ts
|
|
196
|
+
type Recorder<E = Record<string, unknown>> = TraceLogger<E> & {
|
|
197
|
+
/**
|
|
198
|
+
* The events received so far, oldest first. Without a `capacity` it is one
|
|
199
|
+
* live array; with one, each read is a new array that is a snapshot.
|
|
200
|
+
*/
|
|
201
|
+
readonly events: TraceEvent<E>[];
|
|
202
|
+
/**
|
|
203
|
+
* The tasks the tracer told about, by `id`, also the ones that report no event (a plain
|
|
204
|
+
* listener). `chainOf` reads them to keep a path whole. Cut by `capacity` like `events`.
|
|
205
|
+
*/
|
|
206
|
+
readonly tasks: ReadonlyMap<number, KnownTask>;
|
|
207
|
+
clear: () => void;
|
|
208
|
+
/**
|
|
209
|
+
* The events as plain data that `JSON.stringify` takes: the payload and the error are made safe, so a
|
|
210
|
+
* circular object, an `Error`, a `Map` or a class instance cannot break it. `JSON.stringify(recorder)` uses it.
|
|
211
|
+
*/
|
|
212
|
+
toJSON: () => JsonValue[];
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Trace logger that keeps events in memory. With no option it keeps all of
|
|
216
|
+
* them, for tests. With `capacity` it keeps the last events, to send when
|
|
217
|
+
* something goes wrong.
|
|
218
|
+
*
|
|
219
|
+
* `payload` and `error` are kept as they are, and can hold private data: cut
|
|
220
|
+
* what you send. An event has no time, and a `parentId` can name an event that
|
|
221
|
+
* was pushed out: read it as a root.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```ts
|
|
225
|
+
* const recorder = createTraceRecorder<Events>();
|
|
226
|
+
* const bus = createBus<Events>({ trace: createTracer(recorder) });
|
|
227
|
+
*
|
|
228
|
+
* bus.emit("search", "re");
|
|
229
|
+
* bus.emit("search", "redux");
|
|
230
|
+
* recorder.events.map((e) => e.phase); // ["start", "cancel", "start", "done"]
|
|
231
|
+
*
|
|
232
|
+
* const lastEvents = createTraceRecorder<Events>({ capacity: 500 });
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export declare const createTraceRecorder: <E = Record<string, unknown>>(
|
|
236
|
+
/** `capacity`: keep the last N events (a ring buffer); not a positive integer, or left out: keep all. */
|
|
237
|
+
options?: {
|
|
238
|
+
capacity?: number;
|
|
239
|
+
}) => Recorder<E>;
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/trace/chain.d.ts
|
|
242
|
+
/** One task on the way from the root to the task you asked about. */
|
|
243
|
+
type ChainStep = {
|
|
244
|
+
id: number;
|
|
245
|
+
type: string;
|
|
246
|
+
/** Absent for a task that reported no event (a plain listener). */
|
|
247
|
+
effect?: EffectName;
|
|
248
|
+
/** The latest phase of the task; absent when it reported no event. */
|
|
249
|
+
phase?: Phase;
|
|
250
|
+
source?: string;
|
|
251
|
+
traceGroupId?: string;
|
|
252
|
+
};
|
|
253
|
+
type ChainSource<E> = readonly TraceEvent<E>[] | Pick<Recorder<E>, "events" | "tasks">;
|
|
254
|
+
/**
|
|
255
|
+
* The causal path of a task: the tasks that led to it, from the root, ending
|
|
256
|
+
* with the task itself. Use it to answer "what started the task that failed".
|
|
257
|
+
*
|
|
258
|
+
* Give it a recorder to keep the listeners that report no event in the path;
|
|
259
|
+
* a plain list of events (a snapshot, a file read back) shows only the tasks
|
|
260
|
+
* that have events.
|
|
261
|
+
*
|
|
262
|
+
* A parent that is not known (pushed out by a `capacity`) ends the path:
|
|
263
|
+
* it starts at the oldest task that is known. An unknown `id` gives `[]`.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* const failed = recorder.events.find((event) => event.phase === "error");
|
|
268
|
+
* const path = chainOf(recorder, failed.id);
|
|
269
|
+
* path.map((step) => step.type).join(" → "); // "queryChanged → searchLoaded"
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
export declare const chainOf: <E = Record<string, unknown>>(source: ChainSource<E>, id: number) => ChainStep[];
|
|
273
|
+
//#endregion
|
|
139
274
|
//#region src/trace/console.d.ts
|
|
140
275
|
type ConsoleLoggerOptions = {
|
|
141
276
|
/** Defaults to `globalThis.console`. */
|
|
142
277
|
console?: Pick<Console, "debug" | "error">;
|
|
143
278
|
/** Prepended to every line. */
|
|
144
279
|
prefix?: string;
|
|
280
|
+
/** Append where the listener was registered, to the lines of events that have it. Default `false`. */
|
|
281
|
+
source?: boolean;
|
|
282
|
+
/** Append the path from the root, with the listeners that report nothing, to the line of an `error`. Default `false`. */
|
|
283
|
+
chain?: boolean;
|
|
145
284
|
};
|
|
146
285
|
/**
|
|
147
286
|
* Trace logger that prints one line per phase, indented by task depth.
|
|
@@ -156,6 +295,32 @@ type ConsoleLoggerOptions = {
|
|
|
156
295
|
*/
|
|
157
296
|
export declare const consoleLogger: (options?: ConsoleLoggerOptions) => TraceLogger;
|
|
158
297
|
//#endregion
|
|
298
|
+
//#region src/trace/describe.d.ts
|
|
299
|
+
type DescribeBusOptions = {
|
|
300
|
+
/** Add where each listener was registered, for the ones `tracePlugin({ source: true })` recorded. Default `false`. */
|
|
301
|
+
source?: boolean;
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* The listeners that each event has right now, by name and in the order they were
|
|
305
|
+
* added: the `traceId` of a listener, else its function name, else `"<anonymous>"`.
|
|
306
|
+
* Reads what `tracePlugin` keeps, so it returns `{}` on a bus without the plugin or
|
|
307
|
+
* a tracer, and in the `notrace` build. It changes nothing on the bus. With `{ source: true }`
|
|
308
|
+
* each name is followed by `(file:line:column)` of its registration, when it was recorded.
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```ts
|
|
312
|
+
* import { createBus } from "nanoeffects";
|
|
313
|
+
* import { consoleLogger, createTracer, describeBus, tracePlugin } from "nanoeffects/trace";
|
|
314
|
+
*
|
|
315
|
+
* const trace = createTracer(consoleLogger());
|
|
316
|
+
* const bus = createBus({ trace }).use(tracePlugin());
|
|
317
|
+
* bus.on("name/changed", function saveName() {});
|
|
318
|
+
*
|
|
319
|
+
* describeBus(bus); // { "name/changed": ["saveName"] }
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
export declare const describeBus: <E extends EventMap>(bus: Bus<E>, options?: DescribeBusOptions) => Record<string, string[]>;
|
|
323
|
+
//#endregion
|
|
159
324
|
//#region src/trace/performance.d.ts
|
|
160
325
|
/** The part of the User Timing API the logger uses. */
|
|
161
326
|
type PerformanceLike = {
|
|
@@ -186,6 +351,14 @@ type PerformanceLoggerOptions = {
|
|
|
186
351
|
export declare const performanceLogger: (options?: PerformanceLoggerOptions) => TraceLogger;
|
|
187
352
|
//#endregion
|
|
188
353
|
//#region src/trace/plugin.d.ts
|
|
354
|
+
type TracePluginOptions = {
|
|
355
|
+
/**
|
|
356
|
+
* Record where each `bus.on` and `bus.once` was called (`file:line:column`) and put it on the
|
|
357
|
+
* events of the listener. Reads one stack at registration, never on emit. An anonymous listener
|
|
358
|
+
* is reported too, under the type of its event. Default `false`.
|
|
359
|
+
*/
|
|
360
|
+
source?: boolean;
|
|
361
|
+
};
|
|
189
362
|
/**
|
|
190
363
|
* Names and groups what the trace shows, on a bus that has a tracer:
|
|
191
364
|
*
|
|
@@ -213,48 +386,7 @@ export declare const performanceLogger: (options?: PerformanceLoggerOptions) =>
|
|
|
213
386
|
* bus.on("name/changed", saveName, { traceId: "saveNotifier" });
|
|
214
387
|
* ```
|
|
215
388
|
*/
|
|
216
|
-
export declare const tracePlugin: () => <E extends EventMap>(bus: Bus<E>) => Bus<E>;
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region src/trace/recorder.d.ts
|
|
219
|
-
type Recorder<E = Record<string, unknown>> = TraceLogger<E> & {
|
|
220
|
-
/**
|
|
221
|
-
* The events received so far, oldest first. Without a `capacity` it is one
|
|
222
|
-
* live array; with one, each read is a new array that is a snapshot.
|
|
223
|
-
*/
|
|
224
|
-
readonly events: TraceEvent<E>[];
|
|
225
|
-
clear: () => void;
|
|
226
|
-
/**
|
|
227
|
-
* The events as plain data that `JSON.stringify` takes: the payload and the error are made safe, so a
|
|
228
|
-
* circular object, an `Error`, a `Map` or a class instance cannot break it. `JSON.stringify(recorder)` uses it.
|
|
229
|
-
*/
|
|
230
|
-
toJSON: () => JsonValue[];
|
|
231
|
-
};
|
|
232
|
-
/**
|
|
233
|
-
* Trace logger that keeps events in memory. With no option it keeps all of
|
|
234
|
-
* them, for tests. With `capacity` it keeps the last events, to send when
|
|
235
|
-
* something goes wrong.
|
|
236
|
-
*
|
|
237
|
-
* `payload` and `error` are kept as they are, and can hold private data: cut
|
|
238
|
-
* what you send. An event has no time, and a `parentId` can name an event that
|
|
239
|
-
* was pushed out: read it as a root.
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* ```ts
|
|
243
|
-
* const recorder = createTraceRecorder<Events>();
|
|
244
|
-
* const bus = createBus<Events>({ trace: createTracer(recorder) });
|
|
245
|
-
*
|
|
246
|
-
* bus.emit("search", "re");
|
|
247
|
-
* bus.emit("search", "redux");
|
|
248
|
-
* recorder.events.map((e) => e.phase); // ["start", "cancel", "start", "done"]
|
|
249
|
-
*
|
|
250
|
-
* const lastEvents = createTraceRecorder<Events>({ capacity: 500 });
|
|
251
|
-
* ```
|
|
252
|
-
*/
|
|
253
|
-
export declare const createTraceRecorder: <E = Record<string, unknown>>(
|
|
254
|
-
/** `capacity`: keep the last N events (a ring buffer); not a positive integer, or left out: keep all. */
|
|
255
|
-
options?: {
|
|
256
|
-
capacity?: number;
|
|
257
|
-
}) => Recorder<E>;
|
|
389
|
+
export declare const tracePlugin: (options?: TracePluginOptions) => <E extends EventMap>(bus: Bus<E>) => Bus<E>;
|
|
258
390
|
//#endregion
|
|
259
391
|
//#region src/trace/redux.d.ts
|
|
260
392
|
type ReduxConnection = {
|
|
@@ -353,6 +485,57 @@ type ReduxDevtoolsState = {
|
|
|
353
485
|
*/
|
|
354
486
|
export declare const reduxDevtools: (options?: ReduxDevtoolsOptions) => TraceLogger;
|
|
355
487
|
//#endregion
|
|
488
|
+
//#region src/trace/timing.d.ts
|
|
489
|
+
/** One task of the trace with the time it took, or the time since it started. */
|
|
490
|
+
type TimedTask = {
|
|
491
|
+
id: number;
|
|
492
|
+
type: string;
|
|
493
|
+
effect: EffectName;
|
|
494
|
+
parentId?: number;
|
|
495
|
+
rootId?: number;
|
|
496
|
+
source?: string;
|
|
497
|
+
/** Milliseconds from `start` to the closing phase, or to now for an open task. */
|
|
498
|
+
ms: number;
|
|
499
|
+
};
|
|
500
|
+
/** A task that closed: how it ended and how long it took. */
|
|
501
|
+
type ClosedTask = TimedTask & {
|
|
502
|
+
phase: Exclude<Phase, "start">;
|
|
503
|
+
};
|
|
504
|
+
type TimingLoggerOptions = {
|
|
505
|
+
/** The clock, in ms. Default `performance.now`, or `Date.now` where there is none. */
|
|
506
|
+
now?: () => number;
|
|
507
|
+
/** Keep only the last N closed tasks in `durations`. `pending()` is never cut. Not a positive integer, or left out: keep all. */
|
|
508
|
+
capacity?: number;
|
|
509
|
+
};
|
|
510
|
+
type TimingLogger = TraceLogger & {
|
|
511
|
+
/** The tasks that closed, oldest closed first. One live array. */
|
|
512
|
+
readonly durations: ClosedTask[];
|
|
513
|
+
/** The tasks that started and have not closed, oldest started first, with the time since `start`. */
|
|
514
|
+
pending: () => TimedTask[];
|
|
515
|
+
clear: () => void;
|
|
516
|
+
};
|
|
517
|
+
/**
|
|
518
|
+
* Trace logger that measures time. It stamps each event when it gets it,
|
|
519
|
+
* pairs `start` with the first `done`, `error`, `cancel` or `drop` of the same
|
|
520
|
+
* task and effect, and keeps the result. Use it to find a slow handler, to see
|
|
521
|
+
* how long a request lived before `cancel`, or to check that a test left
|
|
522
|
+
* no task open.
|
|
523
|
+
*
|
|
524
|
+
* The logger sees what the tracer lets through: a task whose `start` was
|
|
525
|
+
* filtered or not sampled never pairs, and its closing event is ignored.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* ```ts
|
|
529
|
+
* const timing = timingLogger();
|
|
530
|
+
* const bus = createBus<Events>({ trace: createTracer(timing) });
|
|
531
|
+
*
|
|
532
|
+
* bus.emit("search", "redux");
|
|
533
|
+
* timing.pending(); // [{ id: 1, type: "search", effect: "latest", ms: 0 }]
|
|
534
|
+
* timing.durations; // after it ends: [{ ..., phase: "done", ms: 120 }]
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
export declare const timingLogger: (options?: TimingLoggerOptions) => TimingLogger;
|
|
538
|
+
//#endregion
|
|
356
539
|
//#region src/trace/tracer.d.ts
|
|
357
540
|
type TracerOptions = {
|
|
358
541
|
/** Drops the events it returns `false` for, before any logger sees them. */
|
|
@@ -388,4 +571,4 @@ type TracerOptions = {
|
|
|
388
571
|
*/
|
|
389
572
|
export declare const createTracer: <E = Record<string, unknown>>(trace: Trace<E>, options?: TracerOptions) => Tracer;
|
|
390
573
|
//#endregion
|
|
391
|
-
export type { ConsoleLoggerOptions, EffectName, ExportOptions, Finding, GraphLogger, GraphLoggerOptions, GraphSnapshot, JsonOptions, JsonValue, PayloadMode, PerformanceLoggerOptions, Phase, PolicyStage, PolicyStages, Recorder, ReduxDevtoolsOptions, ReduxDevtoolsState, ReduxExtension, SerializeOptions, TaskInfo, Trace, TraceEvent, TraceLogger, Tracer, TracerOptions };
|
|
574
|
+
export type { ChainStep, ClosedTask, ConsoleLoggerOptions, DescribeBusOptions, EffectName, ExportOptions, Finding, GraphLogger, GraphLoggerOptions, GraphSnapshot, JsonOptions, JsonValue, Orphan, PayloadMode, PerformanceLoggerOptions, Phase, PolicyStage, PolicyStages, Recorder, ReduxDevtoolsOptions, ReduxDevtoolsState, ReduxExtension, SerializeOptions, TaskInfo, TimedTask, TimingLogger, TimingLoggerOptions, Trace, TraceEvent, TraceLogger, TracePluginOptions, Tracer, TracerOptions };
|
package/dist/trace.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{n as e
|
|
2
|
-
`)},
|
|
3
|
-
`)},b=e=>e.kind===`storm`?"an emit from a component or a timer repeats: stop it with `equals` of useEmitter, debounce, or a guard":e.kind===`runaway`?`one chain started a huge number of tasks: look for event names that are made from a counter or an id`:e.path.length<=2?`a handler emits its own event: emit a different event for the result`:`handlers feed each other: break the loop with a condition, or emit a different event for the result`,x=(e,t)=>{let n=t===void 0?`[nanoeffects]`:`[nanoeffects ${t}]`,r=e.traceGroupId===void 0?``:` (flow ${e.traceGroupId})`,i=e.kind===`cycle`?`cycle: ${e.path.join(` → `)} (repeated ${e.repeats} times, started at ${e.root})`:`${e.kind}: ${e.path.join(` → `)} (${e.repeats} in a row, started at ${e.root})`,a=[...new Set(e.path)].flatMap(e=>{let t=u(e);return t===void 0?[]:[`${e} at ${t}`]});return`${n} ${i}${r}${a.length>0?`\n ${a.join(`; `)}`:``}\n ${b(e)}`},S=(e,t)=>{if(!e)return;let n=e.connect({name:t});n.init({findings:0});let r=0;return e=>{r+=1,n.send({type:`cycle/detected`,kind:e.kind,path:e.path,repeats:e.repeats,root:e.root},{findings:r})}},C=2e3,w=e=>{let t=Object.getPrototypeOf(e),n=t===null?void 0:Reflect.get(t,`constructor`),r=typeof n==`function`?n.name:``;return typeof r==`string`&&r!==``?r:`Object`},T=e=>{let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype},E=e=>typeof Reflect.get(e,`nodeType`)==`number`&&typeof Reflect.get(e,`nodeName`)==`string`,D=e=>e.length>C?`${e.slice(0,C)}…`:e,O=e=>{switch(typeof e){case`string`:return D(e);case`boolean`:return e;case`number`:return Number.isFinite(e)?e:String(e);case`bigint`:return`${e}n`;case`symbol`:return String(e);case`function`:return`[Function ${e.name||`anonymous`}]`;default:return e===null?null:void 0}},k=e=>{if(e instanceof WeakMap)return`[WeakMap]`;if(e instanceof WeakSet)return`[WeakSet]`;if(e instanceof Promise)return`[Promise]`;if(E(e))return`[DOM ${String(Reflect.get(e,`nodeName`))}]`;if(e instanceof Date)return Number.isNaN(e.getTime())?`[Invalid Date]`:e.toISOString()},A=(e,t,n)=>{if(t.budget<=0)return`[Cut]`;--t.budget;let r=O(e);return r===void 0?typeof e!=`object`||!e?`[undefined]`:j(e,t,n):r},j=(e,t,n)=>{try{let r=k(e);return r===void 0?t.path.has(e)?`[Circular]`:n>=t.maxDepth?Array.isArray(e)?`[Array]`:`[${w(e)}]`:M(e,t,n):r}catch{return`[Unserializable]`}},M=(e,t,n)=>{t.path.add(e);try{return N(e,t,n)}finally{t.path.delete(e)}},N=(e,t,n)=>e instanceof Error?P(e,t,n):Array.isArray(e)?F(e,t,n):e instanceof Map?{$map:F([...e.entries()],t,n)}:e instanceof Set?{$set:F([...e.values()],t,n)}:ArrayBuffer.isView(e)?{$class:w(e),length:Number(Reflect.get(e,`length`))}:I(e,t,n,T(e)?void 0:w(e)),P=(e,t,n)=>{let r={name:D(e.name),message:D(e.message)};return typeof e.stack==`string`&&(r.stack=D(e.stack)),`cause`in e&&(r.cause=A(e.cause,t,n+1)),r},F=(e,t,n)=>{let r=[];for(let[i,a]of e.entries()){if(t.budget<=0){r.push(`[${e.length-i} more]`);break}r.push(A(a,t,n+1))}return r},I=(e,t,n,r)=>{let i={};r!==void 0&&(i.$class=r);for(let r of Object.keys(e)){let a=Object.getOwnPropertyDescriptor(e,r);a&&(i[r]=`value`in a?A(a.value,t,n+1):`[Getter]`)}return i},L=(e,t={})=>{let n={maxDepth:t.maxDepth??6,budget:t.maxSize??1e3,path:/* @__PURE__ */ new Set};try{return A(e,n,0)}catch{return`[Unserializable]`}},R=(e,t)=>`${e}\u0000${t}`,z=e=>{if(typeof e==`function`)return e;let t=new Set(e);return e=>t.has(e)},B=e=>e.event===void 0?[e.node]:[e.event,e.node],V=e=>{let t=e.slice(0,-1),n=t.reduce((e,n,r)=>n<(t[e]??n)?r:e,0);return[...t.slice(n),...t.slice(0,n)].join(`\0`)},H=(e,t)=>{let{node:n}=t,r=[],i=e;for(;i&&i.node!==n;)r.push(i),i=i.parent;let a=r.reverse();return{path:[n,...a.flatMap(B),...B(t)],names:[n,...a.map(e=>e.node),n]}},U=(e={})=>{let t=e.repeats??3,n=e.maxSteps??5e3,r=e.storm===!1?void 0:e.storm??{count:100,perMs:1e3},i=z(e.ignore),a=e.now??(()=>globalThis.performance.now()),o=e.console??globalThis.console,s=/* @__PURE__ */ new Map,c=/* @__PURE__ */ new Map,l=/* @__PURE__ */ new Map,d=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Set,h=!1,g=!1,_,b,C=!1,w=!1,T=e=>{let t=s.get(e)??{count:0};t.count+=1,s.set(e,t)},E=(e,t)=>{let n=R(e,t),r=c.get(n)??{from:e,to:t,count:0,inCycle:!1};r.count+=1,c.set(n,r)},D=t=>{if(e.devtools&&!C){C=!0;let t=e.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;b=S(t,e.name??`nanoeffects graph`)}b?.(t),e.onCycle?e.onCycle(t):o?.warn(x(t,e.name))},O=(e,t)=>{let n=l.get(e);if(n){n.turns+=1;return}let r=t();if(l.set(e,r),!w){w=!0;try{D(r)}catch(e){globalThis.console?.error(`[nanoeffects] graph logger report failed`,e)}finally{w=!1}}},k=(e,t)=>{let n=new Map(e.counts);n.set(t,(n.get(t)??0)+1),e.counts=n},A=(e,n)=>{let r=e.counts.get(e.node)??0;if(r<t||i(e.node))return;let{path:a,names:o}=H(e.parent,e);O(`cycle:${V(o)}`,()=>{let t={kind:`cycle`,path:a,repeats:r,turns:1,root:e.root.name,source:`chain`};return n.traceGroupId!==void 0&&(t.traceGroupId=n.traceGroupId),t})},j=e=>{e.root.steps+=1,!(e.root.steps<=n||e.root.flagged)&&(e.root.flagged=!0,O(`runaway:${e.root.name}`,()=>({kind:`runaway`,path:[e.root.name],repeats:e.root.steps,turns:1,root:e.root.name,source:`chain`})))},M=e=>{if(!r||i(e))return;let t=a(),n=(p.get(e)??[]).filter(e=>t-e<r.perMs);n.push(t),p.set(e,n),n.length<r.count?m.delete(e):m.has(e)||(m.add(e),O(`storm:${e}:${t}`,()=>({kind:`storm`,path:[e],repeats:n.length,turns:1,root:e,source:`chain`})))},N=(e,t)=>{let n=_;return n!==void 0&&n.parent===e&&n.type===t},P=(e,t,n)=>({node:e.type,parent:t,counts:t?.counts??/* @__PURE__ */ new Map,root:t?.root??{name:e.type,steps:0,flagged:!1},inner:n}),F=()=>{g||(g=!0,queueMicrotask(()=>{h||o?.warn(`[nanoeffects] graphLogger got tasks but no emit event: add bus.use(tracePlugin()) for a finer graph.`)}))},I=(e,t,n,r)=>{k(t,e.type),(e.leaf===!0||r||!h)&&(T(e.type),n?E(n.node,e.type):M(e.type)),e.leaf||i(e.type)||(j(t),A(t,e))},B=e=>{let t=e.parent?d.get(e.parent):void 0;e.leaf?(h=!0,_={parent:t,type:e.type}):F();let n=e.emitted===!1,r=!e.leaf&&h&&!n&&!N(t,e.type),i=r&&!t,a=P(e,t,n||r&&!i);d.set(e.ref,a),a.inner||I(e,a,t,i)},U=(e,t)=>{let n=new Map(e.counts),r=e.node;n.set(r,Math.max(0,(n.get(r)??1)-1)),n.set(t.type,(n.get(t.type)??0)+1),e.counts=n,e.node=t.type,e.event=t.event,T(t.type),t.event!==void 0&&E(t.event,t.type),e.inner||A(e,t)},W=e=>{let t=d.get(e.ref);t?U(t,e):B(e)},G=e=>{if(e.phase!==`done`&&e.phase!==`error`)return;let t=s.get(e.type);t&&(t.last=e.phase===`error`?{payload:e.payload,error:e.error}:{payload:e.payload})},K=()=>{let t=J(),n=/* @__PURE__ */ new Set;for(let e of t)q(e,n);let r={nodes:[...s].map(([e,t])=>{let n=u(e);return n===void 0?{name:e,count:t.count}:{name:e,count:t.count,site:n}}),edges:[...c.values()].map(e=>({...e,inCycle:n.has(R(e.from,e.to))})),cycles:t};return e.name!==void 0&&(r.name=e.name),r},q=(e,t)=>{if(e.source===`chain`){for(let[n,r]of e.path.entries()){let i=e.path[n+1];i!==void 0&&t.add(R(r,i))}return}let n=new Set(e.path);for(let e of c.values())n.has(e.from)&&n.has(e.to)&&t.add(R(e.from,e.to))},J=()=>{let e=[...l.values()].filter(e=>e.kind===`cycle`),t=new Set(e.flatMap(e=>e.path)),n=[],r=[...c.values()].filter(e=>!(i(e.from)||i(e.to)));for(let e of f(r))e.every(e=>t.has(e))||n.push({kind:`cycle`,path:e,repeats:e.length,turns:0,root:e[0]??``,source:`graph`});return[...l.values(),...n.filter(t=>!e.some(e=>e.path.join()===t.path.join()))]};return Object.assign(G,{task:W,cycles:()=>J(),toMermaid:e=>v(K(),e),toDot:e=>y(K(),e),toJSON:(e={})=>{let t=K();if(!e.payload)return t;for(let e of t.nodes){let t=s.get(e.name)?.last;t&&(e.last={payload:L(t.payload),...t.error!==void 0&&{error:L(t.error)}})}return t},clear:()=>{s=/* @__PURE__ */ new Map,c=/* @__PURE__ */ new Map,l=/* @__PURE__ */ new Map,d=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Set,_=void 0}})},W=(e={})=>{let t=e.console??globalThis.console,n=e.prefix??`[nanoeffects]`,r=/* @__PURE__ */ new Map;return({id:e,parentId:i,type:a,effect:o,phase:s,payload:c,error:l,traceGroupId:u})=>{r.has(e)||r.set(e,typeof i==`number`?(r.get(i)??0)+1:0);let d=` `.repeat(r.get(e)??0);s!==`start`&&r.delete(e);let f=u===void 0?``:` [${u}]`,p=`${n}${f} ${d}${a} · ${o} ${s}`;s===`error`?t?.error(p,l):t?.debug(p,c)}},G=e=>{if(e instanceof Error)return`${e.name}: ${e.message}`;let t=L(e);return typeof t==`string`?t:JSON.stringify(t)},K=(e={})=>{let t=e.performance??globalThis.performance,n=/* @__PURE__ */ new Map;return({id:e,parentId:r,rootId:i,traceGroupId:a,type:o,effect:s,phase:c,error:l})=>{if(!t)return;if(c===`start`){n.set(e,t.now());return}let u=`${o} · ${s} (${c})`,d={id:e,parentId:r,...i!==void 0&&{rootId:i},...a!==void 0&&{traceGroupId:a},phase:c,...c===`error`&&{error:G(l)}},f=n.get(e);n.delete(e),typeof f==`number`?t.measure(u,{start:f,end:t.now(),detail:d}):t.mark(u,{detail:d})}};let q;const J=()=>q,Y=(e,t)=>{let n=q;q=e;try{return t()}finally{q=n}},X=(e,t,n={})=>{let{trace:r}=e;if(!r){e.emit(t);return}let{traceId:a,traceGroupId:o}=n,{ctx:c,unlink:l}=i({event:{type:a??t.type,payload:t,...o===void 0?{}:{traceGroupId:o}},bus:{emit:e.emit,on:e.on,off:e.off,ctx:e.ctx,addContext:e.addContext},tracer:r});s(c,`run`,`start`);try{c.emit(t),s(c,`run`,`done`)}catch(e){throw s(c,`run`,`error`,e),e}finally{l()}},Z=e=>typeof e==`string`?e:Reflect.get(Object(e),`type`),Q=(e,t)=>typeof e==`object`?Reflect.get(Object(e),`payload`):t[0],$=()=>e=>{if(!(r&&e.trace))return e;let{trace:t}=e,i=(e,n)=>{let r=t.task({type:Z(e),payload:Q(e,n),leaf:!0},o());t.report(r,`emit`,`done`)},s=e.emit;e.emit=(e,...t)=>Y(e,()=>(i(e,t),s(e,...t))),Reflect.set(e,l,(t,n)=>{X(e,t,n)});let c=/* @__PURE__ */ new WeakMap,u=(e,t,n)=>{let r=c.get(t)??/* @__PURE__ */ new Map,i=Z(e);r.set(i,[...r.get(i)??[],n]),c.set(t,r)},d=(e,t)=>(c.get(t)?.get(Z(e)))?.pop(),f=(e,t)=>(r,i)=>(n(i,t),a(i,`run`,()=>e(r,i))),p=(e,t)=>(n,r,i)=>{let a=Reflect.get(Object(i),`traceId`);if(typeof a!=`string`)return e(n,r,i);let o=t?(e,t)=>(d(n,r),f(r,a)(e,t)):f(r,a);u(n,r,o);let s=e(n,o,i);return()=>{s()}},m=e.off,h=(e,t)=>{t===void 0?m(e):m(e,d(e,t)??t)},g=e.on,_=e.once;return e.on=p(g,!1),e.once=p(_,!0),e.off=h,e},ee=e=>{let t=e?.capacity??0,n=Number.isInteger(t)&&t>0?t:0,r=[],i=0,a=e=>{n===0?r.push(e):(r[i%n]=e,i+=1)},o=()=>{r.length=0,i=0},s=()=>{let e=Math.min(i,n),t=i>n?i%n:0,a=[];for(let i=0;i<e;i+=1){let e=r[(t+i)%n];e&&a.push(e)}return a},c=Object.assign(a,{clear:o,events:r,toJSON:()=>(n>0?s():r).map(e=>L(e))});return n>0&&Object.defineProperty(c,"events",{get:s}),c},te=()=>{},ne=/* @__PURE__ */ new Set([`cancel`,`drop`,`error`]),re=()=>!1,ie=()=>!0,ae=e=>{if(typeof e==`function`)return e;if(Array.isArray(e)){let t=new Set(e);return({phase:e})=>t.has(e)}return e?ie:re},oe=(e={})=>{let t=e.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;if(!t)return te;let{starts:n=!1,depth:r=0,maxAge:i}=e,a=ae(e.policies),o=e.payload??`essential`,s=e.serialize===!1?e=>e:e.serialize??(e=>L(e)),c=t.connect({name:e.name??`nanoeffects`,...i!==void 0&&{maxAge:i}}),l=/* @__PURE__ */ new Map,u=/* @__PURE__ */ new Map,d=()=>({running:Object.fromEntries(l)});c.init(d());let f=(e,t,n)=>n===0?a({effect:e,phase:t}):n<=r,p=(e,t)=>{e.phase===`start`?(u.set(e.id,t),f(e.effect,`start`,t)&&l.set(e.id,{type:e.type,effect:e.effect,...e.traceGroupId!==void 0&&{traceGroupId:e.traceGroupId}})):(u.delete(e.id),l.delete(e.id))},m=!1,h=!1,g=(e,t)=>{m||h||t!==0||e===`start`||(h=!0,globalThis.console?.warn(`[nanoeffects] reduxDevtools got a task but no emit event: add bus.use(tracePlugin()) to see the emits.`))},_=e=>{let{payload:t,...n}=e;return o===`all`||o===`essential`&&(e.effect===`emit`||ne.has(e.phase))?{...n,payload:s(t)}:n},v=(e,t)=>{c.send({..._(e),type:`${e.type}/${e.effect}/${e.phase}`,event:e.type,...e.phase===`error`&&{error:t instanceof Error?t.message:s(t)}},d())};return({error:e,...t})=>{if(t.effect===`emit`){m=!0,c.send({..._(t),event:t.type},d());return}let r=(t.parentId===void 0?-1:u.get(t.parentId)??-1)+1;p(t,r),g(t.phase,r),(t.phase===`error`&&r===0||f(t.effect,t.phase,r))&&(t.phase!==`start`||n)&&v(t,e)}},se=t=>{let n=typeof t==`function`?[t]:[...t??[]];return n.length===0?null:t=>{for(let r of n)try{r(t)}catch(t){e(`trace logger failed`,t)}}},ce=()=>{},le=e=>{if(typeof e.traceGroupId==`string`)return e.traceGroupId;let t=J();if(typeof t!=`object`&&typeof t!=`function`||t===null)return;let n=Reflect.get(t,d),r=typeof n==`object`&&n?Reflect.get(n,`traceGroupId`):void 0;return typeof r==`string`?r:void 0},ue=(n,r={})=>{let i=n,a=se(i),{filter:s,sample:l=1}=r,u=0,d=(Array.isArray(i)?i:[i]).flatMap(e=>e.task?[e.task]:[]),f=t=>{let n={ref:t,id:t.id,type:t.type};t.parentRef&&(n.parent=t.parentRef),t.event!==void 0&&(n.event=t.event),t.leaf&&(n.leaf=!0),n.emitted=t.emitted,t.group!==void 0&&(n.traceGroupId=t.group);for(let t of d)try{t(n)}catch(t){e(`trace logger failed`,t)}},p=e=>typeof l==`function`?l({type:e.type,payload:e.payload}):Math.random()<l,m={task:(e,t)=>{let n={id:++u,root:t?.root??u,parent:t?.id,parentRef:d.length>0?t:void 0,leaf:e.leaf,emitted:o()===t,type:e.type,payload:e.payload,sampled:t?.sampled??p(e),group:le(e)??t?.group};return d.length>0&&n.sampled&&f(n),n},rename:(e,t)=>{e.event??=e.type,e.type=t,d.length>0&&e.sampled&&f(e)},report:(e,t,n,r)=>{if(!e.sampled)return;let i={id:e.id,type:e.type,effect:t,phase:n,payload:e.payload};typeof e.parent==`number`&&(i.parentId=e.parent),e.root!==e.id&&(i.rootId=e.root),e.group!==void 0&&(i.traceGroupId=e.group),n===`error`&&(i.error=r),(!s||s(i))&&a?.(i)},settler:(e,t)=>{if(!e.sampled)return ce;let n=!1;return(r,i)=>{n||(n=!0,m.report(e,t,r,i))}},run:(e,n,r,i)=>{if(!e.sampled)return i();let a=m.settler(e,n);m.report(e,n,`start`),t({signal:r},()=>a(`cancel`));let o;try{o=i()}catch(e){throw a(`error`,e),e}return c(o)?Promise.resolve(o).then(e=>(a(`done`),e),e=>{throw a(`error`,e),e}):(a(`done`),o)}};return m};export{W as consoleLogger,ee as createTraceRecorder,ue as createTracer,U as graphLogger,K as performanceLogger,oe as reduxDevtools,L as safeSerialize,$ as tracePlugin};
|
|
1
|
+
import{n as e}from"./site-DLvUoXs3.js";import{n as t,r as n,t as r}from"./tracer-v7m-Qah_.js";const i=e=>{let t=/* @__PURE__ */ new Map;for(let{from:n,to:r}of e){let e=t.get(n)??[];e.push(r),t.set(n,e),t.has(r)||t.set(r,[])}let n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Set,a=[],o=[],s=0,c=(e,t)=>{n.set(e,s),r.set(e,s),s+=1,a.push(e),i.add(e),t.push({name:e,next:0})},l=e=>{let n=[],r;do{if(r=a.pop(),r===void 0)break;i.delete(r),n.push(r)}while(r!==e);let[s]=n,c=n.length===1&&s!==void 0&&t.get(s)?.includes(s);(n.length>1||c)&&o.push(n.reverse())},u=(e,t)=>{r.set(e,Math.min(r.get(e)??t,t))},d=(e,r)=>{let a=t.get(r.name)?.[r.next];return a!==void 0&&(r.next+=1,n.has(a)?i.has(a)&&u(r.name,n.get(a)??0):c(a,e),!0)},f=(e,t)=>{e.pop();let i=e.at(-1);i&&u(i.name,r.get(t.name)??0),r.get(t.name)===n.get(t.name)&&l(t.name)},p=e=>{let t=[];c(e,t);for(let e=t.at(-1);e;e=t.at(-1))d(t,e)||f(t,e)};for(let e of t.keys())n.has(e)||p(e);return o},a=(e,t)=>{if(t===`prefix`){let t=e.indexOf(`/`);return t>0?e.slice(0,t):void 0}return t?.(e)},o=e=>e.replaceAll(`"`,`#quot;`).replaceAll(`<`,`#lt;`).replaceAll(`>`,`#gt;`).replaceAll(/\r?\n/g,` `),s=e=>e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(/\r?\n/g,`\\n`),c=e=>new Map(e.nodes.map((e,t)=>[e.name,`n${t}`])),l=(e,t)=>{let n=/* @__PURE__ */ new Map;for(let{name:r}of e.nodes){let e=a(r,t);e!==void 0&&n.set(e,[...n.get(e)??[],r])}return n},u=(e,t={})=>{let n=c(e),r=[`flowchart LR`],i=/* @__PURE__ */ new Set;for(let[a,s]of l(e,t.group)){r.push(` subgraph g_${r.length}["${o(a)}"]`);for(let e of s)i.add(e),r.push(` ${n.get(e)}["${o(e)}"]`);r.push(` end`)}for(let{name:t}of e.nodes)i.has(t)||r.push(` ${n.get(t)}["${o(t)}"]`);let a=[];for(let[t,i]of e.edges.entries())r.push(` ${n.get(i.from)} -->|x${i.count}| ${n.get(i.to)}`),i.inCycle&&a.push(t);return a.length>0&&r.push(` linkStyle ${a.join(`,`)} stroke:red,stroke-width:2px`),r.join(`
|
|
2
|
+
`)},d=(e,t={})=>{let n=c(e),r=[`digraph events {`];e.name!==void 0&&r.push(` label="${s(e.name)}";`);let i=/* @__PURE__ */ new Set;for(let[a,o]of l(e,t.group)){r.push(` subgraph "cluster_${s(a)}" {`,` label="${s(a)}";`);for(let e of o)i.add(e),r.push(` ${n.get(e)} [label="${s(e)}"];`);r.push(` }`)}for(let{name:t}of e.nodes)i.has(t)||r.push(` ${n.get(t)} [label="${s(t)}"];`);for(let t of e.edges){let e=t.inCycle?`, color=red, penwidth=2`:``;r.push(` ${n.get(t.from)} -> ${n.get(t.to)} [label="x${t.count}"${e}];`)}return r.push(`}`),r.join(`
|
|
3
|
+
`)},f=e=>e.kind===`storm`?"an emit from a component or a timer repeats: stop it with `equals` of useEmitter, debounce, or a guard":e.kind===`runaway`?`one chain started a huge number of tasks: look for event names that are made from a counter or an id`:e.path.length<=2?`a handler emits its own event: emit a different event for the result`:`handlers feed each other: break the loop with a condition, or emit a different event for the result`,p=(t,n)=>{let r=n===void 0?`[nanoeffects]`:`[nanoeffects ${n}]`,i=t.traceGroupId===void 0?``:` (flow ${t.traceGroupId})`,a=t.kind===`cycle`?`cycle: ${t.path.join(` → `)} (repeated ${t.repeats} times, started at ${t.root})`:`${t.kind}: ${t.path.join(` → `)} (${t.repeats} in a row, started at ${t.root})`,o=[...new Set(t.path)].flatMap(t=>{let n=e(t);return n===void 0?[]:[`${t} at ${n}`]});return`${r} ${a}${i}${o.length>0?`\n ${o.join(`; `)}`:``}\n ${f(t)}`},m=(e,t)=>{if(!e)return;let n=e.connect({name:t});n.init({findings:0});let r=0;return e=>{r+=1,n.send({type:`cycle/detected`,kind:e.kind,path:e.path,repeats:e.repeats,root:e.root},{findings:r})}},h=2e3,g=e=>{let t=Object.getPrototypeOf(e),n=t===null?void 0:Reflect.get(t,`constructor`),r=typeof n==`function`?n.name:``;return typeof r==`string`&&r!==``?r:`Object`},_=e=>{let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype},v=e=>typeof Reflect.get(e,`nodeType`)==`number`&&typeof Reflect.get(e,`nodeName`)==`string`,y=e=>e.length>h?`${e.slice(0,h)}…`:e,b=e=>{switch(typeof e){case`string`:return y(e);case`boolean`:return e;case`number`:return Number.isFinite(e)?e:String(e);case`bigint`:return`${e}n`;case`symbol`:return String(e);case`function`:return`[Function ${e.name||`anonymous`}]`;default:return e===null?null:void 0}},x=e=>{if(e instanceof WeakMap)return`[WeakMap]`;if(e instanceof WeakSet)return`[WeakSet]`;if(e instanceof Promise)return`[Promise]`;if(v(e))return`[DOM ${String(Reflect.get(e,`nodeName`))}]`;if(e instanceof Date)return Number.isNaN(e.getTime())?`[Invalid Date]`:e.toISOString()},S=(e,t,n)=>{if(t.budget<=0)return`[Cut]`;--t.budget;let r=b(e);return r===void 0?typeof e!=`object`||!e?`[undefined]`:C(e,t,n):r},C=(e,t,n)=>{try{let r=x(e);return r===void 0?t.path.has(e)?`[Circular]`:n>=t.maxDepth?Array.isArray(e)?`[Array]`:`[${g(e)}]`:w(e,t,n):r}catch{return`[Unserializable]`}},w=(e,t,n)=>{t.path.add(e);try{return T(e,t,n)}finally{t.path.delete(e)}},T=(e,t,n)=>e instanceof Error?E(e,t,n):Array.isArray(e)?D(e,t,n):e instanceof Map?{$map:D([...e.entries()],t,n)}:e instanceof Set?{$set:D([...e.values()],t,n)}:ArrayBuffer.isView(e)?{$class:g(e),length:Number(Reflect.get(e,`length`))}:O(e,t,n,_(e)?void 0:g(e)),E=(e,t,n)=>{let r={name:y(e.name),message:y(e.message)};return typeof e.stack==`string`&&(r.stack=y(e.stack)),`cause`in e&&(r.cause=S(e.cause,t,n+1)),r},D=(e,t,n)=>{let r=[];for(let[i,a]of e.entries()){if(t.budget<=0){r.push(`[${e.length-i} more]`);break}r.push(S(a,t,n+1))}return r},O=(e,t,n,r)=>{let i={};r!==void 0&&(i.$class=r);for(let r of Object.keys(e)){let a=Object.getOwnPropertyDescriptor(e,r);a&&(i[r]=`value`in a?S(a.value,t,n+1):`[Getter]`)}return i},k=(e,t={})=>{let n={maxDepth:t.maxDepth??6,budget:t.maxSize??1e3,path:/* @__PURE__ */ new Set};try{return S(e,n,0)}catch{return`[Unserializable]`}},A=(e,t)=>`${e}\u0000${t}`,j=e=>{if(typeof e==`function`)return e;let t=new Set(e);return e=>t.has(e)},M=e=>e.event===void 0?[e.node]:[e.event,e.node],N=e=>{let t=e.slice(0,-1),n=t.reduce((e,n,r)=>n<(t[e]??n)?r:e,0);return[...t.slice(n),...t.slice(0,n)].join(`\0`)},P=(e,t)=>{let{node:n}=t,r=[],i=e;for(;i&&i.node!==n;)r.push(i),i=i.parent;let a=r.reverse();return{path:[n,...a.flatMap(M),...M(t)],names:[n,...a.map(e=>e.node),n]}},F=(t={})=>{let n=t.repeats??3,r=t.maxSteps??5e3,a=t.storm===!1?void 0:t.storm??{count:100,perMs:1e3},o=j(t.ignore),s=t.now??(()=>globalThis.performance.now()),c=t.console??globalThis.console,l=/* @__PURE__ */ new Map,f=/* @__PURE__ */ new Map,h=/* @__PURE__ */ new Map,g=/* @__PURE__ */ new WeakMap,_=/* @__PURE__ */ new Map,v=/* @__PURE__ */ new Set,y=!1,b=!1,x,S,C=!1,w=!1,T=e=>{let t=l.get(e)??{count:0};t.count+=1,l.set(e,t)},E=(e,t)=>{let n=A(e,t),r=f.get(n)??{from:e,to:t,count:0,inCycle:!1};r.count+=1,f.set(n,r)},D=e=>{if(t.devtools&&!C){C=!0;let e=t.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;S=m(e,t.name??`nanoeffects graph`)}S?.(e),t.onCycle?t.onCycle(e):c?.warn(p(e,t.name))},O=(e,t)=>{let n=h.get(e);if(n){n.turns+=1;return}let r=t();if(h.set(e,r),!w){w=!0;try{D(r)}catch(e){globalThis.console?.error(`[nanoeffects] graph logger report failed`,e)}finally{w=!1}}},M=(e,t)=>{let n=new Map(e.counts);n.set(t,(n.get(t)??0)+1),e.counts=n},F=(e,t)=>{let r=e.counts.get(e.node)??0;if(r<n||o(e.node))return;let{path:i,names:a}=P(e.parent,e);O(`cycle:${N(a)}`,()=>{let n={kind:`cycle`,path:i,repeats:r,turns:1,root:e.root.name,source:`chain`};return t.traceGroupId!==void 0&&(n.traceGroupId=t.traceGroupId),n})},I=e=>{e.root.steps+=1,!(e.root.steps<=r||e.root.flagged)&&(e.root.flagged=!0,O(`runaway:${e.root.name}`,()=>({kind:`runaway`,path:[e.root.name],repeats:e.root.steps,turns:1,root:e.root.name,source:`chain`})))},L=e=>{if(!a||o(e))return;let t=s(),n=(_.get(e)??[]).filter(e=>t-e<a.perMs);n.push(t),_.set(e,n),n.length<a.count?v.delete(e):v.has(e)||(v.add(e),O(`storm:${e}:${t}`,()=>({kind:`storm`,path:[e],repeats:n.length,turns:1,root:e,source:`chain`})))},R=(e,t)=>{let n=x;return n!==void 0&&n.parent===e&&n.type===t},z=(e,t,n)=>({node:e.type,parent:t,counts:t?.counts??/* @__PURE__ */ new Map,root:t?.root??{name:e.type,steps:0,flagged:!1},inner:n}),B=()=>{b||(b=!0,queueMicrotask(()=>{y||c?.warn(`[nanoeffects] graphLogger got tasks but no emit event: add bus.use(tracePlugin()) for a finer graph.`)}))},V=(e,t,n,r)=>{M(t,e.type),(e.leaf===!0||r||!y)&&(T(e.type),n?E(n.node,e.type):L(e.type)),e.leaf||o(e.type)||(I(t),F(t,e))},H=e=>{let t=e.parent?g.get(e.parent):void 0;e.leaf?(y=!0,x={parent:t,type:e.type}):B();let n=e.emitted===!1,r=!e.leaf&&y&&!n&&!R(t,e.type),i=r&&!t,a=z(e,t,n||r&&!i);g.set(e.ref,a),a.inner||V(e,a,t,i)},U=(e,t)=>{let n=new Map(e.counts),r=e.node;n.set(r,Math.max(0,(n.get(r)??1)-1)),n.set(t.type,(n.get(t.type)??0)+1),e.counts=n,e.node=t.type,e.event=t.event,T(t.type),t.event!==void 0&&E(t.event,t.type),e.inner||F(e,t)},W=e=>{let t=g.get(e.ref);t?U(t,e):H(e)},G=e=>{if(e.phase!==`done`&&e.phase!==`error`)return;let t=l.get(e.type);t&&(t.last=e.phase===`error`?{payload:e.payload,error:e.error}:{payload:e.payload})},K=()=>{let n=J(),r=/* @__PURE__ */ new Set;for(let e of n)q(e,r);let i={nodes:[...l].map(([t,n])=>{let r=e(t);return r===void 0?{name:t,count:n.count}:{name:t,count:n.count,site:r}}),edges:[...f.values()].map(e=>({...e,inCycle:r.has(A(e.from,e.to))})),cycles:n};return t.name!==void 0&&(i.name=t.name),i},q=(e,t)=>{if(e.source===`chain`){for(let[n,r]of e.path.entries()){let i=e.path[n+1];i!==void 0&&t.add(A(r,i))}return}let n=new Set(e.path);for(let e of f.values())n.has(e.from)&&n.has(e.to)&&t.add(A(e.from,e.to))},J=()=>{let e=[...h.values()].filter(e=>e.kind===`cycle`),t=new Set(e.flatMap(e=>e.path)),n=[],r=[...f.values()].filter(e=>!(o(e.from)||o(e.to)));for(let e of i(r))e.every(e=>t.has(e))||n.push({kind:`cycle`,path:e,repeats:e.length,turns:0,root:e[0]??``,source:`graph`});return[...h.values(),...n.filter(t=>!e.some(e=>e.path.join()===t.path.join()))]};return Object.assign(G,{task:W,cycles:()=>J(),toMermaid:e=>u(K(),e),toDot:e=>d(K(),e),toJSON:(e={})=>{let t=K();if(!e.payload)return t;for(let e of t.nodes){let t=l.get(e.name)?.last;t&&(e.last={payload:k(t.payload),...t.error!==void 0&&{error:k(t.error)}})}return t},clear:()=>{l=/* @__PURE__ */ new Map,f=/* @__PURE__ */ new Map,h=/* @__PURE__ */ new Map,g=/* @__PURE__ */ new WeakMap,_=/* @__PURE__ */ new Map,v=/* @__PURE__ */ new Set,x=void 0}})},I=(e,t)=>`${e}\u0000${t}`,L=e=>{let t=e.slice(0,-1),n=t.reduce((e,n,r)=>n<(t[e]??n)?r:e,0);return[...t.slice(n),...t.slice(0,n)]},R=e=>{let t=e.kind===`cycle`?L(e.path):[e.root];return[e.kind,e.source,e.traceGroupId??``,...t].join(`\0`)},z=(e,t)=>{let n={name:t.name,count:t.count},r=t.site??e?.site;e&&(n.count+=e.count),r!==void 0&&(n.site=e?.site??r);let i=t.last??e?.last;return i!==void 0&&(n.last=i),n},B=(...e)=>{let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i;for(let a of e){i??=a.name;for(let e of a.nodes)t.set(e.name,z(t.get(e.name),e));for(let e of a.edges){let t=I(e.from,e.to),r=n.get(t);n.set(t,{from:e.from,to:e.to,count:e.count+(r?.count??0),inCycle:e.inCycle||(r?.inCycle??!1)})}for(let e of a.cycles){let t=R(e),n=r.get(t);r.set(t,{...e,path:[...e.path],turns:e.turns+(n?.turns??0),repeats:Math.max(e.repeats,n?.repeats??0)})}}let a={nodes:[...t.values()],edges:[...n.values()],cycles:[...r.values()]};return i!==void 0&&(a.name=i),a},V=/ \([^()]*:\d+:\d+\)$/,H=(e,t)=>{let n=new Set(t.nodes.map(e=>e.name)),r=[];for(let[t,i]of Object.entries(e)){let e=n.has(t);for(let a of i){let i=a.replace(V,``);i===`<anonymous>`||n.has(i)||r.push({event:t,listener:i,kind:e?`unrun`:`unemitted`})}}return r},U=e=>`events`in e?e.events:e,W=e=>`tasks`in e?e.tasks:/* @__PURE__ */ new Map,G=(e,t)=>{let n=/* @__PURE__ */ new Map;for(let t of U(e))n.set(t.id,t);let r=W(e),i=[],a=/* @__PURE__ */ new Set,o=t;for(;o!==void 0&&!a.has(o);){a.add(o);let e=n.get(o),t=r.get(o),s=K(o,e,t);if(!s)break;i.push(s),o=e?.parentId??t?.parentId}return i.reverse()},K=(e,t,n)=>{let r=t??{},i=n??{},a=r.type??i.type;if(a===void 0)return;let o=r.source??i.source,s=r.traceGroupId??i.traceGroupId;return{id:e,type:a,...t?{effect:t.effect,phase:t.phase}:{},...o===void 0?{}:{source:o},...s===void 0?{}:{traceGroupId:s}}},q=e=>{let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new WeakMap;return{task:({ref:r,parent:i,id:a,type:o,source:s,traceGroupId:c})=>{n.set(r,a);let l=i===void 0?void 0:n.get(i),u={type:o,...l===void 0?{}:{parentId:l},...s===void 0?{}:{source:s},...c===void 0?{}:{traceGroupId:c}};if(t.set(a,u),e>0&&t.size>e){let e=t.keys().next().value;e!==void 0&&t.delete(e)}},tasks:t,clear:()=>t.clear()}},J=(e={})=>{let t=e.console??globalThis.console,n=e.prefix??`[nanoeffects]`,r=e.source===!0,i=e=>r&&e!==void 0?` (${e})`:``,a=/* @__PURE__ */ new Map,o=e.chain===!0?q(1e3):void 0,s=(e,t)=>{if(!o||t!==`error`)return``;let n=[],r=/* @__PURE__ */ new Set,i=e;for(;i!==void 0&&!r.has(i);){r.add(i);let e=o.tasks.get(i);if(!e)break;n.push(e.type),i=e.parentId}return n.length>1?` (${n.reverse().join(` → `)})`:``},c=({id:e,parentId:r,type:o,effect:c,phase:l,payload:u,error:d,traceGroupId:f,source:p})=>{a.has(e)||a.set(e,typeof r==`number`?(a.get(r)??0)+1:0);let m=` `.repeat(a.get(e)??0);l!==`start`&&a.delete(e);let h=f===void 0?``:` [${f}]`,g=i(p),_=s(e,l),v=`${n}${h} ${m}${o} · ${c} ${l}${g}${_}`;l===`error`?t?.error(v,d):t?.debug(v,u)};return o&&(c.task=o.task),c},Y=(e,t={})=>{let r=t.source===!0,i=e=>{let t=e.name??`<anonymous>`;return r&&e.source!==void 0?`${t} (${e.source})`:t},a={};for(let[t,r]of n(e)??[])typeof t==`string`&&(a[t]=r.map(i));return a},X=e=>{if(e instanceof Error)return`${e.name}: ${e.message}`;let t=k(e);return typeof t==`string`?t:JSON.stringify(t)},Z=(e={})=>{let t=e.performance??globalThis.performance,n=/* @__PURE__ */ new Map;return({id:e,parentId:r,rootId:i,traceGroupId:a,type:o,effect:s,phase:c,error:l})=>{if(!t)return;if(c===`start`){n.set(e,t.now());return}let u=`${o} · ${s} (${c})`,d={id:e,parentId:r,...i!==void 0&&{rootId:i},...a!==void 0&&{traceGroupId:a},phase:c,...c===`error`&&{error:X(l)}},f=n.get(e);n.delete(e),typeof f==`number`?t.measure(u,{start:f,end:t.now(),detail:d}):t.mark(u,{detail:d})}},Q=e=>{let t=e?.capacity??0,n=Number.isInteger(t)&&t>0?t:0,r=[],i=q(n),a=0,o=e=>{n===0?r.push(e):(r[a%n]=e,a+=1)},s=()=>{r.length=0,a=0,i.clear()},c=()=>{let e=Math.min(a,n),t=a>n?a%n:0,i=[];for(let a=0;a<e;a+=1){let e=r[(t+a)%n];e&&i.push(e)}return i},l=Object.assign(o,{clear:s,events:r,tasks:i.tasks,task:i.task,toJSON:()=>(n>0?c():r).map(e=>k(e))});return n>0&&Object.defineProperty(l,"events",{get:c}),l},$=()=>{},ee=/* @__PURE__ */ new Set([`cancel`,`drop`,`error`]),te=()=>!1,ne=()=>!0,re=e=>{if(typeof e==`function`)return e;if(Array.isArray(e)){let t=new Set(e);return({phase:e})=>t.has(e)}return e?ne:te},ie=(e={})=>{let t=e.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;if(!t)return $;let{starts:n=!1,depth:r=0,maxAge:i}=e,a=re(e.policies),o=e.payload??`essential`,s=e.serialize===!1?e=>e:e.serialize??(e=>k(e)),c=t.connect({name:e.name??`nanoeffects`,...i!==void 0&&{maxAge:i}}),l=/* @__PURE__ */ new Map,u=/* @__PURE__ */ new Map,d=()=>({running:Object.fromEntries(l)});c.init(d());let f=(e,t,n)=>n===0?a({effect:e,phase:t}):n<=r,p=(e,t)=>{e.phase===`start`?(u.set(e.id,t),f(e.effect,`start`,t)&&l.set(e.id,{type:e.type,effect:e.effect,...e.traceGroupId!==void 0&&{traceGroupId:e.traceGroupId}})):(u.delete(e.id),l.delete(e.id))},m=!1,h=!1,g=(e,t)=>{m||h||t!==0||e===`start`||(h=!0,globalThis.console?.warn(`[nanoeffects] reduxDevtools got a task but no emit event: add bus.use(tracePlugin()) to see the emits.`))},_=e=>{let{payload:t,...n}=e;return o===`all`||o===`essential`&&(e.effect===`emit`||ee.has(e.phase))?{...n,payload:s(t)}:n},v=(e,t)=>{c.send({..._(e),type:`${e.type}/${e.effect}/${e.phase}`,event:e.type,...e.phase===`error`&&{error:t instanceof Error?t.message:s(t)}},d())};return({error:e,...t})=>{if(t.effect===`emit`){m=!0,c.send({..._(t),event:t.type},d());return}let r=(t.parentId===void 0?-1:u.get(t.parentId)??-1)+1;p(t,r),g(t.phase,r),(t.phase===`error`&&r===0||f(t.effect,t.phase,r))&&(t.phase!==`start`||n)&&v(t,e)}},ae=()=>typeof globalThis.performance?.now==`function`?globalThis.performance.now():Date.now(),oe=e=>({id:e.id,type:e.type,effect:e.effect,...e.parentId===void 0?{}:{parentId:e.parentId},...e.rootId===void 0?{}:{rootId:e.rootId},...e.source===void 0?{}:{source:e.source}}),se=(e={})=>{let t=e.now??ae,n=e.capacity??0,r=Number.isInteger(n)&&n>0?n:0,i=/* @__PURE__ */ new Map,a=[];return Object.assign(e=>{let n=`${e.id}:${e.effect}`,o=t();if(e.phase===`start`){i.set(n,{...oe(e),startedAt:o});return}let s=i.get(n);if(!s)return;i.delete(n);let{startedAt:c,...l}=s;a.push({...l,phase:e.phase,ms:o-c}),r>0&&a.length>r&&a.shift()},{durations:a,pending:()=>{let e=t();return[...i.values()].map(({startedAt:t,...n})=>({...n,ms:e-t}))},clear:()=>{i.clear(),a.length=0}})};export{G as chainOf,J as consoleLogger,Q as createTraceRecorder,r as createTracer,Y as describeBus,H as findOrphans,F as graphLogger,B as mergeGraphs,Z as performanceLogger,ie as reduxDevtools,k as safeSerialize,se as timingLogger,t as tracePlugin};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{i as e,n as t,r as n}from"./caller-DULg_ZYV.js";import{n as r,t as i}from"./onAbort-BgMfspK4.js";import{a,c as o,n as s,o as c,r as l,s as u}from"./context-Dp_QRXzb.js";import{n as d}from"./promise-CSLpzwSR.js";import{t as f}from"./origin-key-BbWN3gmN.js";import{t as p}from"./scope-key-B7l7mUS5.js";const m=/* @__PURE__ */ new WeakMap,h=e=>{let t=m.get(e);if(t)return t;let n=/* @__PURE__ */ new Map;return m.set(e,n),n},g=e=>m.get(e),_=(e,t,n)=>{let r=e.get(t)??[];r.push(n),e.set(t,r)},v=(e,t,n)=>{let r=e.get(t),i=r?.indexOf(n)??-1;!r||i<0||(r.splice(i,1),r.length===0&&e.delete(t))},y=(e,t,n)=>(e.get(t)??[]).findLast(e=>e.handler===n);let b;const x=()=>b,S=(e,t)=>{let n=b;b=e;try{return t()}finally{b=n}},C=(e,t,n={})=>{let{trace:r}=e;if(!r){e.emit(t);return}let{traceId:i,traceGroupId:a}=n,{ctx:o,unlink:c}=s({event:{type:i??t.type,payload:t,...a===void 0?{}:{traceGroupId:a}},bus:{emit:e.emit,on:e.on,off:e.off,ctx:e.ctx,addContext:e.addContext},tracer:r});u(o,`run`,`start`);try{o.emit(t),u(o,`run`,`done`)}catch(e){throw u(o,`run`,`error`,e),e}finally{c()}},w=e=>/^(.+):(\d+):(\d+)$/.exec(e)?e:void 0,T=e=>{let t=e.slice(3).replace(/^async /,``),n=t.lastIndexOf(` (`),r=n<0?t:t.slice(n+2).replace(/\)$/,``);return w(r)},E=e=>w(e.slice(e.indexOf(`@`)+1)),D=e=>{if(typeof e!=`string`)return[];let t=[];for(let n of e.split(`
|
|
2
|
+
`)){let e=n.trim();e.startsWith(`at `)?t.push(T(e)):e.includes(`@`)&&t.push(E(e))}return t},O=(e,t)=>D(e)[t],k=e=>typeof e==`string`?e:Reflect.get(Object(e),`type`),A=(e,t)=>typeof e==`object`?Reflect.get(Object(e),`payload`):t[0],j=(r={})=>i=>{if(!(o&&i.trace))return i;let{trace:s}=i,u=(e,t)=>{let n=s.task({type:k(e),payload:A(e,t),leaf:!0},l());s.report(n,`emit`,`done`)},d=i.emit;i.emit=(e,...t)=>S(e,()=>(u(e,t),d(e,...t))),Reflect.set(i,f,(e,t)=>{C(i,e,t)});let p=h(i),m=(e,t,n)=>(r,i)=>(a(i,t,n),c(i,`run`,()=>e(r,i))),g=(e,t)=>{let n=Reflect.get(Object(t),`traceId`);return typeof n==`string`?n:e.name||void 0},b=r.source===!0;b&&n();let x=/* @__PURE__ */ new Map,w=(e,t,n)=>{let r=e.name;if(!r&&b&&typeof t==`string`){let e=(x.get(t)??0)+1;x.set(t,e),r=`${t}#${e}`}let i=r===void 0?e.handler:m(e.handler,r,e.source);return n?(n,r)=>(v(p,t,e),i(n,r)):i},T=(n,r)=>{let i=(e,i,a)=>{let o=k(e),s=b?O(t(),2):void 0,c={handler:i,wrapper:i,name:g(i,a),source:s};c.wrapper=w(c,o,r),_(p,o,c);let l=n(e,c.wrapper,a);return()=>{v(p,o,c),l()}};return(t,n,r)=>e(()=>i(t,n,r))},E=i.off,D=(e,t)=>{e===void 0?p.clear():t===void 0&&p.delete(k(e));let n=e!==void 0&&t&&y(p,k(e),t);n&&v(p,k(e),n),E(e,n?n.wrapper:t)},j=i.on,M=i.once;return i.on=T(j,!1),i.once=T(M,!0),i.off=D,i},M=e=>{let t=typeof e==`function`?[e]:[...e??[]];return t.length===0?null:e=>{for(let n of t)try{n(e)}catch(e){r(`trace logger failed`,e)}}},N=()=>{},P=e=>{if(typeof e.traceGroupId==`string`)return e.traceGroupId;let t=x();if(typeof t!=`object`&&typeof t!=`function`||t===null)return;let n=Reflect.get(t,p),r=typeof n==`object`&&n?Reflect.get(n,`traceGroupId`):void 0;return typeof r==`string`?r:void 0},F=(e,t={})=>{let n=e,a=M(n),{filter:o,sample:s=1}=t,c=0,u=(Array.isArray(n)?n:[n]).flatMap(e=>e.task?[e.task]:[]),f=e=>{let t={ref:e,id:e.id,type:e.type};e.parentRef&&(t.parent=e.parentRef),e.event!==void 0&&(t.event=e.event),e.leaf&&(t.leaf=!0),t.emitted=e.emitted,e.group!==void 0&&(t.traceGroupId=e.group),e.source!==void 0&&(t.source=e.source);for(let e of u)try{e(t)}catch(e){r(`trace logger failed`,e)}},p=e=>typeof s==`function`?s({type:e.type,payload:e.payload}):Math.random()<s,m={task:(e,t)=>{let n={id:++c,root:t?.root??c,parent:t?.id,parentRef:u.length>0?t:void 0,leaf:e.leaf,emitted:l()===t,type:e.type,payload:e.payload,sampled:t?.sampled??p(e),group:P(e)??t?.group};return u.length>0&&n.sampled&&f(n),n},rename:(e,t,n)=>{e.event??=e.type,e.type=t,n!==void 0&&(e.source=n),u.length>0&&e.sampled&&f(e)},report:(e,t,n,r)=>{if(!e.sampled)return;let i={id:e.id,type:e.type,effect:t,phase:n,payload:e.payload};typeof e.parent==`number`&&(i.parentId=e.parent),e.root!==e.id&&(i.rootId=e.root),e.group!==void 0&&(i.traceGroupId=e.group),e.source!==void 0&&(i.source=e.source),n===`error`&&(i.error=r),(!o||o(i))&&a?.(i)},settler:(e,t)=>{if(!e.sampled)return N;let n=!1;return(r,i)=>{n||(n=!0,m.report(e,t,r,i))}},run:(e,t,n,r)=>{if(!e.sampled)return r();let a=m.settler(e,t);m.report(e,t,`start`),i({signal:n},()=>a(`cancel`));let o;try{o=r()}catch(e){throw a(`error`,e),e}return d(o)?Promise.resolve(o).then(e=>(a(`done`),e),e=>{throw a(`error`,e),e}):(a(`done`),o)}};return m};export{j as n,g as r,F as t};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { H as EventMap, c as Scope, l as WithFields, p as Effects } from "./action-creator-
|
|
2
|
-
import { t as BoundOf } from "./plugin-
|
|
1
|
+
import { H as EventMap, c as Scope, l as WithFields, p as Effects } from "./action-creator-DprJV-pN.js";
|
|
2
|
+
import { t as BoundOf } from "./plugin-2d3uuW7o.js";
|
|
3
3
|
//#region src/scope/types.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The slots `scopePlugin` fills for `modulePlugin`. They are not on `Bus`: a bus
|
package/dist/vue.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { H as EventMap, T as EventKey, a as FreeActionCreator, t as ActionCreator, v as Bus } from "./action-creator-
|
|
1
|
+
import { H as EventMap, T as EventKey, a as FreeActionCreator, t as ActionCreator, v as Bus } from "./action-creator-DprJV-pN.js";
|
|
2
2
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
3
3
|
import { t as StateOf } from "./state-of-C19H6BoV.js";
|
|
4
4
|
import { ShallowRef, WatchSource, WatchStopHandle } from "vue";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./context-
|
|
1
|
+
import{n as e}from"./context-Dp_QRXzb.js";const t=Reflect.get(Symbol,`dispose`),n=n=>{let r=new AbortController,i=async(...t)=>{let i=t[0],{ctx:a,unlink:o}=e({event:{type:`withPolicy`,payload:i},parent:{signal:r.signal}});try{return await n(i,a)}finally{o()}},a=e=>{r.abort(e),r=new AbortController},o=Object.assign(i,{cancel:a});return t&&Reflect.set(o,t,()=>a()),o};export{n as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as PayloadOf, H as EventMap, q as Task } from "./action-creator-
|
|
1
|
+
import { G as PayloadOf, H as EventMap, q as Task } from "./action-creator-DprJV-pN.js";
|
|
2
2
|
//#region src/policies/with-policy.d.ts
|
|
3
3
|
/** What `withPolicy` returns: the task as a plain function that can be cancelled. */
|
|
4
4
|
type PolicyFunction<P, R> = {
|