@vielzeug/herald 1.0.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/README.md +92 -0
- package/dist/_delegate.cjs +2 -0
- package/dist/_delegate.cjs.map +1 -0
- package/dist/_delegate.d.ts +2 -0
- package/dist/_delegate.d.ts.map +1 -0
- package/dist/_delegate.js +30 -0
- package/dist/_delegate.js.map +1 -0
- package/dist/_dev.cjs +2 -0
- package/dist/_dev.cjs.map +1 -0
- package/dist/_dev.d.ts +2 -0
- package/dist/_dev.d.ts.map +1 -0
- package/dist/_dev.js +9 -0
- package/dist/_dev.js.map +1 -0
- package/dist/_prototype.cjs +2 -0
- package/dist/_prototype.cjs.map +1 -0
- package/dist/_prototype.d.ts +2 -0
- package/dist/_prototype.d.ts.map +1 -0
- package/dist/_prototype.js +13 -0
- package/dist/_prototype.js.map +1 -0
- package/dist/_safe.cjs +2 -0
- package/dist/_safe.cjs.map +1 -0
- package/dist/_safe.d.ts +2 -0
- package/dist/_safe.d.ts.map +1 -0
- package/dist/_safe.js +15 -0
- package/dist/_safe.js.map +1 -0
- package/dist/behavior-bus.cjs +2 -0
- package/dist/behavior-bus.cjs.map +1 -0
- package/dist/behavior-bus.d.ts +19 -0
- package/dist/behavior-bus.d.ts.map +1 -0
- package/dist/behavior-bus.js +57 -0
- package/dist/behavior-bus.js.map +1 -0
- package/dist/bus.cjs +2 -0
- package/dist/bus.cjs.map +1 -0
- package/dist/bus.d.ts +17 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +231 -0
- package/dist/bus.js.map +1 -0
- package/dist/devtools.cjs +2 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.ts +55 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +27 -0
- package/dist/devtools.js.map +1 -0
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/herald.cjs +2 -0
- package/dist/herald.cjs.map +1 -0
- package/dist/herald.iife.js +2 -0
- package/dist/herald.iife.js.map +1 -0
- package/dist/herald.js +2 -0
- package/dist/herald.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/pipe.cjs +2 -0
- package/dist/pipe.cjs.map +1 -0
- package/dist/pipe.d.ts +24 -0
- package/dist/pipe.d.ts.map +1 -0
- package/dist/pipe.js +19 -0
- package/dist/pipe.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/testing.cjs +2 -0
- package/dist/testing/testing.cjs.map +1 -0
- package/dist/testing/testing.d.ts +18 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/testing.js +44 -0
- package/dist/testing/testing.js.map +1 -0
- package/dist/testing.cjs +1 -0
- package/dist/testing.js +2 -0
- package/dist/types.d.ts +277 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @vielzeug/herald
|
|
2
|
+
|
|
3
|
+
> Zero-dependency typed event bus with subscribe/emit, wait(), async streams, AbortSignal support, bus piping, and test helpers.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vielzeug/herald) [](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
<details>
|
|
8
|
+
<summary>Quick Reference</summary>
|
|
9
|
+
|
|
10
|
+
**Package:** `@vielzeug/herald` · **Category:** Events
|
|
11
|
+
|
|
12
|
+
**Key exports:** `createBus`, `pipeEvents`, `createTestBus`
|
|
13
|
+
|
|
14
|
+
**When to use:** Decoupled inter-module communication via a typed event bus. Supports subscribe/emit, one-time await, async iteration, event piping, and AbortSignal lifecycle management.
|
|
15
|
+
|
|
16
|
+
**Related:** [@vielzeug/ripple](https://vielzeug.dev/ripple/) · [@vielzeug/wayfinder](https://vielzeug.dev/wayfinder/) · [@vielzeug/familiar](https://vielzeug.dev/familiar/)
|
|
17
|
+
|
|
18
|
+
</details>
|
|
19
|
+
|
|
20
|
+
`@vielzeug/herald` is part of Vielzeug and ships as a zero-dependency TypeScript package with ESM+CJS output.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
pnpm add @vielzeug/herald
|
|
26
|
+
npm install @vielzeug/herald
|
|
27
|
+
yarn add @vielzeug/herald
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { BusDisposedError, createBus, pipeEvents } from '@vielzeug/herald';
|
|
34
|
+
|
|
35
|
+
type AppEvents = {
|
|
36
|
+
'user:login': { userId: string; email: string };
|
|
37
|
+
'user:logout': void;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const bus = createBus<AppEvents>();
|
|
41
|
+
|
|
42
|
+
// Subscribe
|
|
43
|
+
bus.on('user:login', ({ userId }) => {
|
|
44
|
+
console.log('Logged in:', userId);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Emit
|
|
48
|
+
bus.emit('user:login', { email: 'alice@example.com', userId: '42' });
|
|
49
|
+
bus.emit('user:logout');
|
|
50
|
+
|
|
51
|
+
// Await the next event
|
|
52
|
+
const nextLogin = await bus.wait('user:login');
|
|
53
|
+
|
|
54
|
+
// Race multiple events — result is a discriminated union
|
|
55
|
+
const nextSessionEvent = await bus.waitAny(['user:login', 'user:logout'] as const);
|
|
56
|
+
if (nextSessionEvent.event === 'user:login') {
|
|
57
|
+
console.log(nextSessionEvent.payload.userId);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Stream all future emits as an async generator
|
|
61
|
+
for await (const payload of bus.events('user:login', { signal: AbortSignal.timeout(5_000) })) {
|
|
62
|
+
console.log(payload.email);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Forward selected events from one bus to another
|
|
66
|
+
const auditBus = createBus<AppEvents>();
|
|
67
|
+
const unpipe = pipeEvents(bus, auditBus, ['user:login', 'user:logout']);
|
|
68
|
+
// unpipe() — stop forwarding; also stops automatically when either bus disposes
|
|
69
|
+
|
|
70
|
+
// Disposal signal — fire external cleanup when the bus is torn down
|
|
71
|
+
otherBus.on('count', handler, { signal: bus.disposalSignal });
|
|
72
|
+
|
|
73
|
+
// Handle disposal in async code
|
|
74
|
+
try {
|
|
75
|
+
await bus.wait('user:login', { signal: AbortSignal.timeout(1_000) });
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err instanceof BusDisposedError) {
|
|
78
|
+
console.log('Bus was disposed');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Documentation
|
|
84
|
+
|
|
85
|
+
- [Overview](https://vielzeug.dev/herald/)
|
|
86
|
+
- [Usage Guide](https://vielzeug.dev/herald/usage)
|
|
87
|
+
- [API Reference](https://vielzeug.dev/herald/api)
|
|
88
|
+
- [Examples](https://vielzeug.dev/herald/examples)
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e){let t={dispose:()=>e.dispose(),emit:e.emit,eventNames:e.eventNames,events:e.events,listenerCount:e.listenerCount,on:e.on,onAny:e.onAny,once:e.once,[Symbol.dispose]:()=>e.dispose(),wait:e.wait,waitAny:e.waitAny,wildcardCount:e.wildcardCount};return Object.defineProperty(t,"disposalSignal",{configurable:!0,enumerable:!0,get:()=>e.disposalSignal}),Object.defineProperty(t,"disposed",{configurable:!0,enumerable:!0,get:()=>e.disposed}),t}exports.makeBusDelegate=e;
|
|
2
|
+
//# sourceMappingURL=_delegate.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_delegate.cjs","names":[],"sources":["../src/_delegate.ts"],"sourcesContent":["import type { Bus, EventMap } from './types';\n\n/**\n * Creates a mutable delegation object that forwards every Bus<T> method and getter to `bus`.\n * Callers can overwrite individual properties on the returned object to override specific\n * behaviour (e.g. `delegate.emit = customEmit`) without repeating the full delegation boilerplate\n * for the remaining ~14 methods.\n *\n * Getters (`disposed`, `disposalSignal`) are defined via `Object.defineProperty` so they remain\n * live — reading them always queries the underlying bus rather than snapshotting the value at\n * creation time.\n *\n * @internal Not re-exported from the public index.\n */\nexport function makeBusDelegate<T extends EventMap>(bus: Bus<T>): Bus<T> {\n type BusMethods<T extends EventMap> = Omit<Bus<T>, 'disposed' | 'disposalSignal'>;\n\n const delegate = {\n dispose: () => bus.dispose(),\n emit: bus.emit,\n eventNames: bus.eventNames,\n events: bus.events,\n listenerCount: bus.listenerCount,\n on: bus.on,\n onAny: bus.onAny,\n once: bus.once,\n [Symbol.dispose]: () => bus.dispose(),\n wait: bus.wait,\n waitAny: bus.waitAny,\n wildcardCount: bus.wildcardCount,\n } satisfies BusMethods<T> as Bus<T>; // satisfies catches any missing method; cast is safe — getters added below.\n\n Object.defineProperty(delegate, 'disposalSignal', {\n configurable: true,\n enumerable: true,\n get: () => bus.disposalSignal,\n });\n\n Object.defineProperty(delegate, 'disposed', {\n configurable: true,\n enumerable: true,\n get: () => bus.disposed,\n });\n\n return delegate;\n}\n"],"mappings":"AAcA,SAAgB,EAAoC,EAAqB,CAGvE,IAAM,EAAW,CACf,YAAe,EAAI,QAAQ,EAC3B,KAAM,EAAI,KACV,WAAY,EAAI,WAChB,OAAQ,EAAI,OACZ,cAAe,EAAI,cACnB,GAAI,EAAI,GACR,MAAO,EAAI,MACX,KAAM,EAAI,MACT,OAAO,aAAgB,EAAI,QAAQ,EACpC,KAAM,EAAI,KACV,QAAS,EAAI,QACb,cAAe,EAAI,aACrB,EAcA,OAZA,OAAO,eAAe,EAAU,iBAAkB,CAChD,aAAc,GACd,WAAY,GACZ,QAAW,EAAI,cACjB,CAAC,EAED,OAAO,eAAe,EAAU,WAAY,CAC1C,aAAc,GACd,WAAY,GACZ,QAAW,EAAI,QACjB,CAAC,EAEM,CACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_delegate.d.ts","sourceRoot":"","sources":["../src/_delegate.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/_delegate.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
let t = {
|
|
4
|
+
dispose: () => e.dispose(),
|
|
5
|
+
emit: e.emit,
|
|
6
|
+
eventNames: e.eventNames,
|
|
7
|
+
events: e.events,
|
|
8
|
+
listenerCount: e.listenerCount,
|
|
9
|
+
on: e.on,
|
|
10
|
+
onAny: e.onAny,
|
|
11
|
+
once: e.once,
|
|
12
|
+
[Symbol.dispose]: () => e.dispose(),
|
|
13
|
+
wait: e.wait,
|
|
14
|
+
waitAny: e.waitAny,
|
|
15
|
+
wildcardCount: e.wildcardCount
|
|
16
|
+
};
|
|
17
|
+
return Object.defineProperty(t, "disposalSignal", {
|
|
18
|
+
configurable: !0,
|
|
19
|
+
enumerable: !0,
|
|
20
|
+
get: () => e.disposalSignal
|
|
21
|
+
}), Object.defineProperty(t, "disposed", {
|
|
22
|
+
configurable: !0,
|
|
23
|
+
enumerable: !0,
|
|
24
|
+
get: () => e.disposed
|
|
25
|
+
}), t;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { e as makeBusDelegate };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=_delegate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_delegate.js","names":[],"sources":["../src/_delegate.ts"],"sourcesContent":["import type { Bus, EventMap } from './types';\n\n/**\n * Creates a mutable delegation object that forwards every Bus<T> method and getter to `bus`.\n * Callers can overwrite individual properties on the returned object to override specific\n * behaviour (e.g. `delegate.emit = customEmit`) without repeating the full delegation boilerplate\n * for the remaining ~14 methods.\n *\n * Getters (`disposed`, `disposalSignal`) are defined via `Object.defineProperty` so they remain\n * live — reading them always queries the underlying bus rather than snapshotting the value at\n * creation time.\n *\n * @internal Not re-exported from the public index.\n */\nexport function makeBusDelegate<T extends EventMap>(bus: Bus<T>): Bus<T> {\n type BusMethods<T extends EventMap> = Omit<Bus<T>, 'disposed' | 'disposalSignal'>;\n\n const delegate = {\n dispose: () => bus.dispose(),\n emit: bus.emit,\n eventNames: bus.eventNames,\n events: bus.events,\n listenerCount: bus.listenerCount,\n on: bus.on,\n onAny: bus.onAny,\n once: bus.once,\n [Symbol.dispose]: () => bus.dispose(),\n wait: bus.wait,\n waitAny: bus.waitAny,\n wildcardCount: bus.wildcardCount,\n } satisfies BusMethods<T> as Bus<T>; // satisfies catches any missing method; cast is safe — getters added below.\n\n Object.defineProperty(delegate, 'disposalSignal', {\n configurable: true,\n enumerable: true,\n get: () => bus.disposalSignal,\n });\n\n Object.defineProperty(delegate, 'disposed', {\n configurable: true,\n enumerable: true,\n get: () => bus.disposed,\n });\n\n return delegate;\n}\n"],"mappings":";AAcA,SAAgB,EAAoC,GAAqB;CAGvE,IAAM,IAAW;EACf,eAAe,EAAI,QAAQ;EAC3B,MAAM,EAAI;EACV,YAAY,EAAI;EAChB,QAAQ,EAAI;EACZ,eAAe,EAAI;EACnB,IAAI,EAAI;EACR,OAAO,EAAI;EACX,MAAM,EAAI;GACT,OAAO,gBAAgB,EAAI,QAAQ;EACpC,MAAM,EAAI;EACV,SAAS,EAAI;EACb,eAAe,EAAI;CACrB;CAcA,OAZA,OAAO,eAAe,GAAU,kBAAkB;EAChD,cAAc;EACd,YAAY;EACZ,WAAW,EAAI;CACjB,CAAC,GAED,OAAO,eAAe,GAAU,YAAY;EAC1C,cAAc;EACd,YAAY;EACZ,WAAW,EAAI;CACjB,CAAC,GAEM;AACT"}
|
package/dist/_dev.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n"],"mappings":"AAAA,IAAM,EAAQ,CAAE,WAA6C,gBAG7D,SAAgB,EAAK,EAAmB,CAClC,GAAO,QAAQ,KAAK,sBAAsB,GAAK,CACrD"}
|
package/dist/_dev.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_dev.d.ts","sourceRoot":"","sources":["../src/_dev.ts"],"names":[],"mappings":""}
|
package/dist/_dev.js
ADDED
package/dist/_dev.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n"],"mappings":";AAAA,IAAM,IAAQ,CAAE,WAA6C;AAG7D,SAAgB,EAAK,GAAmB;CACtC,AAAI,KAAO,QAAQ,KAAK,sBAAsB,GAAK;AACrD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_prototype.cjs","names":[],"sources":["../src/_prototype.ts"],"sourcesContent":["/**\n * Property names that must never be used as a bracket-assignment key on a plain object literal —\n * `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n * and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n * `prototype` are excluded defensively for the same class of risk.\n *\n * Used when copying event-name-keyed `Map` entries into a plain object (`behavior-bus.ts`'s\n * `snapshot()`, `testing/testing.ts`'s `allEmitted()`) — event names ultimately come from a\n * caller-supplied `EventMap` type, but nothing prevents a caller from wiring in a\n * dynamically-determined (e.g. user-supplied) event name at runtime.\n *\n * @internal\n */\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** @internal */\nexport function isUnsafeObjectKey(key: string): boolean {\n return UNSAFE_OBJECT_KEYS.has(key);\n}\n"],"mappings":"AAaA,IAAM,EAAqB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAG5E,SAAgB,EAAkB,EAAsB,CACtD,OAAO,EAAmB,IAAI,CAAG,CACnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_prototype.d.ts","sourceRoot":"","sources":["../src/_prototype.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/_prototype.ts
|
|
2
|
+
var e = /* @__PURE__ */ new Set([
|
|
3
|
+
"__proto__",
|
|
4
|
+
"constructor",
|
|
5
|
+
"prototype"
|
|
6
|
+
]);
|
|
7
|
+
function t(t) {
|
|
8
|
+
return e.has(t);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { t as isUnsafeObjectKey };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=_prototype.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_prototype.js","names":[],"sources":["../src/_prototype.ts"],"sourcesContent":["/**\n * Property names that must never be used as a bracket-assignment key on a plain object literal —\n * `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n * and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n * `prototype` are excluded defensively for the same class of risk.\n *\n * Used when copying event-name-keyed `Map` entries into a plain object (`behavior-bus.ts`'s\n * `snapshot()`, `testing/testing.ts`'s `allEmitted()`) — event names ultimately come from a\n * caller-supplied `EventMap` type, but nothing prevents a caller from wiring in a\n * dynamically-determined (e.g. user-supplied) event name at runtime.\n *\n * @internal\n */\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** @internal */\nexport function isUnsafeObjectKey(key: string): boolean {\n return UNSAFE_OBJECT_KEYS.has(key);\n}\n"],"mappings":";AAaA,IAAM,oBAAqB,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAG5E,SAAgB,EAAkB,GAAsB;CACtD,OAAO,EAAmB,IAAI,CAAG;AACnC"}
|
package/dist/_safe.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_safe.cjs","names":[],"sources":["../src/_safe.ts"],"sourcesContent":["/**\n * Result of a {@link callSafely} invocation. Discriminated on `threw` so a caller can tell\n * \"didn't throw\" apart from \"threw `undefined`\" — inspecting `err` alone can't make that call.\n *\n * @internal\n */\nexport type SafeCallResult = { err: unknown; threw: true } | { threw: false };\n\n/**\n * Calls `fn()`, guarding against a throw.\n *\n * - If `fn()` throws and `onError` is provided, forwards the error to `onError` and reports\n * `{ threw: false }` — the caller treats this call as handled.\n * - If `fn()` throws and no `onError` is provided, the error is **not** rethrown here — it is\n * returned as `{ threw: true, err }` so the caller can decide when (or whether) to rethrow,\n * e.g. after finishing a batch of independent calls.\n *\n * @internal\n */\nexport function callSafely(fn: () => void, onError?: (err: unknown) => void): SafeCallResult {\n try {\n fn();\n\n return { threw: false };\n } catch (err) {\n if (onError) {\n onError(err);\n\n return { threw: false };\n }\n\n return { err, threw: true };\n }\n}\n"],"mappings":"AAmBA,SAAgB,EAAW,EAAgB,EAAkD,CAC3F,GAAI,CAGF,OAFA,EAAG,EAEI,CAAE,MAAO,EAAM,CACxB,OAAS,EAAK,CAOZ,OANI,GACF,EAAQ,CAAG,EAEJ,CAAE,MAAO,EAAM,GAGjB,CAAE,MAAK,MAAO,EAAK,CAC5B,CACF"}
|
package/dist/_safe.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_safe.d.ts","sourceRoot":"","sources":["../src/_safe.ts"],"names":[],"mappings":""}
|
package/dist/_safe.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/_safe.ts
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
try {
|
|
4
|
+
return e(), { threw: !1 };
|
|
5
|
+
} catch (e) {
|
|
6
|
+
return t ? (t(e), { threw: !1 }) : {
|
|
7
|
+
err: e,
|
|
8
|
+
threw: !0
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { e as callSafely };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=_safe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_safe.js","names":[],"sources":["../src/_safe.ts"],"sourcesContent":["/**\n * Result of a {@link callSafely} invocation. Discriminated on `threw` so a caller can tell\n * \"didn't throw\" apart from \"threw `undefined`\" — inspecting `err` alone can't make that call.\n *\n * @internal\n */\nexport type SafeCallResult = { err: unknown; threw: true } | { threw: false };\n\n/**\n * Calls `fn()`, guarding against a throw.\n *\n * - If `fn()` throws and `onError` is provided, forwards the error to `onError` and reports\n * `{ threw: false }` — the caller treats this call as handled.\n * - If `fn()` throws and no `onError` is provided, the error is **not** rethrown here — it is\n * returned as `{ threw: true, err }` so the caller can decide when (or whether) to rethrow,\n * e.g. after finishing a batch of independent calls.\n *\n * @internal\n */\nexport function callSafely(fn: () => void, onError?: (err: unknown) => void): SafeCallResult {\n try {\n fn();\n\n return { threw: false };\n } catch (err) {\n if (onError) {\n onError(err);\n\n return { threw: false };\n }\n\n return { err, threw: true };\n }\n}\n"],"mappings":";AAmBA,SAAgB,EAAW,GAAgB,GAAkD;CAC3F,IAAI;EAGF,OAFA,EAAG,GAEI,EAAE,OAAO,GAAM;CACxB,SAAS,GAAK;EAOZ,OANI,KACF,EAAQ,CAAG,GAEJ,EAAE,OAAO,GAAM,KAGjB;GAAE;GAAK,OAAO;EAAK;CAC5B;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./_delegate.cjs"),t=require("./_prototype.cjs"),n=require("./_safe.cjs"),r=require("./bus.cjs");function i(i,a){let o=new Map(Object.entries(i??{}).filter(([,e])=>e!==void 0)),s=r.createBus({...a,_onDispatch:(e,t)=>{o.set(e,t)}});function c(e,t,r){let i=n.callSafely(()=>e(r),a?.onError?e=>a.onError({err:e,event:t,payload:r,timestamp:Date.now()}):void 0);if(i.threw)throw i.err}function l(e,t,n){if(s.disposed||n?.signal?.aborted)return r.noop;if(o.has(e)){let i=o.get(e);if(n?.once)return c(t,e,i),r.noop;c(t,e,i)}return s.on(e,t,n)}function u(e,t,n){return l(e,t,{once:!0,signal:n?.signal})}function d(e){return o.has(e)?o.get(e):void 0}function f(e){e===void 0?o.clear():o.delete(e)}function p(){let e={};for(let[n,r]of o)t.isUnsafeObjectKey(n)||(e[n]=r);return e}function m(){s.dispose(),o.clear()}let h=e.makeBusDelegate(s);return h.current=d,h.dispose=m,h.on=l,h.once=u,h.reset=f,h.snapshot=p,h[Symbol.dispose]=m,h}exports.createBehaviorBus=i;
|
|
2
|
+
//# sourceMappingURL=behavior-bus.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior-bus.cjs","names":[],"sources":["../src/behavior-bus.ts"],"sourcesContent":["import type { InternalBusOptions } from './bus';\nimport type {\n BehaviorBus,\n BehaviorBusOptions,\n BehaviorInitial,\n EmissionErrorContext,\n EventKey,\n EventMap,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n} from './types';\n\nimport { makeBusDelegate } from './_delegate';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { callSafely } from './_safe';\nimport { createBus, noop } from './bus';\n\n/**\n * Creates a bus that replays the last known value for each event to new subscribers.\n *\n * When a listener subscribes via `on()` or `once()`, it immediately receives the current\n * buffered value for that event (if any have been emitted or were provided as initial values).\n * `events()`, `wait()`, and `waitAny()` behave like a regular bus — no replay.\n *\n * @param initial - Optional map of event names to their starting values.\n * @param options - Standard bus options.\n *\n * @example\n * const bus = createBehaviorBus<{ count: number }>({ count: 0 });\n * bus.on('count', (n) => console.log(n)); // logs 0 immediately\n * bus.emit('count', 1);\n * bus.on('count', (n) => console.log(n)); // logs 1 immediately (latest value)\n */\nexport function createBehaviorBus<T extends EventMap>(\n initial?: BehaviorInitial<T>,\n options?: BehaviorBusOptions<T>,\n): BehaviorBus<T> {\n // Flat buffer: one value per event key.\n // Seeded from initial values; updated via _onDispatch when dispatch actually runs.\n const buffers = new Map<string, unknown>(Object.entries(initial ?? {}).filter(([, v]) => v !== undefined));\n\n // _onDispatch fires after middleware passes (dispatch guaranteed to run).\n // This replaces the sentinel-middleware + mutable-flag pattern.\n const bus = createBus<T>({\n ...options,\n _onDispatch: (event: EventKey<T>, payload: unknown) => {\n buffers.set(event as string, payload);\n },\n } as InternalBusOptions<T>);\n\n // Wrap the listener call during synchronous replay so a throw routes through onError when set.\n // Only one listener is replayed per call here (unlike bus.ts's dispatch() broadcast loop), so\n // there's no \"keep going\" batch to preserve — an unforwarded throw rethrows immediately.\n function callSafeReplay(listener: Listener<unknown>, event: EventKey<T>, value: unknown): void {\n const onError = options?.onError\n ? (err: unknown) =>\n options.onError!({ err, event, payload: value, timestamp: Date.now() } as EmissionErrorContext<T>)\n : undefined;\n\n const result = callSafely(() => listener(value), onError);\n\n if (result.threw) throw result.err;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): Unsubscribe {\n if (bus.disposed || opts?.signal?.aborted) return noop;\n\n if (buffers.has(event as string)) {\n const value = buffers.get(event as string) as T[K];\n\n if (opts?.once) {\n callSafeReplay(listener as Listener<unknown>, event, value);\n\n return noop;\n }\n\n callSafeReplay(listener as Listener<unknown>, event, value);\n }\n\n return bus.on(event, listener, opts);\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): Unsubscribe {\n return on(event, listener, { once: true, signal: opts?.signal });\n }\n\n function current<K extends EventKey<T>>(event: K): T[K] | undefined {\n return buffers.has(event as string) ? (buffers.get(event as string) as T[K]) : undefined;\n }\n\n function reset(event?: EventKey<T>): void {\n if (event !== undefined) buffers.delete(event as string);\n else buffers.clear();\n }\n\n function snapshot(): Partial<T> {\n const result: Partial<T> = {};\n\n for (const [key, value] of buffers) {\n // Guard against a `__proto__`/`constructor`/`prototype` event name hijacking result's\n // own prototype via the bracket-assignment accessor — see _prototype.ts.\n if (isUnsafeObjectKey(key)) continue;\n\n (result as Record<string, unknown>)[key] = value;\n }\n\n return result;\n }\n\n function dispose(): void {\n bus.dispose();\n buffers.clear();\n }\n\n const delegate = makeBusDelegate<T>(bus) as BehaviorBus<T>;\n\n delegate.current = current;\n delegate.dispose = dispose;\n delegate.on = on;\n delegate.once = once;\n delegate.reset = reset;\n delegate.snapshot = snapshot;\n delegate[Symbol.dispose] = dispose;\n\n return delegate;\n}\n"],"mappings":"iHAkCA,SAAgB,EACd,EACA,EACgB,CAGhB,IAAM,EAAU,IAAI,IAAqB,OAAO,QAAQ,GAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAG,KAAO,IAAM,IAAA,EAAS,CAAC,EAInG,EAAM,EAAA,UAAa,CACvB,GAAG,EACH,aAAc,EAAoB,IAAqB,CACrD,EAAQ,IAAI,EAAiB,CAAO,CACtC,CACF,CAA0B,EAK1B,SAAS,EAAe,EAA6B,EAAoB,EAAsB,CAM7F,IAAM,EAAS,EAAA,eAAiB,EAAS,CAAK,EAL9B,GAAS,QACpB,GACC,EAAQ,QAAS,CAAE,MAAK,QAAO,QAAS,EAAO,UAAW,KAAK,IAAI,CAAE,CAA4B,EACnG,IAAA,EAEoD,EAExD,GAAI,EAAO,MAAO,MAAM,EAAO,GACjC,CAEA,SAAS,EAA0B,EAAU,EAA0B,EAAsC,CAC3G,GAAI,EAAI,UAAY,GAAM,QAAQ,QAAS,OAAO,EAAA,KAElD,GAAI,EAAQ,IAAI,CAAe,EAAG,CAChC,IAAM,EAAQ,EAAQ,IAAI,CAAe,EAEzC,GAAI,GAAM,KAGR,OAFA,EAAe,EAA+B,EAAO,CAAK,EAEnD,EAAA,KAGT,EAAe,EAA+B,EAAO,CAAK,CAC5D,CAEA,OAAO,EAAI,GAAG,EAAO,EAAU,CAAI,CACrC,CAEA,SAAS,EACP,EACA,EACA,EACa,CACb,OAAO,EAAG,EAAO,EAAU,CAAE,KAAM,GAAM,OAAQ,GAAM,MAAO,CAAC,CACjE,CAEA,SAAS,EAA+B,EAA4B,CAClE,OAAO,EAAQ,IAAI,CAAe,EAAK,EAAQ,IAAI,CAAe,EAAa,IAAA,EACjF,CAEA,SAAS,EAAM,EAA2B,CACpC,IAAU,IAAA,GACT,EAAQ,MAAM,EADM,EAAQ,OAAO,CAAe,CAEzD,CAEA,SAAS,GAAuB,CAC9B,IAAM,EAAqB,CAAC,EAE5B,IAAK,GAAM,CAAC,EAAK,KAAU,EAGrB,EAAA,kBAAkB,CAAG,IAEzB,EAAoC,GAAO,GAG7C,OAAO,CACT,CAEA,SAAS,GAAgB,CACvB,EAAI,QAAQ,EACZ,EAAQ,MAAM,CAChB,CAEA,IAAM,EAAW,EAAA,gBAAmB,CAAG,EAUvC,MARA,GAAS,QAAU,EACnB,EAAS,QAAU,EACnB,EAAS,GAAK,EACd,EAAS,KAAO,EAChB,EAAS,MAAQ,EACjB,EAAS,SAAW,EACpB,EAAS,OAAO,SAAW,EAEpB,CACT"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BehaviorBus, BehaviorBusOptions, BehaviorInitial, EventMap } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a bus that replays the last known value for each event to new subscribers.
|
|
4
|
+
*
|
|
5
|
+
* When a listener subscribes via `on()` or `once()`, it immediately receives the current
|
|
6
|
+
* buffered value for that event (if any have been emitted or were provided as initial values).
|
|
7
|
+
* `events()`, `wait()`, and `waitAny()` behave like a regular bus — no replay.
|
|
8
|
+
*
|
|
9
|
+
* @param initial - Optional map of event names to their starting values.
|
|
10
|
+
* @param options - Standard bus options.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const bus = createBehaviorBus<{ count: number }>({ count: 0 });
|
|
14
|
+
* bus.on('count', (n) => console.log(n)); // logs 0 immediately
|
|
15
|
+
* bus.emit('count', 1);
|
|
16
|
+
* bus.on('count', (n) => console.log(n)); // logs 1 immediately (latest value)
|
|
17
|
+
*/
|
|
18
|
+
export declare function createBehaviorBus<T extends EventMap>(initial?: BehaviorInitial<T>, options?: BehaviorBusOptions<T>): BehaviorBus<T>;
|
|
19
|
+
//# sourceMappingURL=behavior-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior-bus.d.ts","sourceRoot":"","sources":["../src/behavior-bus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EAGf,QAAQ,EAIT,MAAM,SAAS,CAAC;AAOjB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,QAAQ,EAClD,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC9B,WAAW,CAAC,CAAC,CAAC,CA6FhB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { makeBusDelegate as e } from "./_delegate.js";
|
|
2
|
+
import { isUnsafeObjectKey as t } from "./_prototype.js";
|
|
3
|
+
import { callSafely as n } from "./_safe.js";
|
|
4
|
+
import { createBus as r, noop as i } from "./bus.js";
|
|
5
|
+
//#region src/behavior-bus.ts
|
|
6
|
+
function a(a, o) {
|
|
7
|
+
let s = new Map(Object.entries(a ?? {}).filter(([, e]) => e !== void 0)), c = r({
|
|
8
|
+
...o,
|
|
9
|
+
_onDispatch: (e, t) => {
|
|
10
|
+
s.set(e, t);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
function l(e, t, r) {
|
|
14
|
+
let i = n(() => e(r), o?.onError ? (e) => o.onError({
|
|
15
|
+
err: e,
|
|
16
|
+
event: t,
|
|
17
|
+
payload: r,
|
|
18
|
+
timestamp: Date.now()
|
|
19
|
+
}) : void 0);
|
|
20
|
+
if (i.threw) throw i.err;
|
|
21
|
+
}
|
|
22
|
+
function u(e, t, n) {
|
|
23
|
+
if (c.disposed || n?.signal?.aborted) return i;
|
|
24
|
+
if (s.has(e)) {
|
|
25
|
+
let r = s.get(e);
|
|
26
|
+
if (n?.once) return l(t, e, r), i;
|
|
27
|
+
l(t, e, r);
|
|
28
|
+
}
|
|
29
|
+
return c.on(e, t, n);
|
|
30
|
+
}
|
|
31
|
+
function d(e, t, n) {
|
|
32
|
+
return u(e, t, {
|
|
33
|
+
once: !0,
|
|
34
|
+
signal: n?.signal
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function f(e) {
|
|
38
|
+
return s.has(e) ? s.get(e) : void 0;
|
|
39
|
+
}
|
|
40
|
+
function p(e) {
|
|
41
|
+
e === void 0 ? s.clear() : s.delete(e);
|
|
42
|
+
}
|
|
43
|
+
function m() {
|
|
44
|
+
let e = {};
|
|
45
|
+
for (let [n, r] of s) t(n) || (e[n] = r);
|
|
46
|
+
return e;
|
|
47
|
+
}
|
|
48
|
+
function h() {
|
|
49
|
+
c.dispose(), s.clear();
|
|
50
|
+
}
|
|
51
|
+
let g = e(c);
|
|
52
|
+
return g.current = f, g.dispose = h, g.on = u, g.once = d, g.reset = p, g.snapshot = m, g[Symbol.dispose] = h, g;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { a as createBehaviorBus };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=behavior-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior-bus.js","names":[],"sources":["../src/behavior-bus.ts"],"sourcesContent":["import type { InternalBusOptions } from './bus';\nimport type {\n BehaviorBus,\n BehaviorBusOptions,\n BehaviorInitial,\n EmissionErrorContext,\n EventKey,\n EventMap,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n} from './types';\n\nimport { makeBusDelegate } from './_delegate';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { callSafely } from './_safe';\nimport { createBus, noop } from './bus';\n\n/**\n * Creates a bus that replays the last known value for each event to new subscribers.\n *\n * When a listener subscribes via `on()` or `once()`, it immediately receives the current\n * buffered value for that event (if any have been emitted or were provided as initial values).\n * `events()`, `wait()`, and `waitAny()` behave like a regular bus — no replay.\n *\n * @param initial - Optional map of event names to their starting values.\n * @param options - Standard bus options.\n *\n * @example\n * const bus = createBehaviorBus<{ count: number }>({ count: 0 });\n * bus.on('count', (n) => console.log(n)); // logs 0 immediately\n * bus.emit('count', 1);\n * bus.on('count', (n) => console.log(n)); // logs 1 immediately (latest value)\n */\nexport function createBehaviorBus<T extends EventMap>(\n initial?: BehaviorInitial<T>,\n options?: BehaviorBusOptions<T>,\n): BehaviorBus<T> {\n // Flat buffer: one value per event key.\n // Seeded from initial values; updated via _onDispatch when dispatch actually runs.\n const buffers = new Map<string, unknown>(Object.entries(initial ?? {}).filter(([, v]) => v !== undefined));\n\n // _onDispatch fires after middleware passes (dispatch guaranteed to run).\n // This replaces the sentinel-middleware + mutable-flag pattern.\n const bus = createBus<T>({\n ...options,\n _onDispatch: (event: EventKey<T>, payload: unknown) => {\n buffers.set(event as string, payload);\n },\n } as InternalBusOptions<T>);\n\n // Wrap the listener call during synchronous replay so a throw routes through onError when set.\n // Only one listener is replayed per call here (unlike bus.ts's dispatch() broadcast loop), so\n // there's no \"keep going\" batch to preserve — an unforwarded throw rethrows immediately.\n function callSafeReplay(listener: Listener<unknown>, event: EventKey<T>, value: unknown): void {\n const onError = options?.onError\n ? (err: unknown) =>\n options.onError!({ err, event, payload: value, timestamp: Date.now() } as EmissionErrorContext<T>)\n : undefined;\n\n const result = callSafely(() => listener(value), onError);\n\n if (result.threw) throw result.err;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): Unsubscribe {\n if (bus.disposed || opts?.signal?.aborted) return noop;\n\n if (buffers.has(event as string)) {\n const value = buffers.get(event as string) as T[K];\n\n if (opts?.once) {\n callSafeReplay(listener as Listener<unknown>, event, value);\n\n return noop;\n }\n\n callSafeReplay(listener as Listener<unknown>, event, value);\n }\n\n return bus.on(event, listener, opts);\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): Unsubscribe {\n return on(event, listener, { once: true, signal: opts?.signal });\n }\n\n function current<K extends EventKey<T>>(event: K): T[K] | undefined {\n return buffers.has(event as string) ? (buffers.get(event as string) as T[K]) : undefined;\n }\n\n function reset(event?: EventKey<T>): void {\n if (event !== undefined) buffers.delete(event as string);\n else buffers.clear();\n }\n\n function snapshot(): Partial<T> {\n const result: Partial<T> = {};\n\n for (const [key, value] of buffers) {\n // Guard against a `__proto__`/`constructor`/`prototype` event name hijacking result's\n // own prototype via the bracket-assignment accessor — see _prototype.ts.\n if (isUnsafeObjectKey(key)) continue;\n\n (result as Record<string, unknown>)[key] = value;\n }\n\n return result;\n }\n\n function dispose(): void {\n bus.dispose();\n buffers.clear();\n }\n\n const delegate = makeBusDelegate<T>(bus) as BehaviorBus<T>;\n\n delegate.current = current;\n delegate.dispose = dispose;\n delegate.on = on;\n delegate.once = once;\n delegate.reset = reset;\n delegate.snapshot = snapshot;\n delegate[Symbol.dispose] = dispose;\n\n return delegate;\n}\n"],"mappings":";;;;;AAkCA,SAAgB,EACd,GACA,GACgB;CAGhB,IAAM,IAAU,IAAI,IAAqB,OAAO,QAAQ,KAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,MAAM,KAAA,CAAS,CAAC,GAInG,IAAM,EAAa;EACvB,GAAG;EACH,cAAc,GAAoB,MAAqB;GACrD,EAAQ,IAAI,GAAiB,CAAO;EACtC;CACF,CAA0B;CAK1B,SAAS,EAAe,GAA6B,GAAoB,GAAsB;EAM7F,IAAM,IAAS,QAAiB,EAAS,CAAK,GAL9B,GAAS,WACpB,MACC,EAAQ,QAAS;GAAE;GAAK;GAAO,SAAS;GAAO,WAAW,KAAK,IAAI;EAAE,CAA4B,IACnG,KAAA,CAEoD;EAExD,IAAI,EAAO,OAAO,MAAM,EAAO;CACjC;CAEA,SAAS,EAA0B,GAAU,GAA0B,GAAsC;EAC3G,IAAI,EAAI,YAAY,GAAM,QAAQ,SAAS,OAAO;EAElD,IAAI,EAAQ,IAAI,CAAe,GAAG;GAChC,IAAM,IAAQ,EAAQ,IAAI,CAAe;GAEzC,IAAI,GAAM,MAGR,OAFA,EAAe,GAA+B,GAAO,CAAK,GAEnD;GAGT,EAAe,GAA+B,GAAO,CAAK;EAC5D;EAEA,OAAO,EAAI,GAAG,GAAO,GAAU,CAAI;CACrC;CAEA,SAAS,EACP,GACA,GACA,GACa;EACb,OAAO,EAAG,GAAO,GAAU;GAAE,MAAM;GAAM,QAAQ,GAAM;EAAO,CAAC;CACjE;CAEA,SAAS,EAA+B,GAA4B;EAClE,OAAO,EAAQ,IAAI,CAAe,IAAK,EAAQ,IAAI,CAAe,IAAa,KAAA;CACjF;CAEA,SAAS,EAAM,GAA2B;EACxC,AAAI,MAAU,KAAA,IACT,EAAQ,MAAM,IADM,EAAQ,OAAO,CAAe;CAEzD;CAEA,SAAS,IAAuB;EAC9B,IAAM,IAAqB,CAAC;EAE5B,KAAK,IAAM,CAAC,GAAK,MAAU,GAGrB,EAAkB,CAAG,MAEzB,EAAoC,KAAO;EAG7C,OAAO;CACT;CAEA,SAAS,IAAgB;EAEvB,AADA,EAAI,QAAQ,GACZ,EAAQ,MAAM;CAChB;CAEA,IAAM,IAAW,EAAmB,CAAG;CAUvC,OARA,EAAS,UAAU,GACnB,EAAS,UAAU,GACnB,EAAS,KAAK,GACd,EAAS,OAAO,GAChB,EAAS,QAAQ,GACjB,EAAS,WAAW,GACpB,EAAS,OAAO,WAAW,GAEpB;AACT"}
|
package/dist/bus.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./_safe.cjs"),t=require("./_dev.cjs"),n=require("./errors.cjs");var r=()=>{};function i(e,t){if(e.aborted)return e;if(t.aborted)return t;let n=new AbortController,r=()=>n.abort(e.reason),i=()=>n.abort(t.reason);return e.addEventListener(`abort`,r,{once:!0}),t.addEventListener(`abort`,i,{once:!0}),n.signal.addEventListener(`abort`,()=>{e.removeEventListener(`abort`,r),t.removeEventListener(`abort`,i)},{once:!0}),n.signal}function a(e,...t){return t.length===0?e:t.reduce(i,e)}function o(e,t){return Object.assign(e,{[Symbol.asyncDispose]:t})}function s(i){let s=new Map,c=new Set,l=new AbortController,u=i?.name,d=i?.maxListeners,f=i?.logger?.debug,p=f&&u?e=>f(`${e} (${u})`):f,m=i?.logger!==void 0,h=i?.logger?.warn,g=u?` (${u})`:``;function _(e){h?h(e):m||t.warn(e)}function v(e){return e?a(l.signal,e):l.signal}function y(t,n,r,a){return e.callSafely(t,i?.onError?e=>i.onError({err:e,event:n,payload:r,timestamp:a}):void 0)}function b(e,t,n,{offLog:i,onLog:a,onRemove:o}){if(n.aborted)return r;let s=!1;function c(){s||(s=!0,e.delete(l),o?.(),n.removeEventListener(`abort`,c),p?.(`[herald:sub] ${i} — ${e.size} listener(s) remaining`))}let l=t(c);return e.add(l),n.addEventListener(`abort`,c,{once:!0}),p?.(`[herald:sub] ${a} — ${e.size} listener(s)`),d!==void 0&&e.size>d&&_(`${a} has ${e.size} listeners, exceeding maxListeners (${d}). Possible memory leak.${g}`),c}function x(e,t,n){let r=s.get(e);r||(r=new Set,s.set(e,r));let i=r;return b(i,e=>({fn:t,unsub:e}),n,{offLog:`off("${e}")`,onLog:`on("${e}")`,onRemove:()=>{i.size===0&&s.delete(e)}})}function S(e,t){return b(c,t=>({fn:e,unsub:t}),t,{offLog:`onAny off`,onLog:`onAny`})}function C(e,t,n){let i={unsub:r};return i.unsub=x(e,e=>{i.unsub(),t(e)},n),i.unsub}function w(e,t){let n={unsub:r};return n.unsub=S((t,r)=>{n.unsub(),e(t,r)},t),n.unsub}function T(e,t,n){let r=v(n?.signal);return n?.once?C(e,t,r):x(e,t,r)}function E(e,t,n){return C(e,t,v(n?.signal))}function D(e,t){let n=v(t?.signal);return t?.once?w(e,n):S(e,n)}function O(e,t){let n=v(t?.signal);return n.aborted?Promise.reject(n.reason):new Promise((t,r)=>{function i(){r(n.reason)}C(e,e=>{n.removeEventListener(`abort`,i),t(e)},n),n.addEventListener(`abort`,i,{once:!0})})}function k(e,t){let r=t?.maxBuffer??1/0;if(!(r>0))throw new n.HeraldConfigError(`maxBuffer must be a positive number`);let i=v(t?.signal);if(i.aborted)return o((async function*(){})(),async()=>{});let a=[],s,c=x(e,e=>{a.length>=r&&a.shift(),a.push(e),s?.()},i);async function*l(){try{for(;!i.aborted;){if(a.length){yield a.shift();continue}let{promise:e,resolve:t}=Promise.withResolvers(),n=()=>{t()};s=t,i.addEventListener(`abort`,n,{once:!0}),await e,i.removeEventListener(`abort`,n),s=void 0}}finally{c()}}let u=l();return o(u,async()=>{c(),await u.return(void 0)})}function A(e,t,n){i?._onDispatch?.(e,t);let r=0,a,o=s.get(e);if(o?.size)for(let i of[...o]){let o=y(()=>i.fn(t),e,t,n);o.threw&&!a&&(a={err:o.err}),r++}if(c.size)for(let i of[...c]){let o=y(()=>i.fn(e,t),e,t,n);o.threw&&!a&&(a={err:o.err}),r++}if(a)throw a.err;return r}function j(e,...t){if(l.signal.aborted)return 0;let n=t[0],r=Date.now();if(i?.validatePayload)try{i.validatePayload(e,n)}catch(t){if(i?.onError)return i.onError({err:t,event:e,payload:n,timestamp:r}),0;throw t}if(p){let t=s.get(e)?.size??0,n=c.size;p(`[herald:emit] emit("${e}") — ${t+n} listener(s) (${t} specific, ${n} wildcard)`)}let a=i?.middleware;if(a?.length){let t=0,i=0;function o(){let s=i++;s<a.length?a[s](e,n,o):s===a.length&&(t=A(e,n,r))}return o(),t}return A(e,n,r)}function M(e){if(e!==void 0)return s.get(e)?.size??0;let t=0;for(let e of s.values())t+=e.size;return t}function N(){return c.size}function P(){return[...s.keys()]}function F(e,t){if(e.length<2)throw new n.HeraldConfigError(`waitAny() requires at least 2 event keys`);let r=v(t?.signal);return r.aborted?Promise.reject(r.reason):new Promise((t,n)=>{let i=new AbortController,o=a(r,i.signal);function s(){i.abort(),n(r.reason)}r.addEventListener(`abort`,s,{once:!0});for(let n of e)C(n,e=>{r.removeEventListener(`abort`,s),i.abort(),t({event:n,payload:e})},o)})}function I(){l.signal.aborted||(p?.(`[herald:lifecycle] dispose()`),l.abort(new n.BusDisposedError(u)),s.clear(),c.clear())}return{get disposalSignal(){return l.signal},dispose:I,get disposed(){return l.signal.aborted},emit:j,eventNames:P,events:k,listenerCount:M,on:T,onAny:D,once:E,[Symbol.dispose]:I,wait:O,waitAny:F,wildcardCount:N}}exports.combineSignals=a,exports.createBus=s,exports.noop=r;
|
|
2
|
+
//# sourceMappingURL=bus.cjs.map
|
package/dist/bus.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.cjs","names":[],"sources":["../src/bus.ts"],"sourcesContent":["import type {\n Bus,\n BusOptions,\n EmissionErrorContext,\n EventKey,\n EventMap,\n EventStream,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\nimport { warn as _internalWarn } from './_dev';\nimport { type SafeCallResult, callSafely } from './_safe';\nimport { BusDisposedError, HeraldConfigError } from './errors';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n// @internal — exported only for sibling internal modules; stripped from public declarations via stripInternal.\n/** @internal */\nexport const noop = () => {};\n\n/** @internal */\nfunction mergeTwo(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a;\n\n if (b.aborted) return b;\n\n const ctrl = new AbortController();\n const onA = (): void => ctrl.abort(a.reason);\n const onB = (): void => ctrl.abort(b.reason);\n\n a.addEventListener('abort', onA, { once: true });\n b.addEventListener('abort', onB, { once: true });\n ctrl.signal.addEventListener(\n 'abort',\n () => {\n a.removeEventListener('abort', onA);\n b.removeEventListener('abort', onB);\n },\n { once: true },\n );\n\n return ctrl.signal;\n}\n\n/**\n * Returns a signal that aborts as soon as any of the provided signals abort.\n * With a single argument, returns it directly (no allocation).\n * Registers and cleans up its own event listeners — no leaks when no signal fires.\n *\n * @example\n * const signal = combineSignals(timeoutSignal, bus.disposalSignal);\n * bus.on('event', handler, { signal });\n *\n * @example\n * // Three signals — no nesting required\n * const signal = combineSignals(userSignal, timeoutSignal, bus.disposalSignal);\n */\nexport function combineSignals(first: AbortSignal, ...rest: AbortSignal[]): AbortSignal {\n if (rest.length === 0) return first;\n\n return rest.reduce(mergeTwo, first);\n}\n\n// Each registration gets a unique Entry object, allowing the same listener function\n// to be registered multiple times independently (aligns with Node EventEmitter / mitt).\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts = { offLog: string; onLog: string; onRemove?: () => void };\n\n// makeEventStream wraps an AsyncGenerator with AsyncDisposable.\nfunction makeEventStream<V>(gen: AsyncGenerator<V>, onDispose: () => Promise<void>): EventStream<V> {\n return Object.assign(gen, {\n [Symbol.asyncDispose]: onDispose,\n }) as unknown as EventStream<V>;\n}\n\n/** @internal */\nexport type InternalBusOptions<T extends EventMap> = BusOptions<T> & {\n /** @internal Called after middleware passes, before listeners run. Used by BehaviorBus. */\n _onDispatch?: (event: EventKey<T>, payload: unknown) => void;\n};\n\nexport function createBus<T extends EventMap>(options?: InternalBusOptions<T>): Bus<T> {\n // Per-event set of Entry objects. Set identity prevents accidental dedup of entries;\n // the same fn can appear in multiple entries with independent lifetimes.\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const rawDebug = options?.logger?.debug;\n const logDebug = rawDebug && busName ? (msg: string) => rawDebug(`${msg} (${busName})`) : rawDebug;\n const hasLogger = options?.logger !== undefined;\n const customLogWarn = options?.logger?.warn;\n const busTag = busName ? ` (${busName})` : '';\n\n function doWarn(msg: string): void {\n if (customLogWarn) {\n customLogWarn(msg);\n } else if (!hasLogger) {\n _internalWarn(msg);\n }\n }\n\n function mergeSignal(signal?: AbortSignal): AbortSignal {\n return signal ? combineSignals(disposeController.signal, signal) : disposeController.signal;\n }\n\n // callSafe is defined once per bus (not per emit) — avoids re-allocating on every emission.\n // Captures options.onError via closure. Used in emit() for both specific and wildcard loops.\n // Does not rethrow directly — see dispatch(), which continues the broadcast to every remaining\n // listener (including wildcards) before rethrowing the first captured error, if any.\n function callSafe(fn: () => void, event: EventKey<T>, payload: unknown, timestamp: number): SafeCallResult {\n const onError = options?.onError\n ? (err: unknown) => options.onError!({ err, event, payload, timestamp } as EmissionErrorContext<T>)\n : undefined;\n\n return callSafely(fn, onError);\n }\n\n // registerEntry opts object — self-documenting call sites.\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { offLog, onLog, onRemove }: RegisterEntryOpts,\n ): () => void {\n if (signal.aborted) return noop;\n\n // Boolean guard makes unsub idempotent — a second call after re-registration would\n // otherwise see an empty container and incorrectly delete the outer map entry.\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n logDebug?.(`[herald:sub] ${offLog} — ${container.size} listener(s) remaining`);\n }\n\n // Function declaration is hoisted so `entry` can reference `unsub` directly.\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n logDebug?.(`[herald:sub] ${onLog} — ${container.size} listener(s)`);\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, signal: AbortSignal): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n // Capture the set reference so unsub can safely delete from it even after\n // the event key has been removed from the outer map.\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n offLog: `off(\"${event}\")`,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n },\n });\n }\n\n function onAnyWithSignal(listener: (event: EventKey<T>, payload: unknown) => void, signal: AbortSignal): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { offLog: 'onAny off', onLog: 'onAny' },\n );\n }\n\n // Use a const ref object to hold the unsub handle — avoids the forward-reference that\n // TypeScript cannot prove safe with `const unsub = f(() => unsub)`. The `ref` binding never\n // changes (only its property is mutated), satisfying prefer-const. By the time the inner\n // callback fires (only possible after onWithSignal returns), ref.unsub is the real handle.\n function onceWithSignal<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, signal: AbortSignal): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n );\n\n return ref.unsub;\n }\n\n // onAny with once — fires the wildcard listener exactly once, then auto-removes.\n function onAnyWithOnce(listener: (event: EventKey<T>, payload: unknown) => void, signal: AbortSignal): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onAnyWithSignal((event, payload) => {\n ref.unsub();\n listener(event, payload);\n }, signal);\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n const signal = mergeSignal(opts?.signal);\n\n if (opts?.once) return onceWithSignal(event, listener, signal);\n\n return onWithSignal(event, listener, signal);\n }\n\n // once() and onAny() take an options object — consistent with on(), extensible for future options.\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n return onceWithSignal(event, listener, mergeSignal(opts?.signal));\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n const signal = mergeSignal(opts?.signal);\n\n if (opts?.once) return onAnyWithOnce(listener, signal);\n\n return onAnyWithSignal(listener, signal);\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const activeSignal = mergeSignal(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n function onAbort() {\n reject(activeSignal.reason);\n }\n\n onceWithSignal(\n event,\n (payload) => {\n activeSignal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n activeSignal,\n );\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n // events() subscribes eagerly — the listener is registered when events() is called, not when\n // the first .next() runs. This ensures events emitted before iteration begins are buffered.\n // maxBuffer is validated synchronously so callers get a RangeError at call time.\n function events<K extends EventKey<T>>(\n event: K,\n opts?: { maxBuffer?: number; signal?: AbortSignal },\n ): EventStream<T[K]> {\n const maxBuffer = opts?.maxBuffer ?? Infinity;\n\n if (!(maxBuffer > 0)) throw new HeraldConfigError('maxBuffer must be a positive number');\n\n const activeSignal = mergeSignal(opts?.signal);\n\n if (activeSignal.aborted) {\n const empty = (async function* (): AsyncGenerator<T[K]> {})();\n\n return makeEventStream(empty, async (): Promise<void> => {});\n }\n\n const queue: T[K][] = [];\n let wake: (() => void) | undefined;\n\n const unsub = onWithSignal(\n event,\n (payload) => {\n if (queue.length >= maxBuffer) queue.shift();\n\n queue.push(payload);\n wake?.();\n },\n activeSignal,\n );\n\n async function* generate(): AsyncGenerator<T[K]> {\n try {\n while (!activeSignal.aborted) {\n if (queue.length) {\n yield queue.shift()!;\n continue;\n }\n\n const { promise, resolve } = Promise.withResolvers<void>();\n const abortHandler = (): void => {\n resolve();\n };\n\n wake = resolve;\n activeSignal.addEventListener('abort', abortHandler, { once: true });\n await promise;\n activeSignal.removeEventListener('abort', abortHandler);\n wake = undefined;\n }\n } finally {\n unsub();\n }\n }\n\n const gen = generate();\n\n // Symbol.asyncDispose calls unsub() directly because gen.return() only runs the finally\n // block when the generator has been started (at least one next() call). The unsub guard\n // (called = false in registerEntry) makes this idempotent.\n return makeEventStream(gen, async (): Promise<void> => {\n unsub();\n await gen.return(undefined as unknown as T[K]);\n });\n }\n\n // dispatch is defined at createBus() scope (once per bus, not per emit call) — consistent with\n // callSafe. Receives event/payload/timestamp as arguments so it can be invoked from both the\n // direct path and the middleware chain without capturing per-emit locals in a closure.\n function dispatch(event: EventKey<T>, payload: unknown, timestamp: number): number {\n options?._onDispatch?.(event, payload);\n\n let count = 0;\n // Only the first unforwarded error is kept — every listener still runs (see callSafe's\n // doc comment) — then it's rethrown once the whole broadcast (specific + wildcard) is done.\n let firstError: { err: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n const result = callSafe(() => entry.fn(payload), event, payload, timestamp);\n\n if (result.threw && !firstError) firstError = { err: result.err };\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n const result = callSafe(() => entry.fn(event, payload), event, payload, timestamp);\n\n if (result.threw && !firstError) firstError = { err: result.err };\n\n count++;\n }\n }\n\n if (firstError) throw firstError.err;\n\n return count;\n }\n\n // emit() returns the number of listeners invoked (specific + wildcard).\n // Returns 0 if bus is disposed, middleware blocked dispatch, or validatePayload rejected.\n // validatePayload runs first, then middleware, then listeners.\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): number {\n if (disposeController.signal.aborted) return 0;\n\n const payload = (args as unknown[])[0];\n const timestamp = Date.now();\n\n if (options?.validatePayload) {\n try {\n options.validatePayload(event, payload as T[K]);\n } catch (err) {\n if (options?.onError) {\n options.onError({ err, event, payload, timestamp } as EmissionErrorContext<T>);\n\n return 0;\n }\n\n throw err;\n }\n }\n\n if (logDebug) {\n const specific = listeners.get(event)?.size ?? 0;\n const wild = wildcards.size;\n\n logDebug(\n `[herald:emit] emit(\"${event}\") — ${specific + wild} listener(s) (${specific} specific, ${wild} wildcard)`,\n );\n }\n\n // Middleware pipeline — each middleware calls next() to proceed.\n const middleware = options?.middleware;\n\n if (middleware?.length) {\n let dispatched = 0;\n let i = 0;\n\n // Guard prevents a misbehaving middleware from calling next() twice and\n // triggering a double-dispatch to listeners. Note: a middleware calling next()\n // more than twice can still invoke downstream middleware multiple times.\n function next(): void {\n const idx = i++;\n\n if (idx < middleware!.length) middleware;\n else if (idx === middleware!.length) dispatched = dispatch(event, payload, timestamp);\n }\n\n next();\n\n return dispatched;\n }\n\n return dispatch(event, payload, timestamp);\n }\n\n // listenerCount counts specific-event listeners only.\n // wildcardCount() is the separate accessor for onAny listeners.\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function waitAny<K extends readonly [EventKey<T>, EventKey<T>, ...EventKey<T>[]]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n if (eventList.length < 2) throw new HeraldConfigError('waitAny() requires at least 2 event keys');\n\n const activeSignal = mergeSignal(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = combineSignals(activeSignal, raceController.signal);\n\n function onAbort() {\n raceController.abort();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n logDebug?.('[herald:lifecycle] dispose()');\n\n disposeController.abort(new BusDisposedError(busName));\n // disposeController.abort() fires all unsub handlers synchronously, which\n // removes every entry and deletes empty keys. By here both maps are already\n // empty. clear() is a cheap defensive measure against any future code path\n // that bypasses the signal (e.g. a direct listeners.set() before a guard).\n listeners.clear();\n wildcards.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n events,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
|
package/dist/bus.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Bus, EventMap } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a signal that aborts as soon as any of the provided signals abort.
|
|
4
|
+
* With a single argument, returns it directly (no allocation).
|
|
5
|
+
* Registers and cleans up its own event listeners — no leaks when no signal fires.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const signal = combineSignals(timeoutSignal, bus.disposalSignal);
|
|
9
|
+
* bus.on('event', handler, { signal });
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Three signals — no nesting required
|
|
13
|
+
* const signal = combineSignals(userSignal, timeoutSignal, bus.disposalSignal);
|
|
14
|
+
*/
|
|
15
|
+
export declare function combineSignals(first: AbortSignal, ...rest: AbortSignal[]): AbortSignal;
|
|
16
|
+
export declare function createBus<T extends EventMap>(options?: InternalBusOptions<T>): Bus<T>;
|
|
17
|
+
//# sourceMappingURL=bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,GAAG,EAIH,QAAQ,EAMT,MAAM,SAAS,CAAC;AAmCjB;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,CAItF;AAsBD,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAAE,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAubrF"}
|