@dudousxd/nestjs-diagnostics 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @dudousxd/nestjs-diagnostics
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4](https://github.com/DavideCarvalho/nestjs-diagnostics/pull/4) [`2d9b817`](https://github.com/DavideCarvalho/nestjs-diagnostics/commit/2d9b817158b058e0c6413acfa8c2b3acd3728a6a) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Make `emit()`/`getChannel()` ~11x cheaper on the hot path by memoizing the
8
+ resolved channel per `(lib, event)` pair. Previously every call re-built the
9
+ `aviary:<lib>:<event>` string, re-looked-up the node channel, and re-checked the
10
+ registry — ~174 ns/op even when nobody was subscribed. Now the first call for a
11
+ pair pays that cost and every subsequent call is two `Map.get`s returning the same
12
+ channel object (~16 ns/op; the no-subscriber path allocates nothing). The
13
+ consumer-side pattern of caching the channel and gating on `hasSubscribers` before
14
+ calling `emit` (~4 ns/op) stays the cheapest and remains recommended.
15
+
16
+ No API or behavior change: channel identity, registry discovery
17
+ (`registeredChannels`/`onChannelRegistered`), `hasSubscribers` gating,
18
+ `opts.traceId` precedence, and never-throw are all unchanged.
19
+
20
+ ## 0.2.1
21
+
22
+ ### Patch Changes
23
+
24
+ - [#2](https://github.com/DavideCarvalho/nestjs-diagnostics/pull/2) [`620c4bc`](https://github.com/DavideCarvalho/nestjs-diagnostics/commit/620c4bc08ce61f7059a2dd6ce2cdc19f2d5388a5) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Harden the cross-copy state to process-global singletons (keyed by `Symbol.for`
25
+ on `globalThis`):
26
+
27
+ - the channel **registry** (`registeredChannels` / `onChannelRegistered`), so the
28
+ generic Telescope watcher discovers every emitted channel; and
29
+ - the **context accessor** (`setContextAccessor` / `resolveTraceId`), so a `traceId`
30
+ registered through one copy is visible to `emit()` in another.
31
+
32
+ This matters when more than one physical copy of the package is loaded — divergent
33
+ version ranges that pnpm cannot dedupe into a single instance. The
34
+ `node:diagnostics_channel` objects were already process-global; this makes their
35
+ discovery registry and the trace accessor equally global. No API change.
36
+
3
37
  ## 0.2.0
4
38
 
5
39
  ### Minor Changes
package/dist/channel.d.ts CHANGED
@@ -13,6 +13,10 @@ export declare function channelName(lib: string, event: string): string;
13
13
  * `.hasSubscribers` is the cheap gate before building an envelope. Touching the
14
14
  * channel also records its name in the {@link registerChannel registry} so a
15
15
  * generic observer can discover it.
16
+ *
17
+ * Memoized via {@link channelCache}: only the first call for a `(lib, event)`
18
+ * pair builds the name, resolves the channel, and registers it; subsequent calls
19
+ * return the cached object after two map lookups.
16
20
  */
17
21
  export declare function getChannel(lib: string, event: string): Channel;
18
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAA4B,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG7E,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAK9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAgB3F"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAA4B,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG7E,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAqBD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAc9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAgB3F"}
package/dist/channel.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import diagnostics_channel from 'node:diagnostics_channel';
2
2
  import { resolveTraceId } from './context-accessor.js';
3
- import { registerChannel } from './registry.js';
3
+ import { onRegistryReset, registerChannel } from './registry.js';
4
4
  /** The prefix all channels created by this convention share. */
5
5
  export const CHANNEL_PREFIX = 'aviary';
6
6
  /**
@@ -10,17 +10,49 @@ export const CHANNEL_PREFIX = 'aviary';
10
10
  export function channelName(lib, event) {
11
11
  return `${CHANNEL_PREFIX}:${lib}:${event}`;
12
12
  }
13
+ /**
14
+ * Per-`(lib, event)` cache of the resolved {@link Channel}, keyed by `lib` then
15
+ * `event`. The first {@link getChannel}/{@link emit} for a pair pays the string
16
+ * concat + `diagnostics_channel.channel()` lookup + registry insert; every call
17
+ * after that is a pair of `Map.get`s and returns the SAME object — no string is
18
+ * allocated on the steady state. A nested map (rather than one keyed by the full
19
+ * `aviary:<lib>:<event>` name) is what lets us skip the concat entirely.
20
+ *
21
+ * Node already returns a process-stable {@link Channel} per name, so caching it
22
+ * here changes nothing observable: `getChannel(a,b)` still returns
23
+ * `diagnostics_channel.channel('aviary:a:b')`. The registry is still fed exactly
24
+ * once per pair (on the cache miss), so discovery is unchanged.
25
+ */
26
+ const channelCache = new Map();
27
+ // Drop the memo cache whenever the registry is reset (test-only), so the next
28
+ // getChannel re-registers every channel. See onRegistryReset in registry.ts.
29
+ onRegistryReset(() => channelCache.clear());
13
30
  /**
14
31
  * The memoized `node:diagnostics_channel` for a `<lib>`/`<event>` pair. Node
15
32
  * returns the same {@link Channel} object for the same name, so reading
16
33
  * `.hasSubscribers` is the cheap gate before building an envelope. Touching the
17
34
  * channel also records its name in the {@link registerChannel registry} so a
18
35
  * generic observer can discover it.
36
+ *
37
+ * Memoized via {@link channelCache}: only the first call for a `(lib, event)`
38
+ * pair builds the name, resolves the channel, and registers it; subsequent calls
39
+ * return the cached object after two map lookups.
19
40
  */
20
41
  export function getChannel(lib, event) {
42
+ let byEvent = channelCache.get(lib);
43
+ if (byEvent !== undefined) {
44
+ const cached = byEvent.get(event);
45
+ if (cached !== undefined)
46
+ return cached;
47
+ }
48
+ else {
49
+ byEvent = new Map();
50
+ channelCache.set(lib, byEvent);
51
+ }
21
52
  const name = channelName(lib, event);
22
53
  const channel = diagnostics_channel.channel(name);
23
54
  registerChannel(name);
55
+ byEvent.set(event, channel);
24
56
  return channel;
25
57
  }
26
58
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAqC,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,GAAG,cAAc,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,KAAa;IACnD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,KAAa,EAAE,OAAgB,EAAE,IAAkB;IACnF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,CAAC,cAAc;QAAE,OAAO;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,cAAc,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAoB;YAChC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,GAAG;YACH,KAAK;YACL,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,OAAO;SACR,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAqC,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGjE,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,GAAG,cAAc,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE7D,8EAA8E;AAC9E,6EAA6E;AAC7E,eAAe,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,KAAa;IACnD,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,KAAa,EAAE,OAAgB,EAAE,IAAkB;IACnF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,CAAC,cAAc;QAAE,OAAO;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,cAAc,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAoB;YAChC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,GAAG;YACH,KAAK;YACL,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,OAAO;SACR,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-accessor.d.ts","sourceRoot":"","sources":["../src/context-accessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,mGAAmG;AACnG,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,OAAO,IAAI,MAAM,GAAG,SAAS,CAAC;IAC9B,mFAAmF;IACnF,QAAQ,IAAI,MAAM,GAAG,SAAS,CAAC;IAC/B,0EAA0E;IAC1E,OAAO,IAAI,OAAO,GAAG,SAAS,CAAC;IAC/B,qEAAqE;IACrE,GAAG,IAAI,YAAY,GAAG,SAAS,CAAC;CACjC;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,eAAkD,CAAC;AAUhF,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAErE;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAE3D;AAED,iFAAiF;AACjF,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAOnD"}
1
+ {"version":3,"file":"context-accessor.d.ts","sourceRoot":"","sources":["../src/context-accessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,mGAAmG;AACnG,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,OAAO,IAAI,MAAM,GAAG,SAAS,CAAC;IAC9B,mFAAmF;IACnF,QAAQ,IAAI,MAAM,GAAG,SAAS,CAAC;IAC/B,0EAA0E;IAC1E,OAAO,IAAI,OAAO,GAAG,SAAS,CAAC;IAC/B,qEAAqE;IACrE,GAAG,IAAI,YAAY,GAAG,SAAS,CAAC;CACjC;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,eAAkD,CAAC;AAwBhF,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAErE;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAE3D;AAED,iFAAiF;AACjF,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAQnD"}
@@ -5,23 +5,21 @@
5
5
  * of the `@dudousxd/nestjs-*` family wires the optional context peer.
6
6
  */
7
7
  export const CONTEXT_ACCESSOR = Symbol.for('@dudousxd/nestjs-context:accessor');
8
- /**
9
- * Module-level accessor used by {@link emit} to auto-fill `traceId`. `null` until
10
- * an app calls {@link setContextAccessor} (e.g. from a Nest module's `onModuleInit`
11
- * after resolving the optional {@link CONTEXT_ACCESSOR} provider). Kept out of
12
- * the hot path: when unset, `emit` simply leaves `traceId` undefined.
13
- */
14
- let accessor = null;
8
+ const ACCESSOR_KEY = Symbol.for('@dudousxd/nestjs-diagnostics:accessor');
9
+ const accessorStore = globalThis;
10
+ const accessorHolder = accessorStore[ACCESSOR_KEY] ?? { current: null };
11
+ accessorStore[ACCESSOR_KEY] = accessorHolder;
15
12
  /** Register (or clear, with `null`) the accessor {@link emit} reads `traceId` from. */
16
13
  export function setContextAccessor(next) {
17
- accessor = next;
14
+ accessorHolder.current = next;
18
15
  }
19
16
  /** The currently registered accessor, or `null`. */
20
17
  export function getContextAccessor() {
21
- return accessor;
18
+ return accessorHolder.current;
22
19
  }
23
20
  /** Resolve the current trace id from the registered accessor, never throwing. */
24
21
  export function resolveTraceId() {
22
+ const accessor = accessorHolder.current;
25
23
  if (accessor == null)
26
24
  return undefined;
27
25
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"context-accessor.js","sourceRoot":"","sources":["../src/context-accessor.ts"],"names":[],"mappings":"AAgCA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAEhF;;;;;GAKG;AACH,IAAI,QAAQ,GAA2B,IAAI,CAAC;AAE5C,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,IAA4B;IAC7D,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,kBAAkB;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc;IAC5B,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"context-accessor.js","sourceRoot":"","sources":["../src/context-accessor.ts"],"names":[],"mappings":"AAgCA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAmBhF,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACzE,MAAM,aAAa,GAAG,UAAqE,CAAC;AAC5F,MAAM,cAAc,GAAmB,aAAa,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACxF,aAAa,CAAC,YAAY,CAAC,GAAG,cAAc,CAAC;AAE7C,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,IAA4B;IAC7D,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;AAChC,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,kBAAkB;IAChC,OAAO,cAAc,CAAC,OAAO,CAAC;AAChC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc;IAC5B,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC;IACxC,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -31,6 +31,11 @@ export declare function registeredChannels(): string[];
31
31
  * ```
32
32
  */
33
33
  export declare function onChannelRegistered(cb: (name: string) => void): () => void;
34
+ /**
35
+ * Register a callback run by {@link resetRegistry}. Used internally by
36
+ * {@link getChannel}'s memo cache; not part of the public contract.
37
+ */
38
+ export declare function onRegistryReset(cb: () => void): void;
34
39
  /**
35
40
  * Test-only: forget every registered channel and listener. Not part of the
36
41
  * public contract — exposed so suites can assert registration in isolation.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUlD;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAK1E;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAGpC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6BH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUlD;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAK1E;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAUpC"}
package/dist/registry.js CHANGED
@@ -9,10 +9,14 @@
9
9
  * provides both: {@link registeredChannels} for the current set and
10
10
  * {@link onChannelRegistered} for future additions.
11
11
  */
12
- /** Every channel name seen so far, in insertion order. */
13
- const channels = new Set();
14
- /** Listeners notified once per newly-registered channel name. */
15
- const listeners = new Set();
12
+ const REGISTRY_KEY = Symbol.for('@dudousxd/nestjs-diagnostics:registry');
13
+ const globalStore = globalThis;
14
+ const registry = globalStore[REGISTRY_KEY] ?? {
15
+ channels: new Set(),
16
+ listeners: new Set(),
17
+ };
18
+ globalStore[REGISTRY_KEY] = registry;
19
+ const { channels, listeners } = registry;
16
20
  /**
17
21
  * Record a channel name, notifying {@link onChannelRegistered} listeners the first
18
22
  * time it is seen. Idempotent: re-registering an existing name is a no-op.
@@ -54,6 +58,22 @@ export function onChannelRegistered(cb) {
54
58
  listeners.delete(cb);
55
59
  };
56
60
  }
61
+ /**
62
+ * Hooks run by {@link resetRegistry} so other modules can drop registry-derived
63
+ * caches in lockstep. {@link getChannel} memoizes channels and only registers a
64
+ * name on a cache MISS; if `resetRegistry` cleared `channels` without clearing
65
+ * that cache, an already-cached channel would never re-register and would vanish
66
+ * from discovery. Registering its cache-clear here keeps the test-only reset
67
+ * exact: after a reset, the next `getChannel`/`emit` re-registers every channel.
68
+ */
69
+ const resetHooks = new Set();
70
+ /**
71
+ * Register a callback run by {@link resetRegistry}. Used internally by
72
+ * {@link getChannel}'s memo cache; not part of the public contract.
73
+ */
74
+ export function onRegistryReset(cb) {
75
+ resetHooks.add(cb);
76
+ }
57
77
  /**
58
78
  * Test-only: forget every registered channel and listener. Not part of the
59
79
  * public contract — exposed so suites can assert registration in isolation.
@@ -61,5 +81,13 @@ export function onChannelRegistered(cb) {
61
81
  export function resetRegistry() {
62
82
  channels.clear();
63
83
  listeners.clear();
84
+ for (const hook of resetHooks) {
85
+ try {
86
+ hook();
87
+ }
88
+ catch {
89
+ // A misbehaving reset hook must never break the reset itself.
90
+ }
91
+ }
64
92
  }
65
93
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,0DAA0D;AAC1D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;AAEnC,iEAAiE;AACjE,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC/B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;IACH,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAA0B;IAC5D,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjB,SAAS,CAAC,KAAK,EAAE,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAoBH,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACzE,MAAM,WAAW,GAAG,UAA+D,CAAC;AACpF,MAAM,QAAQ,GAAa,WAAW,CAAC,YAAY,CAAC,IAAI;IACtD,QAAQ,EAAE,IAAI,GAAG,EAAU;IAC3B,SAAS,EAAE,IAAI,GAAG,EAA0B;CAC7C,CAAC;AACF,WAAW,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAC;AACrC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC/B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;IACH,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAA0B;IAC5D,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,IAAI,GAAG,EAAc,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAAc;IAC5C,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-diagnostics",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A standard convention for @dudousxd/nestjs-* libs to emit observability events over node:diagnostics_channel.",
5
5
  "license": "MIT",
6
6
  "repository": {