@vampgg/utils 1.0.0-beta.1

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.
@@ -0,0 +1,156 @@
1
+ //#region src/async-queue.ts
2
+ var AsyncQueueOverflowError = class extends Error {
3
+ constructor(highWaterMark) {
4
+ super(`async queue overflowed (highWaterMark=${highWaterMark})`);
5
+ this.name = "AsyncQueueOverflowError";
6
+ }
7
+ };
8
+ var AsyncQueue = class {
9
+ buffer;
10
+ head = 0;
11
+ count = 0;
12
+ highWaterMark;
13
+ overflow;
14
+ pendingResolve = null;
15
+ pendingReject = null;
16
+ closed = false;
17
+ error;
18
+ hasError = false;
19
+ onDispose;
20
+ disposed = false;
21
+ constructor(opts = {}, onDispose) {
22
+ this.highWaterMark = opts.highWaterMark ?? 1024;
23
+ this.overflow = opts.overflow ?? "error";
24
+ this.buffer = new Array(Math.min(this.highWaterMark, 32));
25
+ this.onDispose = onDispose;
26
+ }
27
+ /** Producer: enqueue a value. Returns false if the buffer is full (backpressure signal). */
28
+ push(value) {
29
+ if (this.closed || this.hasError) return false;
30
+ if (this.pendingResolve) {
31
+ const resolve = this.pendingResolve;
32
+ this.pendingResolve = null;
33
+ this.pendingReject = null;
34
+ resolve({
35
+ value,
36
+ done: false
37
+ });
38
+ return true;
39
+ }
40
+ if (this.count >= this.highWaterMark) {
41
+ if (this.overflow === "error") {
42
+ this.fail(new AsyncQueueOverflowError(this.highWaterMark));
43
+ return false;
44
+ }
45
+ return false;
46
+ }
47
+ this.enqueue(value);
48
+ return true;
49
+ }
50
+ /** Producer: terminate the stream as a clean completion. Idempotent. */
51
+ close() {
52
+ if (this.closed || this.hasError) return;
53
+ this.closed = true;
54
+ if (this.pendingResolve) {
55
+ const resolve = this.pendingResolve;
56
+ this.pendingResolve = null;
57
+ this.pendingReject = null;
58
+ resolve({
59
+ value: void 0,
60
+ done: true
61
+ });
62
+ }
63
+ }
64
+ /** Producer: terminate the stream with an error thrown into the consumer. Idempotent. */
65
+ fail(error) {
66
+ if (this.closed || this.hasError) return;
67
+ this.hasError = true;
68
+ this.error = error;
69
+ if (this.pendingReject) {
70
+ const reject = this.pendingReject;
71
+ this.pendingResolve = null;
72
+ this.pendingReject = null;
73
+ reject(error);
74
+ }
75
+ }
76
+ async next() {
77
+ if (this.count > 0) return {
78
+ value: this.dequeue(),
79
+ done: false
80
+ };
81
+ if (this.hasError) {
82
+ await this.dispose();
83
+ throw this.error;
84
+ }
85
+ if (this.closed) {
86
+ await this.dispose();
87
+ return {
88
+ value: void 0,
89
+ done: true
90
+ };
91
+ }
92
+ return new Promise((resolve, reject) => {
93
+ this.pendingResolve = resolve;
94
+ this.pendingReject = reject;
95
+ });
96
+ }
97
+ /** Consumer aborted early (break / return). Runs dispose and ends the stream. */
98
+ async return(value) {
99
+ this.closed = true;
100
+ if (this.pendingResolve) {
101
+ const resolve = this.pendingResolve;
102
+ this.pendingResolve = null;
103
+ this.pendingReject = null;
104
+ resolve({
105
+ value: void 0,
106
+ done: true
107
+ });
108
+ }
109
+ await this.dispose();
110
+ return {
111
+ value,
112
+ done: true
113
+ };
114
+ }
115
+ /** Consumer threw. Propagate after dispose. */
116
+ async throw(e) {
117
+ this.closed = true;
118
+ if (this.pendingReject) {
119
+ const reject = this.pendingReject;
120
+ this.pendingResolve = null;
121
+ this.pendingReject = null;
122
+ reject(e);
123
+ }
124
+ await this.dispose();
125
+ throw e;
126
+ }
127
+ [Symbol.asyncIterator]() {
128
+ return this;
129
+ }
130
+ enqueue(value) {
131
+ if (this.count === this.buffer.length) this.grow();
132
+ const tail = (this.head + this.count) % this.buffer.length;
133
+ this.buffer[tail] = value;
134
+ this.count++;
135
+ }
136
+ dequeue() {
137
+ const value = this.buffer[this.head];
138
+ this.buffer[this.head] = void 0;
139
+ this.head = (this.head + 1) % this.buffer.length;
140
+ this.count--;
141
+ return value;
142
+ }
143
+ grow() {
144
+ const next = new Array(this.buffer.length * 2);
145
+ for (let i = 0; i < this.count; i++) next[i] = this.buffer[(this.head + i) % this.buffer.length];
146
+ this.buffer = next;
147
+ this.head = 0;
148
+ }
149
+ async dispose() {
150
+ if (this.disposed) return;
151
+ this.disposed = true;
152
+ await this.onDispose?.();
153
+ }
154
+ };
155
+ //#endregion
156
+ export { AsyncQueue, AsyncQueueOverflowError };
@@ -0,0 +1,37 @@
1
+ import { BebopRecord, BebopView } from "bebop";
2
+
3
+ //#region src/bebop.d.ts
4
+ declare const BEBOP_SCHEMA: Uint8Array<ArrayBuffer>;
5
+ interface Error {
6
+ readonly code: number;
7
+ readonly tag: string;
8
+ readonly stack: string;
9
+ readonly msg: string;
10
+ readonly details: Map<string, string>;
11
+ }
12
+ declare const Error: ((data: Error) => Error & BebopRecord) & {
13
+ encode(record: Error): Uint8Array<ArrayBufferLike>;
14
+ encodeInto(record: Error, view: BebopView): void;
15
+ decode(buffer: Uint8Array<ArrayBufferLike>): Error & BebopRecord;
16
+ readFrom(view: BebopView): Error;
17
+ };
18
+ interface Message {
19
+ methodId?: number;
20
+ messageId?: string;
21
+ timestamp?: Date;
22
+ deadline?: Date;
23
+ data?: Uint8Array;
24
+ credential?: string;
25
+ status?: number;
26
+ previousAttempts?: number;
27
+ msg?: string;
28
+ authorization?: string;
29
+ }
30
+ declare const Message: ((data: Message) => Message & BebopRecord) & {
31
+ encode(record: Message): Uint8Array<ArrayBufferLike>;
32
+ encodeInto(record: Message, view: BebopView): void;
33
+ decode(buffer: Uint8Array<ArrayBufferLike>): Message & BebopRecord;
34
+ readFrom(view: BebopView): Message;
35
+ };
36
+ //#endregion
37
+ export { BEBOP_SCHEMA, Error, Message };
package/dist/bebop.mjs ADDED
@@ -0,0 +1,434 @@
1
+ import { BebopView } from "bebop";
2
+ //#region src/bebop.ts
3
+ const BEBOP_SCHEMA = new Uint8Array([
4
+ 3,
5
+ 2,
6
+ 0,
7
+ 0,
8
+ 0,
9
+ 69,
10
+ 114,
11
+ 114,
12
+ 111,
13
+ 114,
14
+ 0,
15
+ 1,
16
+ 0,
17
+ 0,
18
+ 20,
19
+ 0,
20
+ 0,
21
+ 0,
22
+ 0,
23
+ 5,
24
+ 99,
25
+ 111,
26
+ 100,
27
+ 101,
28
+ 0,
29
+ 251,
30
+ 255,
31
+ 255,
32
+ 255,
33
+ 0,
34
+ 116,
35
+ 97,
36
+ 103,
37
+ 0,
38
+ 245,
39
+ 255,
40
+ 255,
41
+ 255,
42
+ 0,
43
+ 115,
44
+ 116,
45
+ 97,
46
+ 99,
47
+ 107,
48
+ 0,
49
+ 245,
50
+ 255,
51
+ 255,
52
+ 255,
53
+ 0,
54
+ 109,
55
+ 115,
56
+ 103,
57
+ 0,
58
+ 245,
59
+ 255,
60
+ 255,
61
+ 255,
62
+ 0,
63
+ 100,
64
+ 101,
65
+ 116,
66
+ 97,
67
+ 105,
68
+ 108,
69
+ 115,
70
+ 0,
71
+ 241,
72
+ 255,
73
+ 255,
74
+ 255,
75
+ 245,
76
+ 255,
77
+ 255,
78
+ 255,
79
+ 245,
80
+ 255,
81
+ 255,
82
+ 255,
83
+ 0,
84
+ 77,
85
+ 101,
86
+ 115,
87
+ 115,
88
+ 97,
89
+ 103,
90
+ 101,
91
+ 0,
92
+ 2,
93
+ 0,
94
+ 5,
95
+ 0,
96
+ 0,
97
+ 0,
98
+ 10,
99
+ 109,
100
+ 101,
101
+ 116,
102
+ 104,
103
+ 111,
104
+ 100,
105
+ 73,
106
+ 100,
107
+ 0,
108
+ 251,
109
+ 255,
110
+ 255,
111
+ 255,
112
+ 0,
113
+ 1,
114
+ 109,
115
+ 101,
116
+ 115,
117
+ 115,
118
+ 97,
119
+ 103,
120
+ 101,
121
+ 73,
122
+ 100,
123
+ 0,
124
+ 244,
125
+ 255,
126
+ 255,
127
+ 255,
128
+ 0,
129
+ 2,
130
+ 116,
131
+ 105,
132
+ 109,
133
+ 101,
134
+ 115,
135
+ 116,
136
+ 97,
137
+ 109,
138
+ 112,
139
+ 0,
140
+ 243,
141
+ 255,
142
+ 255,
143
+ 255,
144
+ 0,
145
+ 3,
146
+ 100,
147
+ 101,
148
+ 97,
149
+ 100,
150
+ 108,
151
+ 105,
152
+ 110,
153
+ 101,
154
+ 0,
155
+ 243,
156
+ 255,
157
+ 255,
158
+ 255,
159
+ 0,
160
+ 4,
161
+ 100,
162
+ 97,
163
+ 116,
164
+ 97,
165
+ 0,
166
+ 242,
167
+ 255,
168
+ 255,
169
+ 255,
170
+ 0,
171
+ 254,
172
+ 255,
173
+ 255,
174
+ 255,
175
+ 0,
176
+ 5,
177
+ 99,
178
+ 114,
179
+ 101,
180
+ 100,
181
+ 101,
182
+ 110,
183
+ 116,
184
+ 105,
185
+ 97,
186
+ 108,
187
+ 0,
188
+ 245,
189
+ 255,
190
+ 255,
191
+ 255,
192
+ 0,
193
+ 6,
194
+ 115,
195
+ 116,
196
+ 97,
197
+ 116,
198
+ 117,
199
+ 115,
200
+ 0,
201
+ 254,
202
+ 255,
203
+ 255,
204
+ 255,
205
+ 0,
206
+ 7,
207
+ 112,
208
+ 114,
209
+ 101,
210
+ 118,
211
+ 105,
212
+ 111,
213
+ 117,
214
+ 115,
215
+ 65,
216
+ 116,
217
+ 116,
218
+ 101,
219
+ 109,
220
+ 112,
221
+ 116,
222
+ 115,
223
+ 0,
224
+ 254,
225
+ 255,
226
+ 255,
227
+ 255,
228
+ 0,
229
+ 8,
230
+ 109,
231
+ 115,
232
+ 103,
233
+ 0,
234
+ 245,
235
+ 255,
236
+ 255,
237
+ 255,
238
+ 0,
239
+ 9,
240
+ 97,
241
+ 117,
242
+ 116,
243
+ 104,
244
+ 111,
245
+ 114,
246
+ 105,
247
+ 122,
248
+ 97,
249
+ 116,
250
+ 105,
251
+ 111,
252
+ 110,
253
+ 0,
254
+ 245,
255
+ 255,
256
+ 255,
257
+ 255,
258
+ 0,
259
+ 10,
260
+ 0,
261
+ 0,
262
+ 0,
263
+ 0
264
+ ]);
265
+ const Error = /*#__PURE__*/ Object.freeze(/*#__PURE__*/ Object.assign((data) => {
266
+ return Object.freeze({
267
+ ...data,
268
+ encode() {
269
+ return Error.encode(this);
270
+ }
271
+ });
272
+ }, {
273
+ encode(record) {
274
+ const view = BebopView.getInstance();
275
+ view.startWriting();
276
+ Error.encodeInto(record, view);
277
+ return view.toArray();
278
+ },
279
+ encodeInto(record, view) {
280
+ view.writeUint32(record.code);
281
+ view.writeString(record.tag);
282
+ view.writeString(record.stack);
283
+ view.writeString(record.msg);
284
+ view.writeUint32(record.details.size);
285
+ for (const [k0, v0] of record.details) {
286
+ view.writeString(k0);
287
+ view.writeString(v0);
288
+ }
289
+ },
290
+ decode(buffer) {
291
+ const view = BebopView.getInstance();
292
+ view.startReading(buffer);
293
+ return Error(Error.readFrom(view));
294
+ },
295
+ readFrom(view) {
296
+ let field0;
297
+ field0 = view.readUint32();
298
+ let field1;
299
+ field1 = view.readString();
300
+ let field2;
301
+ field2 = view.readString();
302
+ let field3;
303
+ field3 = view.readString();
304
+ let field4;
305
+ {
306
+ const length0 = view.readUint32();
307
+ field4 = /* @__PURE__ */ new Map();
308
+ for (let i0 = 0; i0 < length0; i0++) {
309
+ let k0;
310
+ let v0;
311
+ k0 = view.readString();
312
+ v0 = view.readString();
313
+ field4.set(k0, v0);
314
+ }
315
+ }
316
+ return {
317
+ code: field0,
318
+ tag: field1,
319
+ stack: field2,
320
+ msg: field3,
321
+ details: field4
322
+ };
323
+ }
324
+ }));
325
+ const Message = /*#__PURE__*/ Object.freeze(/*#__PURE__*/ Object.assign((data) => {
326
+ return {
327
+ ...data,
328
+ encode() {
329
+ return Message.encode(this);
330
+ }
331
+ };
332
+ }, {
333
+ encode(record) {
334
+ const view = BebopView.getInstance();
335
+ view.startWriting();
336
+ Message.encodeInto(record, view);
337
+ return view.toArray();
338
+ },
339
+ encodeInto(record, view) {
340
+ const pos = view.reserveMessageLength();
341
+ const start = view.length;
342
+ if (record.methodId !== void 0) {
343
+ view.writeByte(1);
344
+ view.writeUint32(record.methodId);
345
+ }
346
+ if (record.messageId !== void 0) {
347
+ view.writeByte(2);
348
+ view.writeGuid(record.messageId);
349
+ }
350
+ if (record.timestamp !== void 0) {
351
+ view.writeByte(3);
352
+ view.writeDate(record.timestamp);
353
+ }
354
+ if (record.deadline !== void 0) {
355
+ view.writeByte(4);
356
+ view.writeDate(record.deadline);
357
+ }
358
+ if (record.data !== void 0) {
359
+ view.writeByte(5);
360
+ view.writeBytes(record.data);
361
+ }
362
+ if (record.credential !== void 0) {
363
+ view.writeByte(6);
364
+ view.writeString(record.credential);
365
+ }
366
+ if (record.status !== void 0) {
367
+ view.writeByte(7);
368
+ view.writeByte(record.status);
369
+ }
370
+ if (record.previousAttempts !== void 0) {
371
+ view.writeByte(8);
372
+ view.writeByte(record.previousAttempts);
373
+ }
374
+ if (record.msg !== void 0) {
375
+ view.writeByte(9);
376
+ view.writeString(record.msg);
377
+ }
378
+ if (record.authorization !== void 0) {
379
+ view.writeByte(10);
380
+ view.writeString(record.authorization);
381
+ }
382
+ view.writeByte(0);
383
+ const end = view.length;
384
+ view.fillMessageLength(pos, end - start);
385
+ },
386
+ decode(buffer) {
387
+ const view = BebopView.getInstance();
388
+ view.startReading(buffer);
389
+ return Message(Message.readFrom(view));
390
+ },
391
+ readFrom(view) {
392
+ const message = {};
393
+ const length = view.readMessageLength();
394
+ const end = view.index + length;
395
+ while (true) switch (view.readByte()) {
396
+ case 0: return message;
397
+ case 1:
398
+ message.methodId = view.readUint32();
399
+ break;
400
+ case 2:
401
+ message.messageId = view.readGuid();
402
+ break;
403
+ case 3:
404
+ message.timestamp = view.readDate();
405
+ break;
406
+ case 4:
407
+ message.deadline = view.readDate();
408
+ break;
409
+ case 5:
410
+ message.data = view.readBytes();
411
+ break;
412
+ case 6:
413
+ message.credential = view.readString();
414
+ break;
415
+ case 7:
416
+ message.status = view.readByte();
417
+ break;
418
+ case 8:
419
+ message.previousAttempts = view.readByte();
420
+ break;
421
+ case 9:
422
+ message.msg = view.readString();
423
+ break;
424
+ case 10:
425
+ message.authorization = view.readString();
426
+ break;
427
+ default:
428
+ view.index = end;
429
+ return message;
430
+ }
431
+ }
432
+ }));
433
+ //#endregion
434
+ export { BEBOP_SCHEMA, Error, Message };
@@ -0,0 +1,11 @@
1
+ import { ConsoleLogger, TempoLogLevel, TempoLogger } from "@tempojs/common";
2
+
3
+ //#region src/context-logger.d.ts
4
+ declare class ContextLogger extends ConsoleLogger {
5
+ bindings: Record<string, unknown>;
6
+ constructor(sourceName: string, logLevel?: TempoLogLevel, parent?: TempoLogger, bindings?: Record<string, unknown>);
7
+ correlate<TLogger extends TempoLogger>(sourceName: string, correlationId?: string, asOrphan?: boolean, bindings?: Record<string, unknown>): TLogger;
8
+ clone<TLogger extends TempoLogger>(sourceName: string, asOrphan?: boolean, bindings?: Record<string, unknown>): TLogger;
9
+ }
10
+ //#endregion
11
+ export { ContextLogger };
@@ -0,0 +1,31 @@
1
+ import { ConsoleLogger, TempoLogLevel, TempoLogger } from "@tempojs/common";
2
+ //#region src/context-logger.ts
3
+ var ContextLogger = class extends ConsoleLogger {
4
+ bindings = {};
5
+ constructor(sourceName, logLevel = TempoLogLevel.Info, parent, bindings = {}) {
6
+ super(sourceName, logLevel, parent);
7
+ this.bindings = bindings || {};
8
+ TempoLogger.instances.delete(sourceName.replace(/\s+/g, "_"));
9
+ }
10
+ correlate(sourceName, correlationId, asOrphan, bindings) {
11
+ return this.clone(sourceName, asOrphan, {
12
+ ...correlationId ? { correlationId } : {},
13
+ ...bindings
14
+ });
15
+ }
16
+ clone(sourceName, asOrphan, bindings) {
17
+ const logger = Reflect.construct(this.constructor, [
18
+ sourceName,
19
+ this.logLevel,
20
+ asOrphan !== true ? this : void 0
21
+ ]);
22
+ logger.bindings = {
23
+ ...this.bindings,
24
+ ...bindings
25
+ };
26
+ if (asOrphan !== true) this.children.add(logger);
27
+ return logger;
28
+ }
29
+ };
30
+ //#endregion
31
+ export { ContextLogger };
@@ -0,0 +1,16 @@
1
+ import { AsyncQueueOptions } from "./async-queue.mjs";
2
+ import { CleanupFn, Context } from "./create-event-iterator.mjs";
3
+ import { BebopRecord } from "bebop";
4
+
5
+ //#region src/create-duplex-iterator.d.ts
6
+ type Writer<T> = (context: Context<T>) => void | CleanupFn | Promise<CleanupFn | void>;
7
+ /**
8
+ * Duplex stream iterator. The outgoing generator is pumped in its own task and
9
+ * the incoming stream is drained independently off a bounded {@link AsyncQueue}
10
+ * — the two are never coupled, so an outgoing send with no incoming reply (or a
11
+ * server push with no matching outgoing send) neither deadlocks nor drops
12
+ * frames. Consumer teardown halts the outgoing pump and unsubscribes incoming.
13
+ */
14
+ declare function createDuplexIterator<T>(outgoing: AsyncGenerator<BebopRecord, void, undefined>, emitter: (record: BebopRecord) => void, incoming: Writer<T>, options?: AsyncQueueOptions): AsyncGenerator<T>;
15
+ //#endregion
16
+ export { Writer, createDuplexIterator };
@@ -0,0 +1,36 @@
1
+ import { AsyncQueue } from "./async-queue.mjs";
2
+ import { queueIterator } from "./create-event-iterator.mjs";
3
+ //#region src/create-duplex-iterator.ts
4
+ /**
5
+ * Duplex stream iterator. The outgoing generator is pumped in its own task and
6
+ * the incoming stream is drained independently off a bounded {@link AsyncQueue}
7
+ * — the two are never coupled, so an outgoing send with no incoming reply (or a
8
+ * server push with no matching outgoing send) neither deadlocks nor drops
9
+ * frames. Consumer teardown halts the outgoing pump and unsubscribes incoming.
10
+ */
11
+ function createDuplexIterator(outgoing, emitter, incoming, options) {
12
+ let unsubscribe;
13
+ const queue = new AsyncQueue(options, async () => {
14
+ await outgoing.return?.(void 0);
15
+ await unsubscribe?.();
16
+ });
17
+ const context = {
18
+ emit: (value) => {
19
+ queue.push(value);
20
+ },
21
+ cancel: () => queue.close(),
22
+ error: (e) => queue.fail(e)
23
+ };
24
+ return queueIterator(queue, async () => {
25
+ unsubscribe = await incoming(context);
26
+ (async () => {
27
+ try {
28
+ for await (const record of outgoing) emitter(record);
29
+ } catch (e) {
30
+ queue.fail(e);
31
+ }
32
+ })().catch(() => {});
33
+ });
34
+ }
35
+ //#endregion
36
+ export { createDuplexIterator };