@okikio/observables 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/LICENSE +21 -0
- package/README.md +578 -0
- package/esm/_dnt.polyfills.d.ts +20 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +12 -0
- package/esm/_spec.d.ts +260 -0
- package/esm/_spec.d.ts.map +1 -0
- package/esm/_spec.js +1 -0
- package/esm/_types.d.ts +141 -0
- package/esm/_types.d.ts.map +1 -0
- package/esm/_types.js +20 -0
- package/esm/error.d.ts +331 -0
- package/esm/error.d.ts.map +1 -0
- package/esm/error.js +408 -0
- package/esm/events.d.ts +320 -0
- package/esm/events.d.ts.map +1 -0
- package/esm/events.js +451 -0
- package/esm/helpers/_types.d.ts +188 -0
- package/esm/helpers/_types.d.ts.map +1 -0
- package/esm/helpers/_types.js +1 -0
- package/esm/helpers/mod.d.ts +90 -0
- package/esm/helpers/mod.d.ts.map +1 -0
- package/esm/helpers/mod.js +90 -0
- package/esm/helpers/operations/batch.d.ts +109 -0
- package/esm/helpers/operations/batch.d.ts.map +1 -0
- package/esm/helpers/operations/batch.js +140 -0
- package/esm/helpers/operations/combination.d.ts +162 -0
- package/esm/helpers/operations/combination.d.ts.map +1 -0
- package/esm/helpers/operations/combination.js +350 -0
- package/esm/helpers/operations/conditional.d.ts +211 -0
- package/esm/helpers/operations/conditional.d.ts.map +1 -0
- package/esm/helpers/operations/conditional.js +280 -0
- package/esm/helpers/operations/core.d.ts +198 -0
- package/esm/helpers/operations/core.d.ts.map +1 -0
- package/esm/helpers/operations/core.js +264 -0
- package/esm/helpers/operations/errors.d.ts +277 -0
- package/esm/helpers/operations/errors.d.ts.map +1 -0
- package/esm/helpers/operations/errors.js +378 -0
- package/esm/helpers/operations/mod.d.ts +26 -0
- package/esm/helpers/operations/mod.d.ts.map +1 -0
- package/esm/helpers/operations/mod.js +25 -0
- package/esm/helpers/operations/timing.d.ts +206 -0
- package/esm/helpers/operations/timing.d.ts.map +1 -0
- package/esm/helpers/operations/timing.js +457 -0
- package/esm/helpers/operators.d.ts +520 -0
- package/esm/helpers/operators.d.ts.map +1 -0
- package/esm/helpers/operators.js +563 -0
- package/esm/helpers/pipe.d.ts +118 -0
- package/esm/helpers/pipe.d.ts.map +1 -0
- package/esm/helpers/pipe.js +129 -0
- package/esm/helpers/utils.d.ts +142 -0
- package/esm/helpers/utils.d.ts.map +1 -0
- package/esm/helpers/utils.js +193 -0
- package/esm/mod.d.ts +863 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +861 -0
- package/esm/observable.d.ts +1610 -0
- package/esm/observable.d.ts.map +1 -0
- package/esm/observable.js +1970 -0
- package/esm/package.json +3 -0
- package/esm/queue.d.ts +201 -0
- package/esm/queue.d.ts.map +1 -0
- package/esm/queue.js +273 -0
- package/esm/symbol.d.ts +60 -0
- package/esm/symbol.d.ts.map +1 -0
- package/esm/symbol.js +132 -0
- package/package.json +96 -0
- package/script/_dnt.polyfills.d.ts +20 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +13 -0
- package/script/_spec.d.ts +260 -0
- package/script/_spec.d.ts.map +1 -0
- package/script/_spec.js +2 -0
- package/script/_types.d.ts +141 -0
- package/script/_types.d.ts.map +1 -0
- package/script/_types.js +22 -0
- package/script/error.d.ts +331 -0
- package/script/error.d.ts.map +1 -0
- package/script/error.js +414 -0
- package/script/events.d.ts +320 -0
- package/script/events.d.ts.map +1 -0
- package/script/events.js +458 -0
- package/script/helpers/_types.d.ts +188 -0
- package/script/helpers/_types.d.ts.map +1 -0
- package/script/helpers/_types.js +2 -0
- package/script/helpers/mod.d.ts +90 -0
- package/script/helpers/mod.d.ts.map +1 -0
- package/script/helpers/mod.js +106 -0
- package/script/helpers/operations/batch.d.ts +109 -0
- package/script/helpers/operations/batch.d.ts.map +1 -0
- package/script/helpers/operations/batch.js +144 -0
- package/script/helpers/operations/combination.d.ts +162 -0
- package/script/helpers/operations/combination.d.ts.map +1 -0
- package/script/helpers/operations/combination.js +355 -0
- package/script/helpers/operations/conditional.d.ts +211 -0
- package/script/helpers/operations/conditional.d.ts.map +1 -0
- package/script/helpers/operations/conditional.js +286 -0
- package/script/helpers/operations/core.d.ts +198 -0
- package/script/helpers/operations/core.d.ts.map +1 -0
- package/script/helpers/operations/core.js +272 -0
- package/script/helpers/operations/errors.d.ts +277 -0
- package/script/helpers/operations/errors.d.ts.map +1 -0
- package/script/helpers/operations/errors.js +387 -0
- package/script/helpers/operations/mod.d.ts +26 -0
- package/script/helpers/operations/mod.d.ts.map +1 -0
- package/script/helpers/operations/mod.js +41 -0
- package/script/helpers/operations/timing.d.ts +206 -0
- package/script/helpers/operations/timing.d.ts.map +1 -0
- package/script/helpers/operations/timing.js +464 -0
- package/script/helpers/operators.d.ts +520 -0
- package/script/helpers/operators.d.ts.map +1 -0
- package/script/helpers/operators.js +570 -0
- package/script/helpers/pipe.d.ts +118 -0
- package/script/helpers/pipe.d.ts.map +1 -0
- package/script/helpers/pipe.js +132 -0
- package/script/helpers/utils.d.ts +142 -0
- package/script/helpers/utils.d.ts.map +1 -0
- package/script/helpers/utils.js +200 -0
- package/script/mod.d.ts +863 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +877 -0
- package/script/observable.d.ts +1610 -0
- package/script/observable.d.ts.map +1 -0
- package/script/observable.js +1984 -0
- package/script/package.json +3 -0
- package/script/queue.d.ts +201 -0
- package/script/queue.d.ts.map +1 -0
- package/script/queue.js +286 -0
- package/script/symbol.d.ts +60 -0
- package/script/symbol.d.ts.map +1 -0
- package/script/symbol.js +135 -0
package/script/events.js
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var _EventBus_subscribers, _EventBus_closed;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.EventBus = void 0;
|
|
16
|
+
exports.createEventDispatcher = createEventDispatcher;
|
|
17
|
+
exports.waitForEvent = waitForEvent;
|
|
18
|
+
exports.withReplay = withReplay;
|
|
19
|
+
/**
|
|
20
|
+
* Multicast event primitives built on top of the Observable runtime.
|
|
21
|
+
*
|
|
22
|
+
* This entrypoint is for the hot side of the library: shared event streams that
|
|
23
|
+
* multiple consumers can listen to at the same time. It exports `EventBus` for
|
|
24
|
+
* one-to-many pub/sub, `createEventDispatcher` for named and type-safe events,
|
|
25
|
+
* and helpers such as `withReplay` and `waitForEvent` for common coordination
|
|
26
|
+
* patterns.
|
|
27
|
+
*
|
|
28
|
+
* Use `Observable` when each subscription should start fresh work. Use this
|
|
29
|
+
* module when one emission should fan out to many listeners, such as UI events,
|
|
30
|
+
* app-wide notifications, or workflow status updates.
|
|
31
|
+
*
|
|
32
|
+
* @module
|
|
33
|
+
*/
|
|
34
|
+
require("./_dnt.polyfills.js");
|
|
35
|
+
const observable_js_1 = require("./observable.js");
|
|
36
|
+
const symbol_js_1 = require("./symbol.js");
|
|
37
|
+
const queue_js_1 = require("./queue.js"); // Assume path to your queue utils
|
|
38
|
+
/**
|
|
39
|
+
* A multicast event bus that extends {@link Observable<T>}, allowing
|
|
40
|
+
* emission of values to multiple subscribers and supporting both
|
|
41
|
+
* Observer-style and async-iterator consumption.
|
|
42
|
+
*
|
|
43
|
+
* @typeParam T - The type of values emitted by this bus.
|
|
44
|
+
*
|
|
45
|
+
* - Calling {@link emit} delivers the value to all active subscribers.
|
|
46
|
+
* - Calling {@link close} completes all subscribers and prevents further emissions.
|
|
47
|
+
* - Implements both {@link Symbol.dispose} and {@link Symbol.asyncDispose}
|
|
48
|
+
* for cleanup in synchronous and asynchronous contexts.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { EventBus } from './EventBus.ts';
|
|
53
|
+
*
|
|
54
|
+
* // Create a bus for string messages
|
|
55
|
+
* const bus = new EventBus<string>();
|
|
56
|
+
*
|
|
57
|
+
* // Subscribe using Observer
|
|
58
|
+
* bus.events.subscribe({
|
|
59
|
+
* next(msg) { console.log('Received:', msg); },
|
|
60
|
+
* complete() { console.log('Bus closed'); }
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Emit values
|
|
64
|
+
* bus.emit('hello');
|
|
65
|
+
* bus.emit('world');
|
|
66
|
+
*
|
|
67
|
+
* // Close the bus
|
|
68
|
+
* bus.close();
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
class EventBus extends observable_js_1.Observable {
|
|
72
|
+
/**
|
|
73
|
+
* Construct a new EventBus instance.
|
|
74
|
+
*
|
|
75
|
+
* The base {@link Observable} constructor is invoked with the subscriber
|
|
76
|
+
* registration logic, adding and removing subscribers to the internal set.
|
|
77
|
+
*/
|
|
78
|
+
constructor() {
|
|
79
|
+
super((subscriber) => {
|
|
80
|
+
if (__classPrivateFieldGet(this, _EventBus_closed, "f")) {
|
|
81
|
+
subscriber.complete?.();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
__classPrivateFieldGet(this, _EventBus_subscribers, "f").add(subscriber);
|
|
85
|
+
return () => {
|
|
86
|
+
__classPrivateFieldGet(this, _EventBus_subscribers, "f").delete(subscriber);
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
/** Active subscribers receiving emitted values */
|
|
90
|
+
_EventBus_subscribers.set(this, new Set());
|
|
91
|
+
/** Tracks whether the bus has been closed */
|
|
92
|
+
_EventBus_closed.set(this, false);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Exposes the bus itself as an {@link Observable<T>} for subscription.
|
|
96
|
+
*
|
|
97
|
+
* @returns The current instance as an Observable of T.
|
|
98
|
+
*/
|
|
99
|
+
get events() {
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Emit a value to all active subscribers.
|
|
104
|
+
*
|
|
105
|
+
* @param value - The value to deliver.
|
|
106
|
+
*/
|
|
107
|
+
emit(value) {
|
|
108
|
+
if (__classPrivateFieldGet(this, _EventBus_closed, "f"))
|
|
109
|
+
return;
|
|
110
|
+
for (const subscriber of __classPrivateFieldGet(this, _EventBus_subscribers, "f")) {
|
|
111
|
+
subscriber.next?.(value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Close the bus, completing all subscribers and preventing further emits.
|
|
116
|
+
*/
|
|
117
|
+
close() {
|
|
118
|
+
if (__classPrivateFieldGet(this, _EventBus_closed, "f"))
|
|
119
|
+
return;
|
|
120
|
+
__classPrivateFieldSet(this, _EventBus_closed, true, "f");
|
|
121
|
+
for (const subscriber of __classPrivateFieldGet(this, _EventBus_subscribers, "f")) {
|
|
122
|
+
subscriber.complete?.();
|
|
123
|
+
}
|
|
124
|
+
__classPrivateFieldGet(this, _EventBus_subscribers, "f").clear();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Synchronous disposal method (for `using` syntax).
|
|
128
|
+
*
|
|
129
|
+
* Alias for {@link close}.
|
|
130
|
+
*/
|
|
131
|
+
[(_EventBus_subscribers = new WeakMap(), _EventBus_closed = new WeakMap(), symbol_js_1.Symbol.dispose)]() {
|
|
132
|
+
this.close();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Asynchronous disposal method.
|
|
136
|
+
*
|
|
137
|
+
* Alias for {@link close}.
|
|
138
|
+
*/
|
|
139
|
+
async [symbol_js_1.Symbol.asyncDispose]() {
|
|
140
|
+
return await this.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.EventBus = EventBus;
|
|
144
|
+
/**
|
|
145
|
+
* Creates a strongly-typed event bus based on {@link EventBus}, ensuring
|
|
146
|
+
* that both `emit` and `on` methods enforce matching event names and payload types.
|
|
147
|
+
*
|
|
148
|
+
* @typeParam E - The event map type, mapping event names to payloads.
|
|
149
|
+
*
|
|
150
|
+
* @returns An object with the following methods:
|
|
151
|
+
* - `emit(name, payload)`: Emit an event.
|
|
152
|
+
* - `on(name, handler)`: Subscribe to a specific event.
|
|
153
|
+
* - `events`: Observable stream of all events.
|
|
154
|
+
* - `close()`: Close the bus and complete all subscribers.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* interface MyEvents {
|
|
159
|
+
* message: { text: string };
|
|
160
|
+
* error: { code: number; message: string };
|
|
161
|
+
* }
|
|
162
|
+
*
|
|
163
|
+
* const bus = createTypedEventBus<MyEvents>();
|
|
164
|
+
*
|
|
165
|
+
* // Subscribe to `message` events
|
|
166
|
+
* bus.on('message', payload => {
|
|
167
|
+
* console.log('New message:', payload.text);
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* // Emit an event
|
|
171
|
+
* bus.emit('message', { text: 'Hello World' });
|
|
172
|
+
*
|
|
173
|
+
* // Close the bus when done
|
|
174
|
+
* bus.close();
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
function createEventDispatcher() {
|
|
178
|
+
// Internal bus carries a union of all event types and payloads
|
|
179
|
+
const bus = new EventBus();
|
|
180
|
+
return {
|
|
181
|
+
/**
|
|
182
|
+
* Emit an event with the given name and payload.
|
|
183
|
+
* @param name - The event name.
|
|
184
|
+
* @param payload - The payload matching the event name.
|
|
185
|
+
*/
|
|
186
|
+
emit(name, payload) {
|
|
187
|
+
bus.emit({ type: name, payload });
|
|
188
|
+
},
|
|
189
|
+
/**
|
|
190
|
+
* Subscribe to a specific event by name.
|
|
191
|
+
* Only events with a matching `type` will invoke the handler.
|
|
192
|
+
* @param name - The event name to listen for.
|
|
193
|
+
* @param handler - The callback invoked with the event payload.
|
|
194
|
+
* @returns A subscription object with `unsubscribe()`.
|
|
195
|
+
*/
|
|
196
|
+
on(name, handler) {
|
|
197
|
+
return bus.events.subscribe({
|
|
198
|
+
next(event) {
|
|
199
|
+
if (event.type === name) {
|
|
200
|
+
handler(event.payload);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
/**
|
|
206
|
+
* Observable stream of all emitted events, carrying `{ type, payload }` objects.
|
|
207
|
+
*/
|
|
208
|
+
events: bus.events,
|
|
209
|
+
/**
|
|
210
|
+
* Synchronous disposal method (for `using` syntax).
|
|
211
|
+
* Closes the bus and completes all subscribers.
|
|
212
|
+
*/
|
|
213
|
+
[symbol_js_1.Symbol.dispose]() {
|
|
214
|
+
bus[symbol_js_1.Symbol.dispose]();
|
|
215
|
+
},
|
|
216
|
+
/**
|
|
217
|
+
* Asynchronous disposal method.
|
|
218
|
+
* Closes the bus and completes all subscribers.
|
|
219
|
+
*/
|
|
220
|
+
[symbol_js_1.Symbol.asyncDispose]() {
|
|
221
|
+
return bus[symbol_js_1.Symbol.asyncDispose]();
|
|
222
|
+
},
|
|
223
|
+
/**
|
|
224
|
+
* Close the bus, completing all subscribers and preventing further emits.
|
|
225
|
+
*/
|
|
226
|
+
close() {
|
|
227
|
+
bus.close();
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Waits for the next occurrence of a specific event on a typed event bus.
|
|
233
|
+
* Resolves with the event payload when the named event fires.
|
|
234
|
+
* Can be aborted or optionally reject if the bus closes first.
|
|
235
|
+
*
|
|
236
|
+
* @typeParam E - The event map type.
|
|
237
|
+
* @typeParam K - The specific event key to listen for.
|
|
238
|
+
*
|
|
239
|
+
* @param bus - An object with an `events` Observable emitting `{ type, payload }`.
|
|
240
|
+
* @param type - The event name to wait for.
|
|
241
|
+
* @param options - Optional signal to abort, and throwOnClose behavior.
|
|
242
|
+
* @returns A promise resolving to the payload of the event, or rejecting on error/abort/close.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* interface MyEvents {
|
|
247
|
+
* data: { value: number };
|
|
248
|
+
* done: void;
|
|
249
|
+
* }
|
|
250
|
+
*
|
|
251
|
+
* const bus = createTypedEventBus<MyEvents>();
|
|
252
|
+
*
|
|
253
|
+
* // somewhere else...
|
|
254
|
+
* waitForEvent(bus, 'data').then(payload => {
|
|
255
|
+
* console.log('Data arrived:', payload.value);
|
|
256
|
+
* });
|
|
257
|
+
*
|
|
258
|
+
* // later
|
|
259
|
+
* bus.emit('data', { value: 42 });
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
function waitForEvent(bus, type, { signal, throwOnClose = false } = {}) {
|
|
263
|
+
const { resolve, reject, promise } = Promise.withResolvers();
|
|
264
|
+
let settled = false;
|
|
265
|
+
// Immediate abort
|
|
266
|
+
if (signal?.aborted) {
|
|
267
|
+
reject(signal.reason);
|
|
268
|
+
return promise;
|
|
269
|
+
}
|
|
270
|
+
const subscription_ref = {};
|
|
271
|
+
function cleanup() {
|
|
272
|
+
subscription_ref.current?.unsubscribe?.();
|
|
273
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
274
|
+
}
|
|
275
|
+
function onAbort() {
|
|
276
|
+
if (settled)
|
|
277
|
+
return;
|
|
278
|
+
settled = true;
|
|
279
|
+
cleanup();
|
|
280
|
+
reject(signal.reason);
|
|
281
|
+
}
|
|
282
|
+
signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
283
|
+
subscription_ref.current = bus.events.subscribe({
|
|
284
|
+
next(event) {
|
|
285
|
+
if (settled)
|
|
286
|
+
return;
|
|
287
|
+
if (event.type === type) {
|
|
288
|
+
settled = true;
|
|
289
|
+
cleanup();
|
|
290
|
+
// cast payload to the correct type
|
|
291
|
+
resolve(event.payload);
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
error(err) {
|
|
295
|
+
if (settled)
|
|
296
|
+
return;
|
|
297
|
+
settled = true;
|
|
298
|
+
cleanup();
|
|
299
|
+
reject(err);
|
|
300
|
+
},
|
|
301
|
+
complete() {
|
|
302
|
+
if (settled)
|
|
303
|
+
return;
|
|
304
|
+
settled = true;
|
|
305
|
+
cleanup();
|
|
306
|
+
if (throwOnClose) {
|
|
307
|
+
reject(new Error(`Stream closed before event "${String(type)}" fired`));
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
resolve(undefined);
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
// We need both hooks for full race coverage:
|
|
315
|
+
// 1. the listener above catches aborts that happen before or during
|
|
316
|
+
// subscription setup, so the promise rejects immediately
|
|
317
|
+
// 2. this re-check catches the narrow case where that abort happened before
|
|
318
|
+
// `subscription_ref.current` was assigned, so we can still unsubscribe the
|
|
319
|
+
// newly created subscription instead of leaving it attached. For example,
|
|
320
|
+
// the signal can abort synchronously from inside `addEventListener()`
|
|
321
|
+
// before control returns to the subscription assignment above.
|
|
322
|
+
if (signal?.aborted) {
|
|
323
|
+
onAbort();
|
|
324
|
+
}
|
|
325
|
+
return promise;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Adds replay capability to an Observable, multicasting values to multiple subscribers
|
|
329
|
+
* while maintaining a buffer of recent emissions.
|
|
330
|
+
*
|
|
331
|
+
* Without replay, each new subscriber triggers a fresh execution of the source Observable:
|
|
332
|
+
* ```ts
|
|
333
|
+
* const apiCall = new Observable(subscriber => {
|
|
334
|
+
* console.log('Making expensive API call...');
|
|
335
|
+
* fetch('/api/data').then(response => subscriber.next(response));
|
|
336
|
+
* });
|
|
337
|
+
*
|
|
338
|
+
* apiCall.subscribe(data1 => {}); // Triggers API call #1
|
|
339
|
+
* apiCall.subscribe(data2 => {}); // Triggers API call #2 (duplicate!)
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* With replay, the source executes once and shares results:
|
|
343
|
+
* ```ts
|
|
344
|
+
* const sharedApi = withReplay(apiCall, { count: 1, mode: 'lazy' });
|
|
345
|
+
*
|
|
346
|
+
* sharedApi.subscribe(data1 => {}); // Triggers API call
|
|
347
|
+
* sharedApi.subscribe(data2 => {}); // Gets cached result, no new call!
|
|
348
|
+
* ```
|
|
349
|
+
*
|
|
350
|
+
* ## Memory Considerations
|
|
351
|
+
*
|
|
352
|
+
* - Buffer size directly impacts memory usage: `count * sizeof(T)`
|
|
353
|
+
* - 'eager' mode holds references even with no subscribers (potential memory leak)
|
|
354
|
+
* - 'lazy' mode clears buffer when all subscribers disconnect (automatic cleanup)
|
|
355
|
+
* - Consider using finite counts for long-running streams to prevent unbounded growth
|
|
356
|
+
*
|
|
357
|
+
* > **Note**: Infinite buffers are by default capped at 1000 items to prevent memory issues.
|
|
358
|
+
* > The primary reason for this cap is because some runtimes such as Deno and Node.js
|
|
359
|
+
* > litereally crash when you try to allocate Ininity-sized arrays.
|
|
360
|
+
*
|
|
361
|
+
* ## Performance Characteristics
|
|
362
|
+
*
|
|
363
|
+
* - Enqueue/Dequeue: O(1) constant time
|
|
364
|
+
* - New subscriber replay: O(n) where n = buffer size
|
|
365
|
+
* - Memory overhead: One queue + subscriber set + source subscription
|
|
366
|
+
*
|
|
367
|
+
* ## Edge Cases & Gotchas
|
|
368
|
+
*
|
|
369
|
+
* 1. **Late subscribers in eager mode**: May receive very old values if the source
|
|
370
|
+
* emitted long ago and no cleanup occurred.
|
|
371
|
+
*
|
|
372
|
+
* 2. **Infinite buffers**: Without a count limit, buffers grow indefinitely.
|
|
373
|
+
* Always set a reasonable count for production use.
|
|
374
|
+
*
|
|
375
|
+
* 3. **Error handling**: Errors are multicast to all subscribers but don't clear
|
|
376
|
+
* the buffer. New subscribers still get the replay before the error.
|
|
377
|
+
*
|
|
378
|
+
* 4. **Completion**: The source completion is multicast, but the replay buffer
|
|
379
|
+
* remains accessible to new subscribers (they get replay + completion).
|
|
380
|
+
*
|
|
381
|
+
* @param source The source Observable to add replay behavior to
|
|
382
|
+
* @param options Configuration for replay behavior
|
|
383
|
+
* @returns A new Observable with replay capability
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```ts
|
|
387
|
+
* // Lazy mode - only buffers when subscribers are present
|
|
388
|
+
* const shared = withReplay(expensive, {
|
|
389
|
+
* count: 5,
|
|
390
|
+
* mode: 'lazy' // Only run expensive when needed
|
|
391
|
+
* });
|
|
392
|
+
*
|
|
393
|
+
* // Eager mode - always buffering, like a flight recorder
|
|
394
|
+
* const eventLog = withReplay(systemEvents, {
|
|
395
|
+
* count: 100,
|
|
396
|
+
* mode: 'eager' // Capture events even if no one's listening
|
|
397
|
+
* });
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
function withReplay(source, { count = Infinity, mode = "lazy" } = {}) {
|
|
401
|
+
// Validate inputs
|
|
402
|
+
if (count <= 0) {
|
|
403
|
+
throw new Error(`Replay count must be positive, got {count}`);
|
|
404
|
+
}
|
|
405
|
+
// Shared state across all subscribers
|
|
406
|
+
// Using 1000 as a reasonable default for "infinite" to avoid memory issues
|
|
407
|
+
const buffer = (0, queue_js_1.createQueue)(count === Infinity ? 1000 : count);
|
|
408
|
+
const subscribers = new Set();
|
|
409
|
+
const observer = {
|
|
410
|
+
next(value) {
|
|
411
|
+
// Manage buffer capacity
|
|
412
|
+
if (count !== Infinity && (0, queue_js_1.isFull)(buffer)) {
|
|
413
|
+
(0, queue_js_1.dequeue)(buffer); // Remove oldest
|
|
414
|
+
}
|
|
415
|
+
(0, queue_js_1.enqueue)(buffer, value);
|
|
416
|
+
// Emit to all active subscribers
|
|
417
|
+
for (const sub of subscribers) {
|
|
418
|
+
sub.next(value);
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
error(err) {
|
|
422
|
+
for (const sub of subscribers) {
|
|
423
|
+
sub.error(err);
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
complete() {
|
|
427
|
+
for (const sub of subscribers) {
|
|
428
|
+
sub.complete();
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
const isEager = mode === "eager";
|
|
433
|
+
let shared = isEager ? source.subscribe(observer) : null;
|
|
434
|
+
/**
|
|
435
|
+
* Creates the replay Observable that new subscribers will receive.
|
|
436
|
+
*/
|
|
437
|
+
return new observable_js_1.Observable((subscriber) => {
|
|
438
|
+
// Step 1: Replay buffered values to the new subscriber
|
|
439
|
+
(0, queue_js_1.forEach)(buffer, (item) => subscriber.next(item));
|
|
440
|
+
// Step 2: Add to active subscribers for future emissions
|
|
441
|
+
subscribers.add(subscriber);
|
|
442
|
+
// Step 3: Connect to source if needed (lazy mode, first subscriber)
|
|
443
|
+
if (!isEager && !shared && subscribers.size > 0) {
|
|
444
|
+
shared = source.subscribe(observer);
|
|
445
|
+
}
|
|
446
|
+
// Step 4: Return cleanup function
|
|
447
|
+
return () => {
|
|
448
|
+
subscribers.delete(subscriber);
|
|
449
|
+
// In lazy mode, disconnect and clear when last subscriber leaves
|
|
450
|
+
if (!isEager && subscribers.size === 0 && shared) {
|
|
451
|
+
shared.unsubscribe();
|
|
452
|
+
shared = null;
|
|
453
|
+
(0, queue_js_1.clear)(buffer); // Clear shared buffer when fully disconnected
|
|
454
|
+
}
|
|
455
|
+
// In eager mode, we keep the connection alive regardless
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { ObservableError } from "../error.js";
|
|
2
|
+
import type { Observable } from "../observable.js";
|
|
3
|
+
/**
|
|
4
|
+
* Type representing a stream operator function
|
|
5
|
+
* Transforms a ReadableStream of type In to a ReadableStream of type Out
|
|
6
|
+
*/
|
|
7
|
+
export type Operator<In, Out> = (stream: ReadableStream<In>) => ReadableStream<Out>;
|
|
8
|
+
/**
|
|
9
|
+
* Removes `ObservableError` from a type so operators can describe
|
|
10
|
+
* error-filtered output channels.
|
|
11
|
+
*/
|
|
12
|
+
export type ExcludeError<T> = Exclude<T, ObservableError>;
|
|
13
|
+
/**
|
|
14
|
+
* Represents an operator slot in a pipeline where the previous operator may
|
|
15
|
+
* or may not have filtered `ObservableError` values out of the stream.
|
|
16
|
+
*/
|
|
17
|
+
export type OperatorItem<T, R> = Operator<T, R> | Operator<T, ExcludeError<R>>;
|
|
18
|
+
/**
|
|
19
|
+
* Infers the item type contributed by either an Observable source or an
|
|
20
|
+
* operator in a pipe chain.
|
|
21
|
+
*/
|
|
22
|
+
export type InferSourceType<TSource extends unknown> = TSource extends Observable<unknown> ? InferObservableType<TSource> : TSource extends OperatorItem<unknown, unknown> ? InferOperatorItemOutputType<TSource> : TSource;
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the chunk type emitted by an operator.
|
|
25
|
+
*/
|
|
26
|
+
export type InferOperatorItemOutputType<TSource extends OperatorItem<any, any>> = ReturnType<TSource> extends ReadableStream<infer T> ? T : never;
|
|
27
|
+
/**
|
|
28
|
+
* Extracts the value type emitted by an Observable.
|
|
29
|
+
*/
|
|
30
|
+
export type InferObservableType<TSource extends Observable<unknown>> = TSource extends Observable<infer R> ? R : any;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the first item in a non-empty tuple.
|
|
33
|
+
*/
|
|
34
|
+
export type FirstTupleItem<TTuple extends readonly [unknown, ...unknown[]]> = TTuple[0];
|
|
35
|
+
/**
|
|
36
|
+
* Returns the last item in any tuple shape.
|
|
37
|
+
*/
|
|
38
|
+
export type GenericLastTupleItem<T extends readonly any[]> = T extends [
|
|
39
|
+
...infer _,
|
|
40
|
+
infer L
|
|
41
|
+
] ? L : never;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the last tuple item only when it is a valid operator item.
|
|
44
|
+
*/
|
|
45
|
+
export type LastTupleItem<T extends readonly unknown[]> = GenericLastTupleItem<T> extends OperatorItem<any, any> ? GenericLastTupleItem<T> : never;
|
|
46
|
+
/**
|
|
47
|
+
* Computes the Observable type returned by a `pipe()` call from the source and
|
|
48
|
+
* its final operator.
|
|
49
|
+
*/
|
|
50
|
+
export type ObservableWithPipe<TPipe extends readonly [Observable<unknown>, ...OperatorItem<any, unknown>[]]> = Observable<InferOperatorItemOutputType<LastTupleItem<TPipe>>>;
|
|
51
|
+
/**
|
|
52
|
+
* Type representing how to handle errors in operators
|
|
53
|
+
* - "ignore" => errors wrapped in ObservableError will be used as values
|
|
54
|
+
* and can then be transformed as the operator sees fit
|
|
55
|
+
* - "pass-through" => errors automatically pass through, meaning ObservableError
|
|
56
|
+
* will not appear as a value
|
|
57
|
+
* - "throw" => errors will cause the stream to throw and terminate
|
|
58
|
+
* - "manual" => errors are passed to the transform function to handle manually
|
|
59
|
+
*/
|
|
60
|
+
export type OperatorErrorMode = "ignore" | "pass-through" | "throw" | "manual";
|
|
61
|
+
/**
|
|
62
|
+
* Base interface with properties shared across all transform options
|
|
63
|
+
*/
|
|
64
|
+
export interface BaseTransformOptions {
|
|
65
|
+
/**
|
|
66
|
+
* Optional name for the operator (used in error reporting)
|
|
67
|
+
*/
|
|
68
|
+
name?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Options for using an existing TransformStream
|
|
72
|
+
*/
|
|
73
|
+
export interface TransformStreamOptions<T, R> extends BaseTransformOptions {
|
|
74
|
+
/**
|
|
75
|
+
* An existing TransformStream to use for transformation
|
|
76
|
+
*/
|
|
77
|
+
stream: (opts: TransformStreamOptions<T, R>) => TransformStream<T, R>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Options for custom transformation logic
|
|
81
|
+
*/
|
|
82
|
+
export interface TransformFunctionOptions<T, R> extends BaseTransformOptions {
|
|
83
|
+
/**
|
|
84
|
+
* How to handle errors in the stream:
|
|
85
|
+
* - "ignore" => errors wrapped in ObservableError will be used as values
|
|
86
|
+
* and can then be transformed as the operator sees fit
|
|
87
|
+
* - "pass-through" => errors automatically pass through, meaning ObservableError
|
|
88
|
+
* will not appear as a value
|
|
89
|
+
* - "throw" => errors will cause the stream to throw and terminate
|
|
90
|
+
* - "manual" => errors are passed to the transform function to handle manually
|
|
91
|
+
* @default "pass-through"
|
|
92
|
+
*/
|
|
93
|
+
errorMode?: OperatorErrorMode;
|
|
94
|
+
/**
|
|
95
|
+
* Function to transform each chunk
|
|
96
|
+
* @param chunk - The input chunk
|
|
97
|
+
* @param controller - The TransformStreamDefaultController
|
|
98
|
+
* @returns The transformed chunk(s) or undefined to filter out the chunk
|
|
99
|
+
*/
|
|
100
|
+
transform: (chunk: T, controller: TransformStreamDefaultController<R>) => R | undefined | void | null | Promise<R | undefined | void | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Function called when the stream is about to close
|
|
103
|
+
* Can enqueue final chunks before closing
|
|
104
|
+
* @param controller - The TransformStreamDefaultController
|
|
105
|
+
*/
|
|
106
|
+
flush?: (controller: TransformStreamDefaultController<R>) => void | Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Called when the stream starts, before processing any chunks
|
|
109
|
+
* @param controller - The TransformStreamDefaultController
|
|
110
|
+
*/
|
|
111
|
+
start?: (controller: TransformStreamDefaultController<R>) => void | Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Called when the stream is cancelled before natural completion
|
|
114
|
+
*/
|
|
115
|
+
cancel?: (reason?: unknown) => void | Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Union type for all createOperator options
|
|
119
|
+
*/
|
|
120
|
+
export type CreateOperatorOptions<T, R> = TransformStreamOptions<T, R> | TransformFunctionOptions<T, R>;
|
|
121
|
+
/**
|
|
122
|
+
* Options for stateful transformation logic
|
|
123
|
+
*/
|
|
124
|
+
export interface StatefulTransformFunctionOptions<T, R, S> extends BaseTransformOptions {
|
|
125
|
+
/**
|
|
126
|
+
* How to handle errors in the stream:
|
|
127
|
+
* - "ignore" => errors wrapped in ObservableError will be used as values
|
|
128
|
+
* and can then be transformed as the operator sees fit
|
|
129
|
+
* - "pass-through" => errors automatically pass through, meaning ObservableError
|
|
130
|
+
* will not appear as a value
|
|
131
|
+
* - "throw" => errors will cause the stream to throw and terminate
|
|
132
|
+
* - "manual" => errors are passed to the transform function to handle manually
|
|
133
|
+
* @default "pass-through"
|
|
134
|
+
*/
|
|
135
|
+
errorMode?: OperatorErrorMode;
|
|
136
|
+
/**
|
|
137
|
+
* Function to create the initial state
|
|
138
|
+
* @returns The initial state
|
|
139
|
+
*/
|
|
140
|
+
createState: () => S;
|
|
141
|
+
/**
|
|
142
|
+
* Function to transform each chunk, with access to the current state
|
|
143
|
+
* @param chunk - The input chunk
|
|
144
|
+
* @param state - The current state (can be modified)
|
|
145
|
+
* @param controller - The TransformStreamDefaultController
|
|
146
|
+
*/
|
|
147
|
+
transform: (chunk: T, state: S, controller: TransformStreamDefaultController<R>) => void | Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Function called when the stream is about to close
|
|
150
|
+
* Can enqueue final chunks based on the state
|
|
151
|
+
* @param state - The final state
|
|
152
|
+
* @param controller - The TransformStreamDefaultController
|
|
153
|
+
*/
|
|
154
|
+
flush?: (state: S, controller: TransformStreamDefaultController<R>) => void | Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Called when the stream starts, before processing any chunks
|
|
157
|
+
* @param state - The initial state
|
|
158
|
+
* @param controller - The TransformStreamDefaultController
|
|
159
|
+
*/
|
|
160
|
+
start?: (state: S, controller: TransformStreamDefaultController<R>) => void | Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Called when the stream is cancelled before natural completion
|
|
163
|
+
* @param state - The current state
|
|
164
|
+
*/
|
|
165
|
+
cancel?: (state: S, reason?: unknown) => void | Promise<void>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Context for transform handlers
|
|
169
|
+
* This interface provides additional information for the transform handler,
|
|
170
|
+
* such as the operator name, whether it is
|
|
171
|
+
* stateful, and any associated state.
|
|
172
|
+
* @typeParam S - State type (if applicable)
|
|
173
|
+
*/
|
|
174
|
+
export interface TransformHandlerContext<S extends unknown = undefined> {
|
|
175
|
+
/**
|
|
176
|
+
* Human-readable operator name used in wrapped error messages.
|
|
177
|
+
*/
|
|
178
|
+
operatorName?: string;
|
|
179
|
+
/**
|
|
180
|
+
* Indicates that the lifecycle handler should pass shared state through.
|
|
181
|
+
*/
|
|
182
|
+
isStateful?: boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Shared operator state for stateful transforms.
|
|
185
|
+
*/
|
|
186
|
+
state?: S;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=_types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_types.d.ts","sourceRoot":"","sources":["../../src/helpers/_types.ts"],"names":[],"mappings":"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"}
|