@noormdev/sdk 1.0.0-alpha.2 → 1.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3UDETNWW.js +943 -0
- package/dist/chunk-3UDETNWW.js.map +1 -0
- package/dist/chunk-D2XW2UOP.js +42 -0
- package/dist/chunk-D2XW2UOP.js.map +1 -0
- package/dist/chunk-TBRUDUBQ.js +1099 -0
- package/dist/chunk-TBRUDUBQ.js.map +1 -0
- package/dist/chunk-UDUDHOIB.js +3136 -0
- package/dist/chunk-UDUDHOIB.js.map +1 -0
- package/dist/chunk-UOFJT5PY.js +1499 -0
- package/dist/chunk-UOFJT5PY.js.map +1 -0
- package/dist/chunk-YJBKNUTP.js +7233 -0
- package/dist/chunk-YJBKNUTP.js.map +1 -0
- package/dist/chunk-ZKYTJJIF.js +308 -0
- package/dist/chunk-ZKYTJJIF.js.map +1 -0
- package/dist/csv-T5P3IN4K.js +7 -0
- package/dist/csv-T5P3IN4K.js.map +1 -0
- package/dist/engine-27DNMF4T.js +11 -0
- package/dist/{engine-B4JH5RQJ.js.map → engine-27DNMF4T.js.map} +1 -1
- package/dist/index.d.ts +2848 -1038
- package/dist/index.js +26190 -6890
- package/dist/index.js.map +1 -1
- package/dist/json5-LNT3RGJ7.js +7 -0
- package/dist/json5-LNT3RGJ7.js.map +1 -0
- package/dist/mssql-3NNVV77C.js +121 -0
- package/dist/mssql-3NNVV77C.js.map +1 -0
- package/dist/{mysql-C2DR4TF7.js → mysql-UPMQUBLE.js} +5 -3
- package/dist/mysql-UPMQUBLE.js.map +1 -0
- package/dist/{postgres-SIDJBSIT.js → postgres-CPVTCR7W.js} +5 -3
- package/dist/postgres-CPVTCR7W.js.map +1 -0
- package/dist/{sqlite-5VZTBN5J.js → sqlite-F3ZSSDUM.js} +5 -3
- package/dist/sqlite-F3ZSSDUM.js.map +1 -0
- package/dist/sqlite-bun-LMHUMGQI.js +60 -0
- package/dist/sqlite-bun-LMHUMGQI.js.map +1 -0
- package/dist/storage-TZNQBIX3.js +8 -0
- package/dist/storage-TZNQBIX3.js.map +1 -0
- package/dist/yaml-XI7RQ2D5.js +7 -0
- package/dist/yaml-XI7RQ2D5.js.map +1 -0
- package/package.json +8 -4
- package/dist/chunk-MERTHCAJ.js +0 -299
- package/dist/chunk-MERTHCAJ.js.map +0 -1
- package/dist/engine-B4JH5RQJ.js +0 -3
- package/dist/mssql-T4M7OGEC.js +0 -46
- package/dist/mssql-T4M7OGEC.js.map +0 -1
- package/dist/mysql-C2DR4TF7.js.map +0 -1
- package/dist/postgres-SIDJBSIT.js.map +0 -1
- package/dist/sqlite-5VZTBN5J.js.map +0 -1
|
@@ -0,0 +1,3136 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
|
|
3
|
+
createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
// node_modules/@logosdx/utils/dist/esm/object-utils/index.mjs
|
|
6
|
+
var definePrivateProps = (target, props, configurable = false) => {
|
|
7
|
+
Object.entries(props).map(([prop, value]) => {
|
|
8
|
+
Object.defineProperty(target, prop, {
|
|
9
|
+
value,
|
|
10
|
+
writable: false,
|
|
11
|
+
enumerable: false,
|
|
12
|
+
configurable
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var reach = (obj, val) => {
|
|
17
|
+
const path = val.split(".");
|
|
18
|
+
return path.reduce((acc, key) => {
|
|
19
|
+
if (acc === void 0 || acc === null) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
if (acc instanceof Map) {
|
|
23
|
+
return acc.get(key);
|
|
24
|
+
}
|
|
25
|
+
if (acc instanceof Set) {
|
|
26
|
+
const has = acc.has(key);
|
|
27
|
+
const values = Array.from(acc);
|
|
28
|
+
if (has) {
|
|
29
|
+
return values[values.indexOf(key)];
|
|
30
|
+
}
|
|
31
|
+
return values[key];
|
|
32
|
+
}
|
|
33
|
+
return acc[key];
|
|
34
|
+
}, obj);
|
|
35
|
+
};
|
|
36
|
+
var setDeep = (obj, path, value) => {
|
|
37
|
+
assert(typeof obj === "object" && obj !== null, "obj must be a non-null object");
|
|
38
|
+
assert(typeof path === "string" && path.length > 0, "path must be a non-empty string");
|
|
39
|
+
const keys = path.split(".");
|
|
40
|
+
const lastKey = keys[keys.length - 1];
|
|
41
|
+
let current = obj;
|
|
42
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
43
|
+
const key = keys[i];
|
|
44
|
+
if (current === null || current === void 0) {
|
|
45
|
+
throw new Error(`Cannot set property '${key}' on ${current} at path: ${keys.slice(0, i).join(".")}`);
|
|
46
|
+
}
|
|
47
|
+
if (typeof current !== "object") {
|
|
48
|
+
throw new Error(`Cannot set property '${key}' on primitive value at path: ${keys.slice(0, i).join(".")}`);
|
|
49
|
+
}
|
|
50
|
+
if (!(key in current)) {
|
|
51
|
+
current[key] = {};
|
|
52
|
+
}
|
|
53
|
+
current = current[key];
|
|
54
|
+
}
|
|
55
|
+
if (current === null || current === void 0) {
|
|
56
|
+
throw new Error(`Cannot set property '${lastKey}' on ${current}`);
|
|
57
|
+
}
|
|
58
|
+
if (typeof current !== "object") {
|
|
59
|
+
throw new Error(`Cannot set property '${lastKey}' on primitive value`);
|
|
60
|
+
}
|
|
61
|
+
current[lastKey] = value;
|
|
62
|
+
};
|
|
63
|
+
var setDeepMany = (obj, entries) => {
|
|
64
|
+
assert(typeof obj === "object" && obj !== null, "obj must be a non-null object");
|
|
65
|
+
assert(Array.isArray(entries), "entries must be an array");
|
|
66
|
+
for (let i = 0; i < entries.length; i++) {
|
|
67
|
+
const entry = entries[i];
|
|
68
|
+
assert(Array.isArray(entry) && entry.length === 2, `entry ${i} must be a [path, value] tuple`);
|
|
69
|
+
const [path, value] = entry;
|
|
70
|
+
assert(typeof path === "string" && path.length > 0, `entry ${i} must have a non-empty string path (received: ${typeof path})`);
|
|
71
|
+
setDeep(obj, path, value);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// node_modules/@logosdx/utils/dist/esm/validation/assert.mjs
|
|
76
|
+
var AssertError = class extends Error {
|
|
77
|
+
};
|
|
78
|
+
var isOptional = (val, check) => val === void 0 || val === null || (check instanceof Function ? !!check(val) : !!check);
|
|
79
|
+
var assert = (test, message, ErrorClass) => {
|
|
80
|
+
const check = test instanceof Function ? !!test() : !!test;
|
|
81
|
+
if (check === false) {
|
|
82
|
+
throw new (ErrorClass || AssertError)(message || "assertion failed");
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var assertOptional = (val, ...rest) => {
|
|
86
|
+
if (val !== void 0) {
|
|
87
|
+
assert(...rest);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// node_modules/@logosdx/utils/dist/esm/validation/type-guards.mjs
|
|
92
|
+
var isPrimitive = (val) => val === null || val === void 0 || typeof val === "string" || typeof val === "number" || typeof val === "boolean" || typeof val === "symbol" || typeof val === "bigint";
|
|
93
|
+
var hasNoConstructor = (val) => val === null || val === void 0;
|
|
94
|
+
var hasSameConstructor = (value, compare) => hasNoConstructor(value) === false && hasNoConstructor(compare) === false && value.constructor === compare.constructor;
|
|
95
|
+
var isFunction = (a) => a instanceof Function;
|
|
96
|
+
var isObject = (a) => a instanceof Object;
|
|
97
|
+
var commonObjects = /* @__PURE__ */ new Set([
|
|
98
|
+
Date,
|
|
99
|
+
RegExp,
|
|
100
|
+
Function,
|
|
101
|
+
Error,
|
|
102
|
+
EvalError,
|
|
103
|
+
RangeError,
|
|
104
|
+
ReferenceError,
|
|
105
|
+
SyntaxError,
|
|
106
|
+
TypeError,
|
|
107
|
+
URIError,
|
|
108
|
+
AggregateError,
|
|
109
|
+
DOMException,
|
|
110
|
+
Array,
|
|
111
|
+
Set,
|
|
112
|
+
Map,
|
|
113
|
+
WeakMap,
|
|
114
|
+
WeakSet,
|
|
115
|
+
Promise,
|
|
116
|
+
Proxy,
|
|
117
|
+
Symbol,
|
|
118
|
+
BigInt,
|
|
119
|
+
WeakRef,
|
|
120
|
+
FinalizationRegistry,
|
|
121
|
+
DataView,
|
|
122
|
+
ArrayBuffer,
|
|
123
|
+
Int8Array,
|
|
124
|
+
Uint8Array,
|
|
125
|
+
Uint8ClampedArray,
|
|
126
|
+
Int16Array,
|
|
127
|
+
Uint16Array,
|
|
128
|
+
Int32Array,
|
|
129
|
+
Uint32Array,
|
|
130
|
+
Float32Array,
|
|
131
|
+
Float64Array,
|
|
132
|
+
BigInt64Array,
|
|
133
|
+
BigUint64Array,
|
|
134
|
+
FormData,
|
|
135
|
+
URLSearchParams
|
|
136
|
+
]);
|
|
137
|
+
var isPlainObject = (a) => !isPrimitive(a) && isObject(a) && !commonObjects.has(a.constructor);
|
|
138
|
+
|
|
139
|
+
// node_modules/@logosdx/utils/dist/esm/validation/values.mjs
|
|
140
|
+
var ENABLED_VALUES = /* @__PURE__ */ new Set([
|
|
141
|
+
"true",
|
|
142
|
+
"yes",
|
|
143
|
+
true
|
|
144
|
+
]);
|
|
145
|
+
var DISABLED_VALUES = /* @__PURE__ */ new Set([
|
|
146
|
+
"false",
|
|
147
|
+
"no",
|
|
148
|
+
false
|
|
149
|
+
]);
|
|
150
|
+
var isEnabledValue = (val) => {
|
|
151
|
+
return ENABLED_VALUES.has(val);
|
|
152
|
+
};
|
|
153
|
+
var isDisabledValue = (val) => {
|
|
154
|
+
return DISABLED_VALUES.has(val);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// node_modules/@logosdx/utils/dist/esm/async/attempt.mjs
|
|
158
|
+
var attempt = async (fn) => {
|
|
159
|
+
assert(isFunction(fn), "fn must be a function");
|
|
160
|
+
try {
|
|
161
|
+
return [
|
|
162
|
+
await fn(),
|
|
163
|
+
null
|
|
164
|
+
];
|
|
165
|
+
} catch (e) {
|
|
166
|
+
return [
|
|
167
|
+
null,
|
|
168
|
+
e
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var attemptSync = (fn) => {
|
|
173
|
+
assert(isFunction(fn), "fn must be a function");
|
|
174
|
+
try {
|
|
175
|
+
return [
|
|
176
|
+
fn(),
|
|
177
|
+
null
|
|
178
|
+
];
|
|
179
|
+
} catch (e) {
|
|
180
|
+
return [
|
|
181
|
+
null,
|
|
182
|
+
e
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// node_modules/@logosdx/utils/dist/esm/data-structures/helpers.mjs
|
|
188
|
+
var cloneHandlers = /* @__PURE__ */ new Map();
|
|
189
|
+
var mergeHandlers = /* @__PURE__ */ new Map();
|
|
190
|
+
var DANGEROUS_PROPS = /* @__PURE__ */ new Set([
|
|
191
|
+
"__proto__",
|
|
192
|
+
"constructor",
|
|
193
|
+
"prototype"
|
|
194
|
+
]);
|
|
195
|
+
var isDangerousKey = (key) => {
|
|
196
|
+
return typeof key === "string" && DANGEROUS_PROPS.has(key);
|
|
197
|
+
};
|
|
198
|
+
var getSafeKeys = (obj) => {
|
|
199
|
+
return Object.keys(obj).filter((key) => !isDangerousKey(key));
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// node_modules/@logosdx/utils/dist/esm/data-structures/clone.mjs
|
|
203
|
+
var prepareCloneHandlers = () => {
|
|
204
|
+
cloneHandlers.set(Array, (arr, seen) => arr.map((v) => clone(v, seen)));
|
|
205
|
+
cloneHandlers.set(Object, (obj, seen) => {
|
|
206
|
+
const copy = {};
|
|
207
|
+
const keys = Object.keys(obj);
|
|
208
|
+
for (const key of keys) {
|
|
209
|
+
if (isDangerousKey(key)) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
copy[key] = clone(obj[key], seen);
|
|
213
|
+
}
|
|
214
|
+
return copy;
|
|
215
|
+
});
|
|
216
|
+
cloneHandlers.set(Map, (_map, seen) => {
|
|
217
|
+
const copy = /* @__PURE__ */ new Map();
|
|
218
|
+
for (const entry of _map.entries()) {
|
|
219
|
+
const [key, val] = entry;
|
|
220
|
+
copy.set(key, clone(val, seen));
|
|
221
|
+
}
|
|
222
|
+
return copy;
|
|
223
|
+
});
|
|
224
|
+
cloneHandlers.set(Set, (_set, seen) => {
|
|
225
|
+
const copy = /* @__PURE__ */ new Set();
|
|
226
|
+
for (const original of _set) {
|
|
227
|
+
copy.add(clone(original, seen));
|
|
228
|
+
}
|
|
229
|
+
return copy;
|
|
230
|
+
});
|
|
231
|
+
const TYPED_ARRAYS = [
|
|
232
|
+
Int8Array,
|
|
233
|
+
Uint8Array,
|
|
234
|
+
Uint8ClampedArray,
|
|
235
|
+
Int16Array,
|
|
236
|
+
Uint16Array,
|
|
237
|
+
Int32Array,
|
|
238
|
+
Uint32Array,
|
|
239
|
+
Float32Array,
|
|
240
|
+
Float64Array,
|
|
241
|
+
BigInt64Array,
|
|
242
|
+
BigUint64Array
|
|
243
|
+
];
|
|
244
|
+
TYPED_ARRAYS.forEach((TypedArrayConstructor) => {
|
|
245
|
+
cloneHandlers.set(TypedArrayConstructor, (arr) => {
|
|
246
|
+
return new TypedArrayConstructor(arr);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
cloneHandlers.set(ArrayBuffer, (buffer) => {
|
|
250
|
+
return buffer.slice(0);
|
|
251
|
+
});
|
|
252
|
+
cloneHandlers.set(DataView, (view) => {
|
|
253
|
+
const clonedBuffer = view.buffer.slice(0);
|
|
254
|
+
return new DataView(clonedBuffer, view.byteOffset, view.byteLength);
|
|
255
|
+
});
|
|
256
|
+
cloneHandlers.set(Error, (error, seen) => {
|
|
257
|
+
const cloned = typeof structuredClone === "function" ? structuredClone(error) : new error.constructor(error.message);
|
|
258
|
+
if (error.name) {
|
|
259
|
+
cloned.name = error.name;
|
|
260
|
+
}
|
|
261
|
+
if (error.stack) {
|
|
262
|
+
cloned.stack = error.stack;
|
|
263
|
+
}
|
|
264
|
+
const keys = Object.keys(error);
|
|
265
|
+
for (const key of keys) {
|
|
266
|
+
if (key !== "name" && key !== "message" && key !== "stack" && !isDangerousKey(key)) {
|
|
267
|
+
cloned[key] = clone(error[key], seen);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return cloned;
|
|
271
|
+
});
|
|
272
|
+
cloneHandlers.set(Date, (date) => {
|
|
273
|
+
return new Date(date.getTime());
|
|
274
|
+
});
|
|
275
|
+
cloneHandlers.set(RegExp, (regex) => {
|
|
276
|
+
return new RegExp(regex.source, regex.flags);
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
var cloneHandlersInitialized = false;
|
|
280
|
+
var useRawHandler = /* @__PURE__ */ new Set([
|
|
281
|
+
ArrayBuffer,
|
|
282
|
+
DataView,
|
|
283
|
+
Int8Array,
|
|
284
|
+
Uint8Array,
|
|
285
|
+
Uint8ClampedArray,
|
|
286
|
+
Int16Array,
|
|
287
|
+
Uint16Array,
|
|
288
|
+
Int32Array,
|
|
289
|
+
Uint32Array,
|
|
290
|
+
Float32Array,
|
|
291
|
+
Float64Array,
|
|
292
|
+
BigInt64Array,
|
|
293
|
+
BigUint64Array,
|
|
294
|
+
Error,
|
|
295
|
+
Date,
|
|
296
|
+
RegExp
|
|
297
|
+
]);
|
|
298
|
+
var clone = (original, seen = /* @__PURE__ */ new WeakMap()) => {
|
|
299
|
+
if (!cloneHandlersInitialized) {
|
|
300
|
+
prepareCloneHandlers();
|
|
301
|
+
cloneHandlersInitialized = true;
|
|
302
|
+
}
|
|
303
|
+
if (isPrimitive(original)) {
|
|
304
|
+
return original;
|
|
305
|
+
}
|
|
306
|
+
if (seen.has(original)) {
|
|
307
|
+
return seen.get(original);
|
|
308
|
+
}
|
|
309
|
+
if (original instanceof Error) {
|
|
310
|
+
const cloneType2 = cloneHandlers.get(Error);
|
|
311
|
+
return cloneType2(original, seen);
|
|
312
|
+
}
|
|
313
|
+
const actualConstructor = Object.getPrototypeOf(original)?.constructor || original.constructor;
|
|
314
|
+
const cloneType = cloneHandlers.get(actualConstructor);
|
|
315
|
+
if (!cloneType) {
|
|
316
|
+
return original;
|
|
317
|
+
}
|
|
318
|
+
if (useRawHandler.has(actualConstructor)) {
|
|
319
|
+
return cloneType(original, seen);
|
|
320
|
+
}
|
|
321
|
+
let placeholder;
|
|
322
|
+
if (Array.isArray(original)) {
|
|
323
|
+
placeholder = [];
|
|
324
|
+
seen.set(original, placeholder);
|
|
325
|
+
const cloned2 = cloneType(original, seen);
|
|
326
|
+
placeholder.push(...cloned2);
|
|
327
|
+
return placeholder;
|
|
328
|
+
}
|
|
329
|
+
if (original instanceof Map) {
|
|
330
|
+
placeholder = /* @__PURE__ */ new Map();
|
|
331
|
+
seen.set(original, placeholder);
|
|
332
|
+
const cloned2 = cloneType(original, seen);
|
|
333
|
+
for (const [key, value] of cloned2) {
|
|
334
|
+
placeholder.set(key, value);
|
|
335
|
+
}
|
|
336
|
+
return placeholder;
|
|
337
|
+
}
|
|
338
|
+
if (original instanceof Set) {
|
|
339
|
+
placeholder = /* @__PURE__ */ new Set();
|
|
340
|
+
seen.set(original, placeholder);
|
|
341
|
+
const cloned2 = cloneType(original, seen);
|
|
342
|
+
for (const value of cloned2) {
|
|
343
|
+
placeholder.add(value);
|
|
344
|
+
}
|
|
345
|
+
return placeholder;
|
|
346
|
+
}
|
|
347
|
+
placeholder = {};
|
|
348
|
+
seen.set(original, placeholder);
|
|
349
|
+
const cloned = cloneType(original, seen);
|
|
350
|
+
Object.assign(placeholder, cloned);
|
|
351
|
+
return placeholder;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// node_modules/@logosdx/utils/dist/esm/data-structures/merge.mjs
|
|
355
|
+
var mergeArrays = (target, source) => {
|
|
356
|
+
for (const value of source) {
|
|
357
|
+
target.push(value);
|
|
358
|
+
}
|
|
359
|
+
return target;
|
|
360
|
+
};
|
|
361
|
+
var mergeSets = (target, source) => {
|
|
362
|
+
for (const value of source) {
|
|
363
|
+
if (!target.has(value)) {
|
|
364
|
+
target.add(value);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return target;
|
|
368
|
+
};
|
|
369
|
+
var overwriteArrays = (target, source) => {
|
|
370
|
+
target.length = 0;
|
|
371
|
+
for (const value of source) {
|
|
372
|
+
target.push(value);
|
|
373
|
+
}
|
|
374
|
+
return target;
|
|
375
|
+
};
|
|
376
|
+
var overwriteSets = (target, source) => {
|
|
377
|
+
target.clear();
|
|
378
|
+
for (const value of source) {
|
|
379
|
+
target.add(value);
|
|
380
|
+
}
|
|
381
|
+
return target;
|
|
382
|
+
};
|
|
383
|
+
var prepareMergeHandlers = () => {
|
|
384
|
+
mergeHandlers.set(Array, (target, source, options) => {
|
|
385
|
+
if (options?.mergeArrays) {
|
|
386
|
+
return mergeArrays(target, source);
|
|
387
|
+
}
|
|
388
|
+
return overwriteArrays(target, source);
|
|
389
|
+
});
|
|
390
|
+
mergeHandlers.set(Set, (target, source, options) => {
|
|
391
|
+
if (options?.mergeSets) {
|
|
392
|
+
return mergeSets(target, source);
|
|
393
|
+
}
|
|
394
|
+
return overwriteSets(target, source);
|
|
395
|
+
});
|
|
396
|
+
mergeHandlers.set(Object, (_target, _source, options) => {
|
|
397
|
+
const target = _target;
|
|
398
|
+
const source = _source;
|
|
399
|
+
const sourceKeys = Object.keys(source);
|
|
400
|
+
for (const key of sourceKeys) {
|
|
401
|
+
if (isDangerousKey(key)) {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (target[key] === void 0 || hasNoConstructor(target[key]) || hasNoConstructor(source[key])) {
|
|
405
|
+
target[key] = source[key];
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (hasSameConstructor(target[key], source[key])) {
|
|
409
|
+
target[key] = merge(target[key], source[key], options);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
target[key] = source[key];
|
|
413
|
+
}
|
|
414
|
+
return target;
|
|
415
|
+
});
|
|
416
|
+
mergeHandlers.set(Map, (_target, _source, options) => {
|
|
417
|
+
const target = _target;
|
|
418
|
+
const source = _source;
|
|
419
|
+
for (const [key, bValue] of source.entries()) {
|
|
420
|
+
if (!target.has(key)) {
|
|
421
|
+
target.set(key, bValue);
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
const aValue = target.get(key);
|
|
425
|
+
if (hasNoConstructor(aValue) || hasNoConstructor(bValue)) {
|
|
426
|
+
target.set(key, bValue);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
if (hasSameConstructor(bValue, aValue)) {
|
|
430
|
+
target.set(key, merge(aValue, bValue, options));
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
target.set(key, bValue);
|
|
434
|
+
}
|
|
435
|
+
return target;
|
|
436
|
+
});
|
|
437
|
+
mergeHandlers.set(Error, (_target, _source, options) => {
|
|
438
|
+
const target = _target;
|
|
439
|
+
const source = _source;
|
|
440
|
+
const sourceKeys = getSafeKeys(source);
|
|
441
|
+
for (const key of sourceKeys) {
|
|
442
|
+
if (target[key] === void 0) {
|
|
443
|
+
target[key] = source[key];
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
if (hasSameConstructor(target[key], source[key])) {
|
|
447
|
+
target[key] = merge(target[key], source[key], options);
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
target[key] = source[key];
|
|
451
|
+
}
|
|
452
|
+
return target;
|
|
453
|
+
});
|
|
454
|
+
const TYPED_ARRAYS = [
|
|
455
|
+
Int8Array,
|
|
456
|
+
Uint8Array,
|
|
457
|
+
Uint8ClampedArray,
|
|
458
|
+
Int16Array,
|
|
459
|
+
Uint16Array,
|
|
460
|
+
Int32Array,
|
|
461
|
+
Uint32Array,
|
|
462
|
+
Float32Array,
|
|
463
|
+
Float64Array,
|
|
464
|
+
BigInt64Array,
|
|
465
|
+
BigUint64Array
|
|
466
|
+
];
|
|
467
|
+
TYPED_ARRAYS.forEach((TypedArrayConstructor) => {
|
|
468
|
+
mergeHandlers.set(TypedArrayConstructor, (_target, source) => {
|
|
469
|
+
return new TypedArrayConstructor(source);
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
mergeHandlers.set(ArrayBuffer, (_target, source) => {
|
|
473
|
+
return source.slice(0);
|
|
474
|
+
});
|
|
475
|
+
mergeHandlers.set(DataView, (_target, source) => {
|
|
476
|
+
const sourceView = source;
|
|
477
|
+
const clonedBuffer = sourceView.buffer.slice(0);
|
|
478
|
+
return new DataView(clonedBuffer, sourceView.byteOffset, sourceView.byteLength);
|
|
479
|
+
});
|
|
480
|
+
const ERROR_TYPES = [
|
|
481
|
+
Error,
|
|
482
|
+
TypeError,
|
|
483
|
+
ReferenceError,
|
|
484
|
+
SyntaxError,
|
|
485
|
+
RangeError,
|
|
486
|
+
EvalError,
|
|
487
|
+
URIError
|
|
488
|
+
];
|
|
489
|
+
ERROR_TYPES.forEach((ErrorConstructor) => {
|
|
490
|
+
mergeHandlers.set(ErrorConstructor, (_target, source) => {
|
|
491
|
+
const sourceError = source;
|
|
492
|
+
const cloned = new sourceError.constructor(sourceError.message);
|
|
493
|
+
if (sourceError.name) {
|
|
494
|
+
cloned.name = sourceError.name;
|
|
495
|
+
}
|
|
496
|
+
if (sourceError.stack) {
|
|
497
|
+
cloned.stack = sourceError.stack;
|
|
498
|
+
}
|
|
499
|
+
const keys = Object.keys(sourceError);
|
|
500
|
+
for (const key of keys) {
|
|
501
|
+
if (key !== "name" && key !== "message" && key !== "stack" && !isDangerousKey(key)) {
|
|
502
|
+
cloned[key] = sourceError[key];
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return cloned;
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
};
|
|
509
|
+
var mergeHandlersInitialized = false;
|
|
510
|
+
var mergeDefaults = {
|
|
511
|
+
mergeArrays: true,
|
|
512
|
+
mergeSets: true
|
|
513
|
+
};
|
|
514
|
+
var merge = (target, source, options = {}) => {
|
|
515
|
+
if (!mergeHandlersInitialized) {
|
|
516
|
+
prepareMergeHandlers();
|
|
517
|
+
mergeHandlersInitialized = true;
|
|
518
|
+
}
|
|
519
|
+
options = {
|
|
520
|
+
...mergeDefaults,
|
|
521
|
+
...options
|
|
522
|
+
};
|
|
523
|
+
if (isPrimitive(source) || source instanceof Date) {
|
|
524
|
+
return source;
|
|
525
|
+
}
|
|
526
|
+
if (hasSameConstructor(source, target)) {
|
|
527
|
+
const actualConstructor = Object.getPrototypeOf(target)?.constructor || target.constructor;
|
|
528
|
+
const mergeType = mergeHandlers.get(actualConstructor);
|
|
529
|
+
if (!mergeType) {
|
|
530
|
+
return target;
|
|
531
|
+
}
|
|
532
|
+
return mergeType(target, source, options);
|
|
533
|
+
}
|
|
534
|
+
return source;
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// node_modules/@logosdx/utils/dist/esm/data-structures/priority-queue.mjs
|
|
538
|
+
var fifoCompare = (a, b) => {
|
|
539
|
+
if (a.priority === b.priority) {
|
|
540
|
+
return a.order - b.order;
|
|
541
|
+
}
|
|
542
|
+
return a.priority - b.priority;
|
|
543
|
+
};
|
|
544
|
+
var lifoCompare = (a, b) => {
|
|
545
|
+
if (a.priority === b.priority) {
|
|
546
|
+
return b.order - a.order;
|
|
547
|
+
}
|
|
548
|
+
return a.priority - b.priority;
|
|
549
|
+
};
|
|
550
|
+
var PriorityQueue = class _PriorityQueue {
|
|
551
|
+
#heap = [];
|
|
552
|
+
#insertionCounter = 0;
|
|
553
|
+
#compare;
|
|
554
|
+
#options;
|
|
555
|
+
constructor(options = {}) {
|
|
556
|
+
this.#compare = options.lifo ? lifoCompare : fifoCompare;
|
|
557
|
+
if (options.compare) {
|
|
558
|
+
this.#compare = options.compare;
|
|
559
|
+
}
|
|
560
|
+
if (options.maxHeap) {
|
|
561
|
+
const originalCompare = this.#compare;
|
|
562
|
+
this.#compare = (a, b) => -originalCompare(a, b);
|
|
563
|
+
}
|
|
564
|
+
this.#options = options;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Adds a new item into the queue.
|
|
568
|
+
* @param value The payload associated with the item
|
|
569
|
+
* @param priority Numeric priority (lower = higher priority)
|
|
570
|
+
*
|
|
571
|
+
* Time Complexity: O(log n)
|
|
572
|
+
* Space Complexity: O(1)
|
|
573
|
+
*/
|
|
574
|
+
push(value, priority = 0) {
|
|
575
|
+
const node = {
|
|
576
|
+
value,
|
|
577
|
+
priority,
|
|
578
|
+
order: this.#insertionCounter++
|
|
579
|
+
};
|
|
580
|
+
this.#heap.push(node);
|
|
581
|
+
this.#bubbleUp(this.#heap.length - 1);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Removes and returns the highest-priority item.
|
|
585
|
+
* Returns null if the queue is empty.
|
|
586
|
+
*
|
|
587
|
+
* Time Complexity: O(log n)
|
|
588
|
+
* Space Complexity: O(1)
|
|
589
|
+
*/
|
|
590
|
+
pop() {
|
|
591
|
+
if (this.#heap.length === 0) return null;
|
|
592
|
+
const top = this.#heap[0];
|
|
593
|
+
const last = this.#heap.pop();
|
|
594
|
+
if (this.#heap.length > 0) {
|
|
595
|
+
this.#heap[0] = last;
|
|
596
|
+
this.#bubbleDown(0);
|
|
597
|
+
}
|
|
598
|
+
return top.value;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Removes and returns many items from the queue.
|
|
602
|
+
* Returns an empty array if the queue is empty.
|
|
603
|
+
*/
|
|
604
|
+
popMany(count = 1) {
|
|
605
|
+
const items = [];
|
|
606
|
+
if (count === 0) {
|
|
607
|
+
return items;
|
|
608
|
+
}
|
|
609
|
+
if (count > this.#heap.length) {
|
|
610
|
+
count = this.#heap.length;
|
|
611
|
+
}
|
|
612
|
+
for (let i = count; i > 0; i--) {
|
|
613
|
+
items.push(this.pop());
|
|
614
|
+
}
|
|
615
|
+
return items;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Returns the next item to be dequeued without removing it.
|
|
619
|
+
*/
|
|
620
|
+
peek() {
|
|
621
|
+
return this.isEmpty() ? null : this.#heap[0].value;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Returns the next item to be dequeued without removing it.
|
|
625
|
+
*/
|
|
626
|
+
peekMany(count = 1) {
|
|
627
|
+
return this.#heap.slice(0, count).map((node) => node.value);
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Find an item in the queue by predicate.
|
|
631
|
+
*/
|
|
632
|
+
find(predicate) {
|
|
633
|
+
return this.#heap.find((node) => predicate(node.value))?.value ?? null;
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Heapify the queue.
|
|
637
|
+
*
|
|
638
|
+
* Time Complexity: O(n)
|
|
639
|
+
* Space Complexity: O(n)
|
|
640
|
+
*/
|
|
641
|
+
heapify(items) {
|
|
642
|
+
this.#heap = items.slice(0);
|
|
643
|
+
this.#insertionCounter = items.length;
|
|
644
|
+
for (let i = Math.floor(this.#heap.length / 2); i >= 0; i--) {
|
|
645
|
+
this.#bubbleDown(i);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
clone() {
|
|
649
|
+
const clone2 = new _PriorityQueue(this.#options);
|
|
650
|
+
clone2.heapify(this.#heap);
|
|
651
|
+
return clone2;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Returns a sorted array of the queue.
|
|
655
|
+
*/
|
|
656
|
+
toSortedArray() {
|
|
657
|
+
const clone2 = this.clone();
|
|
658
|
+
const sorted = [];
|
|
659
|
+
while (clone2.#heap.length > 0) {
|
|
660
|
+
sorted.push(clone2.pop());
|
|
661
|
+
}
|
|
662
|
+
return sorted;
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Returns an iterator over the queue.
|
|
666
|
+
*/
|
|
667
|
+
*[Symbol.iterator]() {
|
|
668
|
+
const clone2 = this.clone();
|
|
669
|
+
while (clone2.#heap.length > 0) {
|
|
670
|
+
yield clone2.pop();
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Returns the number of items in the queue.
|
|
675
|
+
*/
|
|
676
|
+
size() {
|
|
677
|
+
return this.#heap.length;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Returns true if the queue is empty.
|
|
681
|
+
*/
|
|
682
|
+
isEmpty() {
|
|
683
|
+
return this.#heap.length === 0;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Clears all items and resets the insertion counter.
|
|
687
|
+
*/
|
|
688
|
+
clear() {
|
|
689
|
+
this.#heap = [];
|
|
690
|
+
this.#insertionCounter = 0;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Moves the node at index up to restore heap invariant.
|
|
694
|
+
*
|
|
695
|
+
* Time Complexity: O(log n)
|
|
696
|
+
* Space Complexity: O(1)
|
|
697
|
+
*/
|
|
698
|
+
#bubbleUp(index) {
|
|
699
|
+
let idx = index;
|
|
700
|
+
while (idx > 0) {
|
|
701
|
+
const parentIdx = idx - 1 >> 1;
|
|
702
|
+
if (this.#compare(this.#heap[idx], this.#heap[parentIdx]) < 0) {
|
|
703
|
+
this.#swap(idx, parentIdx);
|
|
704
|
+
idx = parentIdx;
|
|
705
|
+
} else {
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Moves the node at index down to restore heap invariant.
|
|
712
|
+
*
|
|
713
|
+
* Time Complexity: O(log n)
|
|
714
|
+
* Space Complexity: O(1)
|
|
715
|
+
*/
|
|
716
|
+
#bubbleDown(index) {
|
|
717
|
+
const length = this.#heap.length;
|
|
718
|
+
let idx = index;
|
|
719
|
+
while (true) {
|
|
720
|
+
const left = (idx << 1) + 1;
|
|
721
|
+
const right = left + 1;
|
|
722
|
+
let smallest = idx;
|
|
723
|
+
if (left < length && this.#compare(this.#heap[left], this.#heap[smallest]) < 0) {
|
|
724
|
+
smallest = left;
|
|
725
|
+
}
|
|
726
|
+
if (right < length && this.#compare(this.#heap[right], this.#heap[smallest]) < 0) {
|
|
727
|
+
smallest = right;
|
|
728
|
+
}
|
|
729
|
+
if (smallest === idx) {
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
this.#swap(idx, smallest);
|
|
733
|
+
idx = smallest;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Swaps two nodes in the heap.
|
|
738
|
+
*/
|
|
739
|
+
#swap(i, j) {
|
|
740
|
+
[this.#heap[i], this.#heap[j]] = [
|
|
741
|
+
this.#heap[j],
|
|
742
|
+
this.#heap[i]
|
|
743
|
+
];
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
// node_modules/@logosdx/utils/dist/esm/flow-control/misc.mjs
|
|
748
|
+
var Deferred = class {
|
|
749
|
+
promise;
|
|
750
|
+
resolve;
|
|
751
|
+
reject;
|
|
752
|
+
constructor() {
|
|
753
|
+
this.promise = new Promise((resolve, reject) => {
|
|
754
|
+
this.resolve = resolve;
|
|
755
|
+
this.reject = reject;
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
if (typeof Promise.withResolvers !== "function") {
|
|
760
|
+
Promise.withResolvers = () => {
|
|
761
|
+
return new Deferred();
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
var TimeoutPromise = class extends Promise {
|
|
765
|
+
clear;
|
|
766
|
+
};
|
|
767
|
+
var wait = (ms, value = true) => {
|
|
768
|
+
let timeout;
|
|
769
|
+
const promise = new TimeoutPromise((resolve) => {
|
|
770
|
+
timeout = setTimeout(() => {
|
|
771
|
+
timeout = null;
|
|
772
|
+
resolve(value);
|
|
773
|
+
}, ms);
|
|
774
|
+
});
|
|
775
|
+
promise.clear = () => {
|
|
776
|
+
if (!timeout) return;
|
|
777
|
+
clearTimeout(timeout);
|
|
778
|
+
timeout = null;
|
|
779
|
+
};
|
|
780
|
+
return promise;
|
|
781
|
+
};
|
|
782
|
+
if (typeof setImmediate !== "function") {
|
|
783
|
+
let nextHandle = 0;
|
|
784
|
+
const tasks = /* @__PURE__ */ new Map();
|
|
785
|
+
const channel = new MessageChannel();
|
|
786
|
+
channel.port1.onmessage = async (event) => {
|
|
787
|
+
const handle = event.data;
|
|
788
|
+
const fn = tasks.get(handle);
|
|
789
|
+
if (!fn) return;
|
|
790
|
+
const [, error] = await attempt(fn);
|
|
791
|
+
if (error) console.error("Error in setImmediate", error);
|
|
792
|
+
};
|
|
793
|
+
globalThis.setImmediate = (fn, ...args) => {
|
|
794
|
+
const handle = nextHandle++;
|
|
795
|
+
tasks.set(handle, () => fn(...args));
|
|
796
|
+
channel.port2.postMessage(handle);
|
|
797
|
+
return handle;
|
|
798
|
+
};
|
|
799
|
+
globalThis.clearImmediate = (handle) => {
|
|
800
|
+
tasks.delete(handle);
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// node_modules/@logosdx/utils/dist/esm/_helpers.mjs
|
|
805
|
+
var maps = {
|
|
806
|
+
retry: /* @__PURE__ */ new WeakMap(),
|
|
807
|
+
circuitBreaker: /* @__PURE__ */ new WeakMap(),
|
|
808
|
+
rateLimit: /* @__PURE__ */ new WeakMap(),
|
|
809
|
+
throttle: /* @__PURE__ */ new WeakMap(),
|
|
810
|
+
debounce: /* @__PURE__ */ new WeakMap(),
|
|
811
|
+
memoize: /* @__PURE__ */ new WeakMap(),
|
|
812
|
+
withTimeout: /* @__PURE__ */ new WeakMap(),
|
|
813
|
+
inflight: /* @__PURE__ */ new WeakMap()
|
|
814
|
+
};
|
|
815
|
+
var assertNotWrapped = (fn, name) => {
|
|
816
|
+
if (maps[name].has(fn)) {
|
|
817
|
+
throw new Error(`Function is already wrapped with ${name}`);
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
// node_modules/@logosdx/utils/dist/esm/async/retry.mjs
|
|
822
|
+
var RetryError = class extends Error {
|
|
823
|
+
constructor(message) {
|
|
824
|
+
super(message);
|
|
825
|
+
this.name = "RetryError";
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
var validateOpts = (opts) => {
|
|
829
|
+
assert(isPlainObject(opts), "opts must be an object");
|
|
830
|
+
assertOptional(opts.retries, typeof opts.retries === "number" && opts.retries > 0, "retries must be a positive number");
|
|
831
|
+
assertOptional(opts.delay, typeof opts.delay === "number" && opts.delay >= 0, "delay must be a positive number");
|
|
832
|
+
assertOptional(opts.backoff, typeof opts.backoff === "number" && opts.backoff > 0, "backoff must be a positive number");
|
|
833
|
+
assertOptional(opts.shouldRetry, isFunction(opts.shouldRetry), "shouldRetry must be a function");
|
|
834
|
+
assertOptional(opts.signal, opts.signal instanceof AbortSignal, "signal must be an AbortSignal");
|
|
835
|
+
};
|
|
836
|
+
var retry = async (fn, opts) => {
|
|
837
|
+
assert(isFunction(fn), "fn must be a function");
|
|
838
|
+
assertNotWrapped(fn, "retry");
|
|
839
|
+
validateOpts(opts);
|
|
840
|
+
const { delay = 0, retries = 3, backoff = 1, jitterFactor = 0, shouldRetry = () => true, signal, throwLastError = false, onRetryExhausted, onRetry } = opts;
|
|
841
|
+
let attempts = 0;
|
|
842
|
+
let lastError = null;
|
|
843
|
+
while (attempts < retries) {
|
|
844
|
+
signal?.throwIfAborted();
|
|
845
|
+
if (attempts > 0 && onRetry && lastError) {
|
|
846
|
+
await onRetry(lastError, attempts);
|
|
847
|
+
}
|
|
848
|
+
const [result, error] = await attempt(fn);
|
|
849
|
+
signal?.throwIfAborted();
|
|
850
|
+
if (error === null) {
|
|
851
|
+
return result;
|
|
852
|
+
}
|
|
853
|
+
lastError = error;
|
|
854
|
+
if (error && shouldRetry(error)) {
|
|
855
|
+
await wait(delay * backoff * (1 + jitterFactor * Math.random()));
|
|
856
|
+
attempts++;
|
|
857
|
+
signal?.throwIfAborted();
|
|
858
|
+
continue;
|
|
859
|
+
}
|
|
860
|
+
throw error;
|
|
861
|
+
}
|
|
862
|
+
if (onRetryExhausted) {
|
|
863
|
+
return onRetryExhausted(lastError);
|
|
864
|
+
}
|
|
865
|
+
if (throwLastError) {
|
|
866
|
+
throw lastError;
|
|
867
|
+
}
|
|
868
|
+
throw new RetryError("Max retries reached");
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// node_modules/@logosdx/utils/dist/esm/misc/index.mjs
|
|
872
|
+
var noop = () => {
|
|
873
|
+
};
|
|
874
|
+
var generateId = () => "_" + Math.random().toString(36).slice(2, 9);
|
|
875
|
+
var unserializableIds = /* @__PURE__ */ new WeakMap();
|
|
876
|
+
var getUnserializableId = (value) => {
|
|
877
|
+
if (!unserializableIds.has(value)) {
|
|
878
|
+
unserializableIds.set(value, generateId());
|
|
879
|
+
}
|
|
880
|
+
return unserializableIds.get(value);
|
|
881
|
+
};
|
|
882
|
+
var serializer = (args) => {
|
|
883
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
884
|
+
const stringify = (value) => {
|
|
885
|
+
if (value === null) return "null";
|
|
886
|
+
if (value === void 0) return "undefined";
|
|
887
|
+
if (typeof value === "string") return `${value}`;
|
|
888
|
+
if (typeof value === "number") {
|
|
889
|
+
if (Object.is(value, -0)) return "-0";
|
|
890
|
+
return String(value);
|
|
891
|
+
}
|
|
892
|
+
if (typeof value === "boolean") return String(value);
|
|
893
|
+
if (typeof value === "bigint") return `bi:${value}`;
|
|
894
|
+
if (typeof value === "symbol") return `sym:${getUnserializableId(value)}`;
|
|
895
|
+
if (typeof value === "function") return `fn:${getUnserializableId(value)}`;
|
|
896
|
+
if (value instanceof Date) return `d:${value.getTime()}`;
|
|
897
|
+
if (value instanceof RegExp) return `r:${value.toString()}`;
|
|
898
|
+
if (value instanceof Error) return `e:${getUnserializableId(value)}`;
|
|
899
|
+
if (value instanceof WeakMap) return `wm:${getUnserializableId(value)}`;
|
|
900
|
+
if (value instanceof WeakSet) return `ws:${getUnserializableId(value)}`;
|
|
901
|
+
if (typeof value === "object") {
|
|
902
|
+
if (seen.has(value)) return `circ:${getUnserializableId(value)}`;
|
|
903
|
+
seen.add(value);
|
|
904
|
+
if (value instanceof Map) {
|
|
905
|
+
const pairs2 = Array.from(value.entries()).map(([k, v]) => `${stringify(k)}:${stringify(v)}`).sort();
|
|
906
|
+
const result2 = `map:${pairs2.join(",")}`;
|
|
907
|
+
seen.delete(value);
|
|
908
|
+
return result2;
|
|
909
|
+
}
|
|
910
|
+
if (value instanceof Set) {
|
|
911
|
+
const values = Array.from(value).map(stringify).sort();
|
|
912
|
+
const result2 = `set:${values.join(",")}`;
|
|
913
|
+
seen.delete(value);
|
|
914
|
+
return result2;
|
|
915
|
+
}
|
|
916
|
+
if (Array.isArray(value)) {
|
|
917
|
+
const result2 = `[${value.map(stringify).join(",")}]`;
|
|
918
|
+
seen.delete(value);
|
|
919
|
+
return result2;
|
|
920
|
+
}
|
|
921
|
+
const keys = Object.keys(value).sort();
|
|
922
|
+
const pairs = keys.map((key2) => `"${key2}":${stringify(value[key2])}`);
|
|
923
|
+
const result = `{${pairs.join(",")}}`;
|
|
924
|
+
seen.delete(value);
|
|
925
|
+
return result;
|
|
926
|
+
}
|
|
927
|
+
return `u:${String(value)}`;
|
|
928
|
+
};
|
|
929
|
+
const key = args.map(stringify).join("|");
|
|
930
|
+
return key || "0";
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
// node_modules/@logosdx/utils/dist/esm/flow-control/memo/helpers.mjs
|
|
934
|
+
var unwrapValue = (value) => {
|
|
935
|
+
if (value instanceof WeakRef) {
|
|
936
|
+
const deref = value.deref();
|
|
937
|
+
return [
|
|
938
|
+
deref,
|
|
939
|
+
deref === void 0
|
|
940
|
+
];
|
|
941
|
+
}
|
|
942
|
+
return [
|
|
943
|
+
value,
|
|
944
|
+
false
|
|
945
|
+
];
|
|
946
|
+
};
|
|
947
|
+
var createCacheItem = (value, createdAt, expiresAt, useWeakRef, accessSequence) => {
|
|
948
|
+
const storedValue = useWeakRef && isObject(value) && value !== null ? new WeakRef(value) : value;
|
|
949
|
+
return {
|
|
950
|
+
value: storedValue,
|
|
951
|
+
createdAt,
|
|
952
|
+
expiresAt,
|
|
953
|
+
accessCount: 1,
|
|
954
|
+
lastAccessed: createdAt,
|
|
955
|
+
accessSequence
|
|
956
|
+
};
|
|
957
|
+
};
|
|
958
|
+
var isExpired = (item) => {
|
|
959
|
+
return Date.now() >= item.expiresAt;
|
|
960
|
+
};
|
|
961
|
+
var updateAccessMetadata = (item, sequence) => {
|
|
962
|
+
const now = Date.now();
|
|
963
|
+
item.lastAccessed = now;
|
|
964
|
+
item.accessCount = (item.accessCount ?? 0) + 1;
|
|
965
|
+
item.accessSequence = sequence;
|
|
966
|
+
};
|
|
967
|
+
var evictLRU = (cache) => {
|
|
968
|
+
let lruKey = null;
|
|
969
|
+
let lruTime = Infinity;
|
|
970
|
+
let lruSequence = Infinity;
|
|
971
|
+
for (const [key, item] of cache.entries()) {
|
|
972
|
+
const itemLastAccessed = item.lastAccessed ?? 0;
|
|
973
|
+
const itemAccessSequence = item.accessSequence ?? 0;
|
|
974
|
+
const isLessRecent = itemLastAccessed < lruTime || itemLastAccessed === lruTime && itemAccessSequence < lruSequence;
|
|
975
|
+
if (isLessRecent) {
|
|
976
|
+
lruTime = itemLastAccessed;
|
|
977
|
+
lruSequence = itemAccessSequence;
|
|
978
|
+
lruKey = key;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (lruKey) {
|
|
982
|
+
cache.delete(lruKey);
|
|
983
|
+
}
|
|
984
|
+
return lruKey;
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
// node_modules/@logosdx/utils/dist/esm/flow-control/memo/memoizeSync.mjs
|
|
988
|
+
var memoizedFunctions = /* @__PURE__ */ new WeakSet();
|
|
989
|
+
var memoizeSync = (fn, opts = {}) => {
|
|
990
|
+
assert(isFunction(fn), "fn must be a function");
|
|
991
|
+
assert(!memoizedFunctions.has(fn), "Function is already wrapped by memoize");
|
|
992
|
+
const { ttl = 6e4, maxSize = 1e3, generateKey, onError, cleanupInterval = 6e4, useWeakRef = false, shouldCache } = opts;
|
|
993
|
+
const { staleIn, staleTimeout, adapter } = opts;
|
|
994
|
+
assert(ttl > 0, "ttl must be greater than 0");
|
|
995
|
+
assert(maxSize > 0, "maxSize must be greater than 0");
|
|
996
|
+
assert(isOptional(cleanupInterval, (val) => typeof val === "number" && val >= 0), "cleanupInterval must be >= 0");
|
|
997
|
+
assertOptional(generateKey, isFunction(generateKey), "generateKey must be a function");
|
|
998
|
+
assertOptional(onError, isFunction(onError), "onError must be a function");
|
|
999
|
+
assert(adapter === void 0, "memoizeSync does not support custom cache adapters (use memoize for async adapters like Redis)");
|
|
1000
|
+
assert(staleTimeout === void 0, "memoizeSync does not support staleTimeout (sync functions execute instantly)");
|
|
1001
|
+
assert(staleIn === void 0, "memoizeSync does not support staleIn (sync functions execute instantly, use ttl instead)");
|
|
1002
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1003
|
+
let accessSequence = 0;
|
|
1004
|
+
let hits = 0;
|
|
1005
|
+
let misses = 0;
|
|
1006
|
+
let evictions = 0;
|
|
1007
|
+
let cleanupTimer;
|
|
1008
|
+
const getNextSequence = () => {
|
|
1009
|
+
if (accessSequence >= Number.MAX_SAFE_INTEGER - 1) {
|
|
1010
|
+
accessSequence = 0;
|
|
1011
|
+
}
|
|
1012
|
+
return ++accessSequence;
|
|
1013
|
+
};
|
|
1014
|
+
const recordHit = () => hits++;
|
|
1015
|
+
const recordMiss = () => misses++;
|
|
1016
|
+
const cleanupExpired = () => {
|
|
1017
|
+
const now = Date.now();
|
|
1018
|
+
for (const [key, item] of cache.entries()) {
|
|
1019
|
+
if (now >= item.expiresAt) {
|
|
1020
|
+
cache.delete(key);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
if (cleanupInterval > 0) {
|
|
1025
|
+
cleanupTimer = setInterval(() => cleanupExpired(), cleanupInterval);
|
|
1026
|
+
if (typeof cleanupTimer.unref === "function") {
|
|
1027
|
+
cleanupTimer.unref();
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
const memoized = function(...args) {
|
|
1031
|
+
if (shouldCache) {
|
|
1032
|
+
const [shouldCacheResult, shouldCacheError] = attemptSync(() => shouldCache(...args));
|
|
1033
|
+
if (!shouldCacheError && !shouldCacheResult) {
|
|
1034
|
+
return fn(...args);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
const [key, keyError] = attemptSync(() => generateKey ? generateKey(...args) : serializer(args));
|
|
1038
|
+
if (keyError) {
|
|
1039
|
+
onError?.(keyError, args);
|
|
1040
|
+
recordMiss();
|
|
1041
|
+
return fn(...args);
|
|
1042
|
+
}
|
|
1043
|
+
const cached = cache.get(key);
|
|
1044
|
+
if (cached && !isExpired(cached)) {
|
|
1045
|
+
updateAccessMetadata(cached, getNextSequence());
|
|
1046
|
+
const [unwrapped, wasGC] = unwrapValue(cached.value);
|
|
1047
|
+
if (wasGC) {
|
|
1048
|
+
cache.delete(key);
|
|
1049
|
+
recordMiss();
|
|
1050
|
+
const [value2, error2] = attemptSync(() => fn(...args));
|
|
1051
|
+
if (error2) {
|
|
1052
|
+
onError?.(error2, args);
|
|
1053
|
+
throw error2;
|
|
1054
|
+
}
|
|
1055
|
+
const now2 = Date.now();
|
|
1056
|
+
const item2 = createCacheItem(value2, now2, now2 + ttl, useWeakRef, getNextSequence());
|
|
1057
|
+
if (cache.size >= maxSize) {
|
|
1058
|
+
evictLRU(cache);
|
|
1059
|
+
evictions++;
|
|
1060
|
+
}
|
|
1061
|
+
cache.set(key, item2);
|
|
1062
|
+
return value2;
|
|
1063
|
+
}
|
|
1064
|
+
recordHit();
|
|
1065
|
+
return unwrapped;
|
|
1066
|
+
}
|
|
1067
|
+
recordMiss();
|
|
1068
|
+
const [value, error] = attemptSync(() => fn(...args));
|
|
1069
|
+
if (error) {
|
|
1070
|
+
onError?.(error, args);
|
|
1071
|
+
throw error;
|
|
1072
|
+
}
|
|
1073
|
+
const now = Date.now();
|
|
1074
|
+
const item = createCacheItem(value, now, now + ttl, useWeakRef, getNextSequence());
|
|
1075
|
+
if (cache.size >= maxSize) {
|
|
1076
|
+
evictLRU(cache);
|
|
1077
|
+
evictions++;
|
|
1078
|
+
}
|
|
1079
|
+
cache.set(key, item);
|
|
1080
|
+
return value;
|
|
1081
|
+
};
|
|
1082
|
+
memoized.cache = {
|
|
1083
|
+
clear: () => {
|
|
1084
|
+
cache.clear();
|
|
1085
|
+
hits = 0;
|
|
1086
|
+
misses = 0;
|
|
1087
|
+
evictions = 0;
|
|
1088
|
+
accessSequence = 0;
|
|
1089
|
+
if (cleanupTimer !== void 0) {
|
|
1090
|
+
clearInterval(cleanupTimer);
|
|
1091
|
+
cleanupTimer = void 0;
|
|
1092
|
+
}
|
|
1093
|
+
},
|
|
1094
|
+
delete: (key) => {
|
|
1095
|
+
return cache.delete(key);
|
|
1096
|
+
},
|
|
1097
|
+
has: (key) => {
|
|
1098
|
+
const item = cache.get(key);
|
|
1099
|
+
if (!item) {
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
if (isExpired(item)) {
|
|
1103
|
+
cache.delete(key);
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
return true;
|
|
1107
|
+
},
|
|
1108
|
+
get size() {
|
|
1109
|
+
return cache.size;
|
|
1110
|
+
},
|
|
1111
|
+
stats: () => {
|
|
1112
|
+
return {
|
|
1113
|
+
hits,
|
|
1114
|
+
misses,
|
|
1115
|
+
evictions,
|
|
1116
|
+
hitRate: hits + misses > 0 ? hits / (hits + misses) : 0,
|
|
1117
|
+
size: cache.size
|
|
1118
|
+
};
|
|
1119
|
+
},
|
|
1120
|
+
keys: () => {
|
|
1121
|
+
return cache.keys();
|
|
1122
|
+
},
|
|
1123
|
+
entries: () => {
|
|
1124
|
+
const results = [];
|
|
1125
|
+
for (const [key, item] of cache.entries()) {
|
|
1126
|
+
if (!isExpired(item)) {
|
|
1127
|
+
const [unwrapped] = unwrapValue(item.value);
|
|
1128
|
+
results.push([
|
|
1129
|
+
key,
|
|
1130
|
+
unwrapped
|
|
1131
|
+
]);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return results;
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
memoizedFunctions.add(memoized);
|
|
1138
|
+
return memoized;
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1141
|
+
// node_modules/@logosdx/utils/dist/esm/flow-control/rate-limit.mjs
|
|
1142
|
+
var RateLimitTokenBucket = class {
|
|
1143
|
+
#tokens;
|
|
1144
|
+
#lastRefill;
|
|
1145
|
+
#stats;
|
|
1146
|
+
#save;
|
|
1147
|
+
#load;
|
|
1148
|
+
capacity;
|
|
1149
|
+
refillIntervalMs;
|
|
1150
|
+
constructor(config) {
|
|
1151
|
+
assert(isPlainObject(config), "config must be an object");
|
|
1152
|
+
assert(typeof config.capacity === "number" && config.capacity > 0, "capacity must be a positive number");
|
|
1153
|
+
assert(typeof config.refillIntervalMs === "number" && config.refillIntervalMs > 0, "refillIntervalMs must be a positive number");
|
|
1154
|
+
assertOptional(config.save, isFunction(config.save), "save must be a function");
|
|
1155
|
+
assertOptional(config.load, isFunction(config.load), "load must be a function");
|
|
1156
|
+
assertOptional(config.initialState, isPlainObject(config.initialState), "initialState must be an object");
|
|
1157
|
+
this.capacity = config.capacity;
|
|
1158
|
+
this.refillIntervalMs = config.refillIntervalMs;
|
|
1159
|
+
this.#save = config.save;
|
|
1160
|
+
this.#load = config.load;
|
|
1161
|
+
if (config.initialState) {
|
|
1162
|
+
this.#tokens = config.initialState.tokens ?? config.capacity;
|
|
1163
|
+
this.#lastRefill = config.initialState.lastRefill ?? Date.now();
|
|
1164
|
+
this.#stats = {
|
|
1165
|
+
totalRequests: config.initialState.stats?.totalRequests ?? 0,
|
|
1166
|
+
rejectedRequests: config.initialState.stats?.rejectedRequests ?? 0,
|
|
1167
|
+
totalWaitTime: config.initialState.stats?.totalWaitTime ?? 0,
|
|
1168
|
+
waitCount: config.initialState.stats?.waitCount ?? 0,
|
|
1169
|
+
createdAt: config.initialState.stats?.createdAt ?? Date.now()
|
|
1170
|
+
};
|
|
1171
|
+
} else {
|
|
1172
|
+
this.#tokens = config.capacity;
|
|
1173
|
+
this.#lastRefill = Date.now();
|
|
1174
|
+
this.#stats = {
|
|
1175
|
+
totalRequests: 0,
|
|
1176
|
+
rejectedRequests: 0,
|
|
1177
|
+
totalWaitTime: 0,
|
|
1178
|
+
waitCount: 0,
|
|
1179
|
+
createdAt: Date.now()
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Whether save and load functions are configured for persistence.
|
|
1185
|
+
*/
|
|
1186
|
+
get isSaveable() {
|
|
1187
|
+
return isFunction(this.#save) && isFunction(this.#load);
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Get the current state for persistence.
|
|
1191
|
+
* This is the minimal data structure needed to restore the bucket.
|
|
1192
|
+
*/
|
|
1193
|
+
get state() {
|
|
1194
|
+
this.#refill();
|
|
1195
|
+
return {
|
|
1196
|
+
tokens: this.#tokens,
|
|
1197
|
+
lastRefill: this.#lastRefill,
|
|
1198
|
+
stats: {
|
|
1199
|
+
...this.#stats
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Save the current state using the configured save function.
|
|
1205
|
+
* @throws If no save function is configured
|
|
1206
|
+
*/
|
|
1207
|
+
async save() {
|
|
1208
|
+
const saveFn = this.#save;
|
|
1209
|
+
if (!isFunction(saveFn)) {
|
|
1210
|
+
throw new Error("No save function configured");
|
|
1211
|
+
}
|
|
1212
|
+
await saveFn(this.state);
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Load state from the configured load function.
|
|
1216
|
+
* If the load function returns undefined/null, the bucket state is not modified.
|
|
1217
|
+
* @throws If no load function is configured
|
|
1218
|
+
*/
|
|
1219
|
+
async load() {
|
|
1220
|
+
const loadFn = this.#load;
|
|
1221
|
+
if (!isFunction(loadFn)) {
|
|
1222
|
+
throw new Error("No load function configured");
|
|
1223
|
+
}
|
|
1224
|
+
const loadedState = await loadFn();
|
|
1225
|
+
if (loadedState) {
|
|
1226
|
+
this.#tokens = loadedState.tokens ?? this.capacity;
|
|
1227
|
+
this.#lastRefill = loadedState.lastRefill ?? Date.now();
|
|
1228
|
+
if (loadedState.stats) {
|
|
1229
|
+
this.#stats = {
|
|
1230
|
+
totalRequests: loadedState.stats.totalRequests ?? 0,
|
|
1231
|
+
rejectedRequests: loadedState.stats.rejectedRequests ?? 0,
|
|
1232
|
+
totalWaitTime: loadedState.stats.totalWaitTime ?? 0,
|
|
1233
|
+
waitCount: loadedState.stats.waitCount ?? 0,
|
|
1234
|
+
createdAt: loadedState.stats.createdAt ?? Date.now()
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Check if there are enough tokens available without consuming them.
|
|
1241
|
+
*
|
|
1242
|
+
* @param count - Number of tokens to check for (default: 1)
|
|
1243
|
+
* @returns true if tokens are available, false otherwise
|
|
1244
|
+
*
|
|
1245
|
+
* @example
|
|
1246
|
+
* if (bucket.hasTokens()) {
|
|
1247
|
+
* // We're within rate limit, proceed
|
|
1248
|
+
* bucket.consume();
|
|
1249
|
+
* }
|
|
1250
|
+
*/
|
|
1251
|
+
hasTokens(count = 1) {
|
|
1252
|
+
this.#refill();
|
|
1253
|
+
return this.#tokens >= count;
|
|
1254
|
+
}
|
|
1255
|
+
#refill() {
|
|
1256
|
+
const now = Date.now();
|
|
1257
|
+
const elapsed = now - this.#lastRefill;
|
|
1258
|
+
const refillRate = 1 / this.refillIntervalMs;
|
|
1259
|
+
if (elapsed < 0 || elapsed > this.refillIntervalMs * this.capacity * 2) {
|
|
1260
|
+
this.#lastRefill = now;
|
|
1261
|
+
this.#tokens = this.capacity;
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
if (elapsed > 0) {
|
|
1265
|
+
const tokensToAdd = elapsed * refillRate;
|
|
1266
|
+
this.#tokens = Math.min(this.capacity, this.#tokens + tokensToAdd);
|
|
1267
|
+
this.#lastRefill = now;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
reset() {
|
|
1271
|
+
this.#tokens = this.capacity;
|
|
1272
|
+
this.#lastRefill = Date.now();
|
|
1273
|
+
}
|
|
1274
|
+
get tokens() {
|
|
1275
|
+
return Math.floor(this.#tokens);
|
|
1276
|
+
}
|
|
1277
|
+
consume(count = 1) {
|
|
1278
|
+
this.#refill();
|
|
1279
|
+
this.#stats.totalRequests++;
|
|
1280
|
+
if (this.#tokens >= count) {
|
|
1281
|
+
this.#tokens -= count;
|
|
1282
|
+
return true;
|
|
1283
|
+
}
|
|
1284
|
+
this.#stats.rejectedRequests++;
|
|
1285
|
+
return false;
|
|
1286
|
+
}
|
|
1287
|
+
getWaitTimeMs(count = 1) {
|
|
1288
|
+
this.#refill();
|
|
1289
|
+
const deficit = count - this.#tokens;
|
|
1290
|
+
if (deficit <= 0) return 0;
|
|
1291
|
+
const refillRate = 1 / this.refillIntervalMs;
|
|
1292
|
+
const waitTime = Math.ceil(deficit / refillRate) + 1;
|
|
1293
|
+
return waitTime;
|
|
1294
|
+
}
|
|
1295
|
+
getNextAvailable(count = 1) {
|
|
1296
|
+
return new Date(Date.now() + this.getWaitTimeMs(count));
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Get a snapshot of current statistics and state.
|
|
1300
|
+
*
|
|
1301
|
+
* @returns Object containing usage statistics and current state
|
|
1302
|
+
*/
|
|
1303
|
+
get snapshot() {
|
|
1304
|
+
this.#refill();
|
|
1305
|
+
const now = Date.now();
|
|
1306
|
+
const uptime = now - this.#stats.createdAt;
|
|
1307
|
+
return {
|
|
1308
|
+
currentTokens: this.tokens,
|
|
1309
|
+
capacity: this.capacity,
|
|
1310
|
+
refillIntervalMs: this.refillIntervalMs,
|
|
1311
|
+
totalRequests: this.#stats.totalRequests,
|
|
1312
|
+
rejectedRequests: this.#stats.rejectedRequests,
|
|
1313
|
+
successfulRequests: this.#stats.totalRequests - this.#stats.rejectedRequests,
|
|
1314
|
+
rejectionRate: this.#stats.totalRequests > 0 ? this.#stats.rejectedRequests / this.#stats.totalRequests : 0,
|
|
1315
|
+
totalWaitTime: this.#stats.totalWaitTime,
|
|
1316
|
+
waitCount: this.#stats.waitCount,
|
|
1317
|
+
averageWaitTime: this.#stats.waitCount > 0 ? this.#stats.totalWaitTime / this.#stats.waitCount : 0,
|
|
1318
|
+
uptime,
|
|
1319
|
+
createdAt: this.#stats.createdAt
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Waits for the next token to be available before
|
|
1324
|
+
* allowing the caller to proceed.
|
|
1325
|
+
*
|
|
1326
|
+
* @param onRateLimit - Callback to invoke when the rate limit is exceeded
|
|
1327
|
+
*
|
|
1328
|
+
* @example
|
|
1329
|
+
* const bucket = new RateLimitTokenBucket({
|
|
1330
|
+
* capacity: 10,
|
|
1331
|
+
* refillIntervalMs: 1000
|
|
1332
|
+
* });
|
|
1333
|
+
*
|
|
1334
|
+
* await bucket.waitForToken(() => {
|
|
1335
|
+
* console.log('Rate limit exceeded');
|
|
1336
|
+
* });
|
|
1337
|
+
* console.log('Token available');
|
|
1338
|
+
*
|
|
1339
|
+
* bucket.consume();
|
|
1340
|
+
* console.log('Token consumed');
|
|
1341
|
+
*/
|
|
1342
|
+
async waitForToken(count = 1, opts = {}) {
|
|
1343
|
+
const { onRateLimit, abortController, jitterFactor = 0 } = opts;
|
|
1344
|
+
this.#refill();
|
|
1345
|
+
if (this.#tokens >= count) return;
|
|
1346
|
+
const waitStart = Date.now();
|
|
1347
|
+
this.#stats.waitCount++;
|
|
1348
|
+
while (this.#tokens < count) {
|
|
1349
|
+
if (abortController?.signal?.aborted) return;
|
|
1350
|
+
await onRateLimit?.(new RateLimitError("Rate limit exceeded", this.capacity), this.getNextAvailable(count));
|
|
1351
|
+
await wait(this.getWaitTimeMs(count) + Math.random() * jitterFactor);
|
|
1352
|
+
this.#refill();
|
|
1353
|
+
}
|
|
1354
|
+
const waitEnd = Date.now();
|
|
1355
|
+
this.#stats.totalWaitTime += waitEnd - waitStart;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Waits for tokens to be available and consumes them atomically.
|
|
1359
|
+
*
|
|
1360
|
+
* @param onRateLimit - Callback to invoke when the rate limit is exceeded
|
|
1361
|
+
*
|
|
1362
|
+
* @example
|
|
1363
|
+
* const bucket = new RateLimitTokenBucket({
|
|
1364
|
+
* capacity: 10,
|
|
1365
|
+
* refillIntervalMs: 1000
|
|
1366
|
+
* });
|
|
1367
|
+
*
|
|
1368
|
+
* await bucket.waitAndConsume(() => {
|
|
1369
|
+
* console.log('Rate limit exceeded');
|
|
1370
|
+
* });
|
|
1371
|
+
* console.log('Token acquired and consumed');
|
|
1372
|
+
*/
|
|
1373
|
+
async waitAndConsume(count = 1, opts = {}) {
|
|
1374
|
+
const { onRateLimit, abortController, jitterFactor = 0 } = opts;
|
|
1375
|
+
this.#refill();
|
|
1376
|
+
this.#stats.totalRequests++;
|
|
1377
|
+
if (this.#tokens >= count) {
|
|
1378
|
+
this.#tokens -= count;
|
|
1379
|
+
return true;
|
|
1380
|
+
}
|
|
1381
|
+
const waitStart = Date.now();
|
|
1382
|
+
this.#stats.waitCount++;
|
|
1383
|
+
while (this.#tokens < count) {
|
|
1384
|
+
if (abortController?.signal?.aborted) {
|
|
1385
|
+
this.#stats.rejectedRequests++;
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
await onRateLimit?.(new RateLimitError("Rate limit exceeded", this.capacity), this.getNextAvailable(count));
|
|
1389
|
+
await wait(this.getWaitTimeMs(count) + Math.random() * jitterFactor);
|
|
1390
|
+
this.#refill();
|
|
1391
|
+
}
|
|
1392
|
+
this.#tokens -= count;
|
|
1393
|
+
const waitEnd = Date.now();
|
|
1394
|
+
this.#stats.totalWaitTime += waitEnd - waitStart;
|
|
1395
|
+
return true;
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
var RateLimitError = class extends Error {
|
|
1399
|
+
maxCalls;
|
|
1400
|
+
constructor(message, maxCalls) {
|
|
1401
|
+
super(message);
|
|
1402
|
+
this.name = "RateLimitError";
|
|
1403
|
+
this.maxCalls = maxCalls;
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
|
|
1407
|
+
// node_modules/@logosdx/utils/dist/esm/flow-control/with-timeout.mjs
|
|
1408
|
+
var TimeoutError = class extends Error {
|
|
1409
|
+
constructor(message) {
|
|
1410
|
+
super(message);
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
var isTimeoutError = (error) => {
|
|
1414
|
+
return error?.constructor?.name === TimeoutError.name;
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
// node_modules/@logosdx/utils/dist/esm/units/time.mjs
|
|
1418
|
+
var timeUnits = {
|
|
1419
|
+
sec: 1e3,
|
|
1420
|
+
min: 60 * 1e3,
|
|
1421
|
+
min15: 15 * 60 * 1e3,
|
|
1422
|
+
min30: 30 * 60 * 1e3,
|
|
1423
|
+
hour: 60 * 60 * 1e3,
|
|
1424
|
+
hour2: 2 * 60 * 60 * 1e3,
|
|
1425
|
+
hour4: 4 * 60 * 60 * 1e3,
|
|
1426
|
+
hour8: 8 * 60 * 60 * 1e3,
|
|
1427
|
+
hour12: 12 * 60 * 60 * 1e3,
|
|
1428
|
+
day: 24 * 60 * 60 * 1e3,
|
|
1429
|
+
week: 7 * 24 * 60 * 60 * 1e3,
|
|
1430
|
+
secs(n) {
|
|
1431
|
+
return n * this.sec;
|
|
1432
|
+
},
|
|
1433
|
+
mins(n) {
|
|
1434
|
+
return n * this.min;
|
|
1435
|
+
},
|
|
1436
|
+
hours(n) {
|
|
1437
|
+
return n * this.hour;
|
|
1438
|
+
},
|
|
1439
|
+
days(n) {
|
|
1440
|
+
return n * this.day;
|
|
1441
|
+
},
|
|
1442
|
+
weeks(n) {
|
|
1443
|
+
return n * this.week;
|
|
1444
|
+
},
|
|
1445
|
+
months(n) {
|
|
1446
|
+
return Math.round(n * 30.4 * this.day);
|
|
1447
|
+
},
|
|
1448
|
+
years(n) {
|
|
1449
|
+
return n * 365 * this.day;
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
var seconds = (n) => timeUnits.secs(n);
|
|
1453
|
+
var minutes = (n) => timeUnits.mins(n);
|
|
1454
|
+
var hours = (n) => timeUnits.hours(n);
|
|
1455
|
+
var days = (n) => timeUnits.days(n);
|
|
1456
|
+
var weeks = (n) => timeUnits.weeks(n);
|
|
1457
|
+
var months = (n) => timeUnits.months(n);
|
|
1458
|
+
var years = (n) => timeUnits.years(n);
|
|
1459
|
+
var parseTimeDuration = (str) => {
|
|
1460
|
+
const match = str.match(/^(\d+(?:\.\d+)?)\s*(s|sec|secs?|seconds?|m|min|mins?|minutes?|h|hr|hrs?|hour|hours?|d|day|days?|w|wk|wks?|week|weeks?|mo|mon|mons?|month|months?|y|yr|yrs?|year|years?)$/i);
|
|
1461
|
+
if (!match) {
|
|
1462
|
+
throw new Error(`Invalid time duration: ${str}`);
|
|
1463
|
+
}
|
|
1464
|
+
const [, num, unit] = match;
|
|
1465
|
+
const n = parseFloat(num);
|
|
1466
|
+
const unitLower = unit.toLowerCase();
|
|
1467
|
+
if (unitLower.startsWith("s")) return seconds(n);
|
|
1468
|
+
if (unitLower.startsWith("m") && !unitLower.startsWith("mo")) return minutes(n);
|
|
1469
|
+
if (unitLower.startsWith("h")) return hours(n);
|
|
1470
|
+
if (unitLower.startsWith("d")) return days(n);
|
|
1471
|
+
if (unitLower.startsWith("w")) return weeks(n);
|
|
1472
|
+
if (unitLower.startsWith("mo")) return months(n);
|
|
1473
|
+
if (unitLower.startsWith("y")) return years(n);
|
|
1474
|
+
throw new Error(`Unknown unit: ${unit}`);
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
// node_modules/@logosdx/utils/dist/esm/units/bytes.mjs
|
|
1478
|
+
var byteUnits = {
|
|
1479
|
+
kb: 1024,
|
|
1480
|
+
mb: 1024 ** 2,
|
|
1481
|
+
gb: 1024 ** 3,
|
|
1482
|
+
tb: 1024 ** 4,
|
|
1483
|
+
kbs(n) {
|
|
1484
|
+
return n * this.kb;
|
|
1485
|
+
},
|
|
1486
|
+
mbs(n) {
|
|
1487
|
+
return n * this.mb;
|
|
1488
|
+
},
|
|
1489
|
+
gbs(n) {
|
|
1490
|
+
return n * this.gb;
|
|
1491
|
+
},
|
|
1492
|
+
tbs(n) {
|
|
1493
|
+
return n * this.tb;
|
|
1494
|
+
}
|
|
1495
|
+
};
|
|
1496
|
+
var kilobytes = (n) => byteUnits.kbs(n);
|
|
1497
|
+
var megabytes = (n) => byteUnits.mbs(n);
|
|
1498
|
+
var gigabytes = (n) => byteUnits.gbs(n);
|
|
1499
|
+
var terabytes = (n) => byteUnits.tbs(n);
|
|
1500
|
+
var parseByteSize = (str) => {
|
|
1501
|
+
const match = str.match(/^(\d+(?:\.\d+)?)\s*(kb|kbs?|kilobytes?|mb|mbs?|megabytes?|gb|gbs?|gigabytes?|tb|tbs?|terabytes?)$/i);
|
|
1502
|
+
if (!match) {
|
|
1503
|
+
throw new Error(`Invalid byte size: ${str}`);
|
|
1504
|
+
}
|
|
1505
|
+
const [, num, unit] = match;
|
|
1506
|
+
const n = parseFloat(num);
|
|
1507
|
+
const unitLower = unit.toLowerCase();
|
|
1508
|
+
if (unitLower.startsWith("k")) return kilobytes(n);
|
|
1509
|
+
if (unitLower.startsWith("m")) return megabytes(n);
|
|
1510
|
+
if (unitLower.startsWith("g")) return gigabytes(n);
|
|
1511
|
+
if (unitLower.startsWith("t")) return terabytes(n);
|
|
1512
|
+
throw new Error(`Unknown unit: ${unit}`);
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
// node_modules/@logosdx/utils/dist/esm/config/index.mjs
|
|
1516
|
+
var onlyNumRegex = /^\d+$/;
|
|
1517
|
+
var castValuesToTypes = (obj, opts = {}) => {
|
|
1518
|
+
const { parseUnits = false, skipConversion } = opts;
|
|
1519
|
+
for (const key in obj) {
|
|
1520
|
+
const k = key;
|
|
1521
|
+
const val = obj[k];
|
|
1522
|
+
if (skipConversion?.(key, val)) {
|
|
1523
|
+
continue;
|
|
1524
|
+
}
|
|
1525
|
+
const isObject2 = typeof val === "object" && val !== null;
|
|
1526
|
+
if (isObject2) {
|
|
1527
|
+
castValuesToTypes(val, opts);
|
|
1528
|
+
continue;
|
|
1529
|
+
}
|
|
1530
|
+
if (parseUnits && typeof val === "string") {
|
|
1531
|
+
const [timeDuration, timeErr] = attemptSync(() => parseTimeDuration(val));
|
|
1532
|
+
if (!timeErr && typeof timeDuration === "number") {
|
|
1533
|
+
obj[k] = timeDuration;
|
|
1534
|
+
continue;
|
|
1535
|
+
}
|
|
1536
|
+
const [byteSize, bytesErr] = attemptSync(() => parseByteSize(val));
|
|
1537
|
+
if (!bytesErr && typeof byteSize === "number") {
|
|
1538
|
+
obj[k] = byteSize;
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
const truthy = isEnabledValue(obj[k]);
|
|
1543
|
+
const falsy = isDisabledValue(obj[k]);
|
|
1544
|
+
if (truthy || falsy) {
|
|
1545
|
+
obj[k] = truthy;
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
if (typeof val === "string" && onlyNumRegex.test(val)) {
|
|
1549
|
+
obj[k] = Number(val);
|
|
1550
|
+
continue;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
var makeNestedConfig = (_flatConfig, opts = {}) => {
|
|
1555
|
+
assert(typeof _flatConfig === "object" && _flatConfig !== null, "flatConfig must be a non-null object");
|
|
1556
|
+
assert(typeof opts === "object" && opts !== null, "opts must be a non-null object");
|
|
1557
|
+
assert(opts.filter === void 0 || typeof opts.filter === "function", "filter must be a function");
|
|
1558
|
+
assert(opts.forceAllCapToLower === void 0 || typeof opts.forceAllCapToLower === "boolean", "forceAllCapToLower must be a boolean");
|
|
1559
|
+
assert(opts.separator === void 0 || typeof opts.separator === "string", "separator must be a string");
|
|
1560
|
+
assert(opts.stripPrefix === void 0 || typeof opts.stripPrefix === "string" || typeof opts.stripPrefix === "number", "stripPrefix must be a string or number");
|
|
1561
|
+
assert(opts.parseUnits === void 0 || typeof opts.parseUnits === "boolean", "parseUnits must be a boolean");
|
|
1562
|
+
assert(opts.skipConversion === void 0 || typeof opts.skipConversion === "function", "skipConversion must be a function");
|
|
1563
|
+
assert(opts.memoizeOpts === void 0 || typeof opts.memoizeOpts === "object" || opts.memoizeOpts === false, "memoizeOpts must be an object or false");
|
|
1564
|
+
const { filter, forceAllCapToLower = true, separator = "_", stripPrefix, parseUnits = false, skipConversion, memoizeOpts = false } = opts;
|
|
1565
|
+
const isAllCaps = (str) => /^[A-Z0-9_]+$/.test(str);
|
|
1566
|
+
const handleCasing = (str) => {
|
|
1567
|
+
let processedStr = str;
|
|
1568
|
+
if (stripPrefix !== void 0) {
|
|
1569
|
+
if (typeof stripPrefix === "number") {
|
|
1570
|
+
processedStr = str.slice(stripPrefix);
|
|
1571
|
+
} else {
|
|
1572
|
+
processedStr = str.startsWith(stripPrefix) ? str.slice(stripPrefix.length) : str;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
const split = processedStr.split(separator);
|
|
1576
|
+
return split.map((s) => {
|
|
1577
|
+
if (isAllCaps(s) && forceAllCapToLower) return s.toLowerCase();
|
|
1578
|
+
return s;
|
|
1579
|
+
}).join(".");
|
|
1580
|
+
};
|
|
1581
|
+
function allConfigs() {
|
|
1582
|
+
const flatConfig = clone(_flatConfig);
|
|
1583
|
+
const config = {};
|
|
1584
|
+
const keys = Object.entries(flatConfig).filter(([key, val]) => filter?.(key, val) ?? true).map(([key]) => key).sort();
|
|
1585
|
+
const [, err] = attemptSync(() => {
|
|
1586
|
+
setDeepMany(config, keys.map((k) => [
|
|
1587
|
+
handleCasing(k),
|
|
1588
|
+
flatConfig[k]
|
|
1589
|
+
]));
|
|
1590
|
+
castValuesToTypes(config, {
|
|
1591
|
+
parseUnits,
|
|
1592
|
+
skipConversion
|
|
1593
|
+
});
|
|
1594
|
+
});
|
|
1595
|
+
if (err instanceof Error && err.message.includes("on primitive value")) {
|
|
1596
|
+
const key = (k) => k.split("_").join(separator);
|
|
1597
|
+
const eq = (k, v) => `${key(k)}=${v}`;
|
|
1598
|
+
const message = [
|
|
1599
|
+
"Failed to load flatmap variables.",
|
|
1600
|
+
"You're likely trying to set a nested property on a non-object value.",
|
|
1601
|
+
`For example, if you have ${eq("APP_DB_NAME", "foo")}, and then you try to set`,
|
|
1602
|
+
`${eq("APP_DB_NAME_TEST", "bar")}, you'll get this error because ${key("APP_DB_NAME")} is a string.`,
|
|
1603
|
+
"The correct way is to designate each namespace (separated by underscores) as ",
|
|
1604
|
+
`an object. For example, ${eq("APP_DB_NAME", "foo")} becomes { db: { name: "foo" } }, and,`,
|
|
1605
|
+
`${eq("APP_DB_NAME_TEST", "bar")} becomes { db: { name: { test: "bar" } } }, but both cannot coexist.`,
|
|
1606
|
+
`
|
|
1607
|
+
|
|
1608
|
+
You can either \`unset ${key("APP_PROBLEMATIC")}\` or scope all vars to \`${key("APP_NAMESPACE_NAME")}\` to`,
|
|
1609
|
+
"make it a nested object.",
|
|
1610
|
+
"\n\n"
|
|
1611
|
+
];
|
|
1612
|
+
console.error(message.join(" "));
|
|
1613
|
+
}
|
|
1614
|
+
if (err) throw err;
|
|
1615
|
+
return config;
|
|
1616
|
+
}
|
|
1617
|
+
function getConfig(path, defaultValue) {
|
|
1618
|
+
const config = allConfigs();
|
|
1619
|
+
const value = reach(config, path);
|
|
1620
|
+
if (value === void 0 || value === null) {
|
|
1621
|
+
return defaultValue;
|
|
1622
|
+
}
|
|
1623
|
+
return value;
|
|
1624
|
+
}
|
|
1625
|
+
if (!memoizeOpts) return {
|
|
1626
|
+
allConfigs,
|
|
1627
|
+
getConfig
|
|
1628
|
+
};
|
|
1629
|
+
return {
|
|
1630
|
+
allConfigs: memoizeSync(allConfigs, memoizeOpts),
|
|
1631
|
+
getConfig: memoizeSync(getConfig, memoizeOpts)
|
|
1632
|
+
};
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
// node_modules/@logosdx/observer/dist/esm/helpers.mjs
|
|
1636
|
+
var EventTrace = class extends Error {
|
|
1637
|
+
listener;
|
|
1638
|
+
data;
|
|
1639
|
+
func;
|
|
1640
|
+
event;
|
|
1641
|
+
stack;
|
|
1642
|
+
};
|
|
1643
|
+
var traceStackFilterRgx = new RegExp(`(${[
|
|
1644
|
+
"node_modules",
|
|
1645
|
+
"node:internal",
|
|
1646
|
+
"$spy",
|
|
1647
|
+
"makeEventTracer",
|
|
1648
|
+
"sendToSpy",
|
|
1649
|
+
"Function.spy",
|
|
1650
|
+
"Observable.Engine"
|
|
1651
|
+
].join("|")})`);
|
|
1652
|
+
var EventError = class extends Error {
|
|
1653
|
+
event;
|
|
1654
|
+
listener;
|
|
1655
|
+
data;
|
|
1656
|
+
constructor(message, opts) {
|
|
1657
|
+
super(message);
|
|
1658
|
+
this.event = opts?.event;
|
|
1659
|
+
this.listener = opts?.listener;
|
|
1660
|
+
this.data = opts?.data;
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1663
|
+
var makeEventTracer = (event, caller, listenerOrData) => {
|
|
1664
|
+
const err = new Error();
|
|
1665
|
+
const split = err.stack.split("\n");
|
|
1666
|
+
split.shift();
|
|
1667
|
+
const filtered = split.filter((line) => !traceStackFilterRgx.test(line));
|
|
1668
|
+
const message = `EventStack (${event} ${caller.toString()}):`;
|
|
1669
|
+
filtered.unshift(message);
|
|
1670
|
+
const stack = filtered.join("\n");
|
|
1671
|
+
const tracer = new EventTrace(message);
|
|
1672
|
+
tracer.name = message;
|
|
1673
|
+
tracer.func = caller;
|
|
1674
|
+
tracer.event = event;
|
|
1675
|
+
tracer.stack = stack;
|
|
1676
|
+
tracer.listener = null;
|
|
1677
|
+
tracer.data = null;
|
|
1678
|
+
if (typeof listenerOrData === "function") {
|
|
1679
|
+
tracer.listener = listenerOrData;
|
|
1680
|
+
} else {
|
|
1681
|
+
tracer.data = listenerOrData;
|
|
1682
|
+
}
|
|
1683
|
+
return tracer;
|
|
1684
|
+
};
|
|
1685
|
+
var rgxStrToRgx = (rgxStr) => {
|
|
1686
|
+
const split = rgxStr?.replace(/^\//, "").split("/");
|
|
1687
|
+
const flags = split.pop();
|
|
1688
|
+
const expr = split.join("/");
|
|
1689
|
+
return RegExp(expr, flags);
|
|
1690
|
+
};
|
|
1691
|
+
var arrOfMatchingValues = (vals, map) => {
|
|
1692
|
+
const listeners = [];
|
|
1693
|
+
for (const key of vals) {
|
|
1694
|
+
for (const fn of map.get(key) || /* @__PURE__ */ new Set()) {
|
|
1695
|
+
listeners.push({
|
|
1696
|
+
event: key,
|
|
1697
|
+
func: fn
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
return listeners;
|
|
1702
|
+
};
|
|
1703
|
+
var InternalEvs = /* @__PURE__ */ (function(InternalEvs2) {
|
|
1704
|
+
InternalEvs2["on"] = "on";
|
|
1705
|
+
InternalEvs2["off"] = "off";
|
|
1706
|
+
InternalEvs2["emit"] = "emit";
|
|
1707
|
+
InternalEvs2["clear"] = "clear";
|
|
1708
|
+
return InternalEvs2;
|
|
1709
|
+
})({});
|
|
1710
|
+
var InternalEvent = class extends Event {
|
|
1711
|
+
type;
|
|
1712
|
+
data;
|
|
1713
|
+
constructor(ev, data) {
|
|
1714
|
+
super(ev);
|
|
1715
|
+
this.data = data;
|
|
1716
|
+
this.type = ev;
|
|
1717
|
+
}
|
|
1718
|
+
};
|
|
1719
|
+
var validateEvent = (fn, opts) => {
|
|
1720
|
+
if (opts.event === void 0 || typeof opts.event !== "string" && opts.event instanceof RegExp === false) {
|
|
1721
|
+
throw new EventError(`observer.${fn}: Event must be a string or RegExp`, opts);
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
var validateListener = (fn, opts) => {
|
|
1725
|
+
if (opts.listener !== void 0 && typeof opts.listener !== "function") {
|
|
1726
|
+
throw new EventError(`observer.${fn}: Listener must be a function`, opts);
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
|
|
1730
|
+
// node_modules/@logosdx/observer/dist/esm/generator.mjs
|
|
1731
|
+
var DeferredEvent = class extends Deferred {
|
|
1732
|
+
cleanup;
|
|
1733
|
+
};
|
|
1734
|
+
var EventGenerator = class {
|
|
1735
|
+
#observer;
|
|
1736
|
+
#event;
|
|
1737
|
+
#buffer;
|
|
1738
|
+
#waiting = null;
|
|
1739
|
+
#done = false;
|
|
1740
|
+
#listener = null;
|
|
1741
|
+
#lastValue = null;
|
|
1742
|
+
#assertNotDestroyed = () => {
|
|
1743
|
+
if (this.#done === true) {
|
|
1744
|
+
throw new EventError(`Event generator for ${this.#event.toString()} has been destroyed`, {
|
|
1745
|
+
event: this.#event,
|
|
1746
|
+
listener: this.#listener,
|
|
1747
|
+
data: null
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
};
|
|
1751
|
+
cleanup;
|
|
1752
|
+
next;
|
|
1753
|
+
constructor(observer2, event, options) {
|
|
1754
|
+
this.#observer = observer2;
|
|
1755
|
+
this.#event = event;
|
|
1756
|
+
this.#buffer = new PriorityQueue();
|
|
1757
|
+
this.#listener = (data) => {
|
|
1758
|
+
this.#lastValue = data;
|
|
1759
|
+
if (this.#waiting) {
|
|
1760
|
+
const defer = this.#waiting;
|
|
1761
|
+
this.#waiting = null;
|
|
1762
|
+
defer.resolve(data);
|
|
1763
|
+
} else {
|
|
1764
|
+
this.#buffer.push(data);
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
const off = observer2.on(event, this.#listener);
|
|
1768
|
+
let generatorAbortCtrl;
|
|
1769
|
+
this.next = () => {
|
|
1770
|
+
this.#assertNotDestroyed();
|
|
1771
|
+
const buffered = this.#buffer.pop();
|
|
1772
|
+
if (buffered !== null) {
|
|
1773
|
+
return Promise.resolve(buffered);
|
|
1774
|
+
}
|
|
1775
|
+
if (!this.#waiting) {
|
|
1776
|
+
this.#waiting = new DeferredEvent();
|
|
1777
|
+
this.#waiting.promise.cleanup = this.cleanup;
|
|
1778
|
+
this.#waiting.promise.resolve = this.#waiting.resolve;
|
|
1779
|
+
this.#waiting.promise.reject = this.#waiting.reject;
|
|
1780
|
+
}
|
|
1781
|
+
return this.#waiting.promise;
|
|
1782
|
+
};
|
|
1783
|
+
this.cleanup = () => {
|
|
1784
|
+
if (this.#done) return;
|
|
1785
|
+
off();
|
|
1786
|
+
this.#done = true;
|
|
1787
|
+
const abortError = new EventError("Aborted", {
|
|
1788
|
+
event: this.#event,
|
|
1789
|
+
listener: this.#listener,
|
|
1790
|
+
data: null
|
|
1791
|
+
});
|
|
1792
|
+
if (this.#waiting) {
|
|
1793
|
+
this.#waiting.reject(abortError);
|
|
1794
|
+
this.#waiting = null;
|
|
1795
|
+
}
|
|
1796
|
+
this.#_iterPromise.forEach((promise) => {
|
|
1797
|
+
promise.reject?.(abortError);
|
|
1798
|
+
});
|
|
1799
|
+
this.#_iterPromise.clear();
|
|
1800
|
+
this.#buffer.clear();
|
|
1801
|
+
this.#lastValue = null;
|
|
1802
|
+
generatorAbortCtrl?.abort();
|
|
1803
|
+
};
|
|
1804
|
+
const userSignal = options?.signal;
|
|
1805
|
+
if (userSignal) {
|
|
1806
|
+
if (userSignal.aborted) {
|
|
1807
|
+
this.#done = true;
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
generatorAbortCtrl = new AbortController();
|
|
1811
|
+
userSignal.addEventListener("abort", this.cleanup, {
|
|
1812
|
+
signal: generatorAbortCtrl.signal
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
/**
|
|
1817
|
+
* Store iterator's last promise. Handles multiple promises
|
|
1818
|
+
* for when the generator is used in multiple places.
|
|
1819
|
+
*/
|
|
1820
|
+
#_iterPromise = /* @__PURE__ */ new Set();
|
|
1821
|
+
async *[Symbol.asyncIterator]() {
|
|
1822
|
+
while (!this.#done) {
|
|
1823
|
+
const promise = this.next();
|
|
1824
|
+
this.#_iterPromise.add(promise);
|
|
1825
|
+
yield await promise;
|
|
1826
|
+
this.#_iterPromise.delete(promise);
|
|
1827
|
+
}
|
|
1828
|
+
return Promise.resolve(void 0);
|
|
1829
|
+
}
|
|
1830
|
+
get lastValue() {
|
|
1831
|
+
return this.#lastValue;
|
|
1832
|
+
}
|
|
1833
|
+
get done() {
|
|
1834
|
+
return this.#done;
|
|
1835
|
+
}
|
|
1836
|
+
emit(data) {
|
|
1837
|
+
this.#assertNotDestroyed();
|
|
1838
|
+
this.#observer.emit(this.#event, data);
|
|
1839
|
+
}
|
|
1840
|
+
};
|
|
1841
|
+
|
|
1842
|
+
// node_modules/@logosdx/observer/dist/esm/queue/state.mjs
|
|
1843
|
+
var QueueStateManager = class {
|
|
1844
|
+
status = "stopped";
|
|
1845
|
+
#allowedTransitions = {
|
|
1846
|
+
["running"]: [
|
|
1847
|
+
"paused",
|
|
1848
|
+
"draining",
|
|
1849
|
+
"stopped"
|
|
1850
|
+
],
|
|
1851
|
+
["draining"]: [
|
|
1852
|
+
"stopped",
|
|
1853
|
+
"paused"
|
|
1854
|
+
],
|
|
1855
|
+
["paused"]: [
|
|
1856
|
+
"running",
|
|
1857
|
+
"draining",
|
|
1858
|
+
"stopped"
|
|
1859
|
+
],
|
|
1860
|
+
["stopped"]: [
|
|
1861
|
+
"running",
|
|
1862
|
+
"draining"
|
|
1863
|
+
]
|
|
1864
|
+
};
|
|
1865
|
+
transition(to) {
|
|
1866
|
+
assert(this.#allowedTransitions[this.status].includes(to), `Invalid transition from ${this.status} to ${to}`);
|
|
1867
|
+
this.status = to;
|
|
1868
|
+
}
|
|
1869
|
+
is(...states) {
|
|
1870
|
+
return states.includes(this.status);
|
|
1871
|
+
}
|
|
1872
|
+
get state() {
|
|
1873
|
+
return this.status;
|
|
1874
|
+
}
|
|
1875
|
+
};
|
|
1876
|
+
|
|
1877
|
+
// node_modules/@logosdx/observer/dist/esm/queue/statistics.mjs
|
|
1878
|
+
var QueueStats = class {
|
|
1879
|
+
observer;
|
|
1880
|
+
queueName;
|
|
1881
|
+
#processing;
|
|
1882
|
+
#processed;
|
|
1883
|
+
#avgProcessingTime;
|
|
1884
|
+
#success;
|
|
1885
|
+
#error;
|
|
1886
|
+
#rejected;
|
|
1887
|
+
constructor(observer2, queueName) {
|
|
1888
|
+
this.observer = observer2;
|
|
1889
|
+
this.queueName = queueName;
|
|
1890
|
+
this.#processing = 0;
|
|
1891
|
+
this.#processed = 0;
|
|
1892
|
+
this.#avgProcessingTime = 0;
|
|
1893
|
+
this.#success = 0;
|
|
1894
|
+
this.#error = 0;
|
|
1895
|
+
this.#rejected = 0;
|
|
1896
|
+
this.observer.on(`queue:${this.queueName}:processing`, () => {
|
|
1897
|
+
this.#processing++;
|
|
1898
|
+
});
|
|
1899
|
+
this.observer.on(`queue:${this.queueName}:success`, (wrapped) => {
|
|
1900
|
+
this.#processed++;
|
|
1901
|
+
this.#success++;
|
|
1902
|
+
this.#processing--;
|
|
1903
|
+
this.#calculateAvg(wrapped.data.elapsed);
|
|
1904
|
+
});
|
|
1905
|
+
this.observer.on(`queue:${this.queueName}:error`, () => {
|
|
1906
|
+
this.#processed++;
|
|
1907
|
+
this.#error++;
|
|
1908
|
+
this.#processing--;
|
|
1909
|
+
});
|
|
1910
|
+
this.observer.on(`queue:${this.queueName}:rejected`, () => this.#rejected++);
|
|
1911
|
+
}
|
|
1912
|
+
#calculateAvg(elapsed) {
|
|
1913
|
+
this.#avgProcessingTime = (this.#avgProcessingTime * (this.#success - 1) + elapsed) / this.#success;
|
|
1914
|
+
}
|
|
1915
|
+
get stats() {
|
|
1916
|
+
return {
|
|
1917
|
+
processed: this.#processed,
|
|
1918
|
+
processing: this.#processing,
|
|
1919
|
+
avgProcessingTime: this.#avgProcessingTime,
|
|
1920
|
+
success: this.#success,
|
|
1921
|
+
error: this.#error,
|
|
1922
|
+
rejected: this.#rejected
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
|
|
1927
|
+
// node_modules/@logosdx/observer/dist/esm/queue/helpers.mjs
|
|
1928
|
+
var InternalQueueEvent = class {
|
|
1929
|
+
data;
|
|
1930
|
+
constructor(data) {
|
|
1931
|
+
this.data = data;
|
|
1932
|
+
}
|
|
1933
|
+
};
|
|
1934
|
+
var QueueRejectionReason = /* @__PURE__ */ (function(QueueRejectionReason2) {
|
|
1935
|
+
QueueRejectionReason2["full"] = "Queue is full";
|
|
1936
|
+
QueueRejectionReason2["notRunning"] = "Queue is not running";
|
|
1937
|
+
return QueueRejectionReason2;
|
|
1938
|
+
})({});
|
|
1939
|
+
|
|
1940
|
+
// node_modules/@logosdx/observer/dist/esm/queue/queue.mjs
|
|
1941
|
+
var EventQueue = class {
|
|
1942
|
+
opts;
|
|
1943
|
+
#queue;
|
|
1944
|
+
#priorites;
|
|
1945
|
+
#off;
|
|
1946
|
+
#state;
|
|
1947
|
+
#stats;
|
|
1948
|
+
#rateLimiter;
|
|
1949
|
+
#idle;
|
|
1950
|
+
#waiting;
|
|
1951
|
+
#listening;
|
|
1952
|
+
#debugging;
|
|
1953
|
+
#generation;
|
|
1954
|
+
#activeRunners;
|
|
1955
|
+
#runningNodes;
|
|
1956
|
+
constructor(opts) {
|
|
1957
|
+
this.opts = opts;
|
|
1958
|
+
this.#priorites = /* @__PURE__ */ new Map();
|
|
1959
|
+
this.#off = noop;
|
|
1960
|
+
this.#state = new QueueStateManager();
|
|
1961
|
+
this.#idle = true;
|
|
1962
|
+
this.#waiting = false;
|
|
1963
|
+
this.#listening = false;
|
|
1964
|
+
this.#debugging = false;
|
|
1965
|
+
this.#generation = 0;
|
|
1966
|
+
this.#activeRunners = 0;
|
|
1967
|
+
this.#runningNodes = /* @__PURE__ */ new Set();
|
|
1968
|
+
const { observer: observer2 = new ObserverEngine(), event, process: process2, name, type = "fifo", concurrency = 1, pollIntervalMs = 100, jitterFactor = 0, rateLimitIntervalMs = 1e3, processIntervalMs = 0, taskTimeoutMs = 0, autoStart = true, debug = false } = this.opts;
|
|
1969
|
+
let { maxQueueSize = 999999999, rateLimitCapacity = 999999999 } = this.opts;
|
|
1970
|
+
assert(isPlainObject(this.opts), "Options is required to be an object");
|
|
1971
|
+
assert(isFunction(observer2?.on), "ObserverEngine is required");
|
|
1972
|
+
assert(typeof event === "string" && event.length > 0 || event instanceof RegExp, "Event is required to be a string or RegExp");
|
|
1973
|
+
assert(isFunction(process2), "Process is required to be a function");
|
|
1974
|
+
assert(name && typeof name === "string" && name.length > 0, "Name is required");
|
|
1975
|
+
assert(concurrency > 0, "Concurrency must be greater than 0");
|
|
1976
|
+
assert(pollIntervalMs > 0, "pollIntervalMs must be a number greater than 0");
|
|
1977
|
+
assert(jitterFactor >= 0 && jitterFactor <= 1, "Jitter must be a number greater than or equal to 0 and less than or equal to 1");
|
|
1978
|
+
assert(maxQueueSize > 0, "MaxQueueSize must be a number greater than 0");
|
|
1979
|
+
assert(rateLimitIntervalMs > 0, "rateLimitIntervalMs must be a number greater than 0");
|
|
1980
|
+
assert(rateLimitCapacity > 0, "rateLimitCapacity must be a number greater than 0");
|
|
1981
|
+
assert(processIntervalMs >= 0, "processIntervalMs must be a number greater than or equal to 0");
|
|
1982
|
+
assert(taskTimeoutMs >= 0, "taskTimeoutMs must be a number greater than or equal to 0");
|
|
1983
|
+
assert(type === "fifo" || type === "lifo", 'Type must be either "fifo" or "lifo"');
|
|
1984
|
+
assert(typeof autoStart === "boolean", "AutoStart must be a boolean");
|
|
1985
|
+
if (maxQueueSize === Infinity) {
|
|
1986
|
+
maxQueueSize = 999999999;
|
|
1987
|
+
}
|
|
1988
|
+
if (rateLimitCapacity === Infinity) {
|
|
1989
|
+
rateLimitCapacity = 999999999;
|
|
1990
|
+
}
|
|
1991
|
+
Object.assign(this.opts, {
|
|
1992
|
+
observer: observer2,
|
|
1993
|
+
type,
|
|
1994
|
+
concurrency,
|
|
1995
|
+
maxQueueSize,
|
|
1996
|
+
pollIntervalMs,
|
|
1997
|
+
jitterFactor,
|
|
1998
|
+
processIntervalMs,
|
|
1999
|
+
taskTimeoutMs
|
|
2000
|
+
});
|
|
2001
|
+
this.#debugging = debug;
|
|
2002
|
+
this.#stats = new QueueStats(observer2, name);
|
|
2003
|
+
this.#rateLimiter = new RateLimitTokenBucket({
|
|
2004
|
+
capacity: rateLimitCapacity,
|
|
2005
|
+
refillIntervalMs: rateLimitIntervalMs
|
|
2006
|
+
});
|
|
2007
|
+
this.#queue = new PriorityQueue({
|
|
2008
|
+
lifo: type === "lifo"
|
|
2009
|
+
});
|
|
2010
|
+
if (autoStart) {
|
|
2011
|
+
this.start();
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
#listen() {
|
|
2015
|
+
if (this.#listening) return;
|
|
2016
|
+
this.#listening = true;
|
|
2017
|
+
const off = this.opts.observer.on(this.opts.event, (payload) => {
|
|
2018
|
+
const maybeInternal = payload?.data ?? payload;
|
|
2019
|
+
if (maybeInternal instanceof InternalQueueEvent) {
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
const data = payload;
|
|
2023
|
+
const item = {
|
|
2024
|
+
data,
|
|
2025
|
+
_taskId: generateId(),
|
|
2026
|
+
priority: this.#priorites.get(data) ?? 0
|
|
2027
|
+
};
|
|
2028
|
+
this.#priorites.delete(data);
|
|
2029
|
+
if (this.#queue.size() >= this.opts.maxQueueSize) {
|
|
2030
|
+
this.#emit("rejected", {
|
|
2031
|
+
...item,
|
|
2032
|
+
reason: QueueRejectionReason.full
|
|
2033
|
+
});
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
this.#emit("added", item);
|
|
2037
|
+
this.#idle = false;
|
|
2038
|
+
this.#queue.push(item, item.priority);
|
|
2039
|
+
});
|
|
2040
|
+
this.#off = () => {
|
|
2041
|
+
off();
|
|
2042
|
+
this.#listening = false;
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
#emit(event, payload) {
|
|
2046
|
+
if (this.#debugging) {
|
|
2047
|
+
const args = [
|
|
2048
|
+
`[${this.name}] ${event}`,
|
|
2049
|
+
payload?._taskId ?? "",
|
|
2050
|
+
payload?.data ?? ""
|
|
2051
|
+
];
|
|
2052
|
+
if (this.#debugging === "verbose") {
|
|
2053
|
+
args[1] = payload;
|
|
2054
|
+
}
|
|
2055
|
+
console.log(...args);
|
|
2056
|
+
}
|
|
2057
|
+
this.opts.observer.emit(`queue:${this.name}:${event}`, new InternalQueueEvent(payload));
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Setups concurrency and begins processing items
|
|
2061
|
+
*/
|
|
2062
|
+
#launchRunners() {
|
|
2063
|
+
const generation = ++this.#generation;
|
|
2064
|
+
for (let i = 0; i < this.opts.concurrency; i++) {
|
|
2065
|
+
this.#workerLoop(generation, i);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* Loops and processes items in the queue until the queue is stopped
|
|
2070
|
+
*/
|
|
2071
|
+
async #workerLoop(generation, instance) {
|
|
2072
|
+
const { pollIntervalMs, jitterFactor } = this.opts;
|
|
2073
|
+
this.#activeRunners++;
|
|
2074
|
+
while (this.#state.is("running") && this.#generation === generation) {
|
|
2075
|
+
if (!this.pending) {
|
|
2076
|
+
if (!this.#idle && !this.pending && this.#runningNodes.size === 0) {
|
|
2077
|
+
this.#idle = true;
|
|
2078
|
+
this.#emit("idle");
|
|
2079
|
+
}
|
|
2080
|
+
this.#waiting = true;
|
|
2081
|
+
await wait(pollIntervalMs * (1 + Math.random() * jitterFactor));
|
|
2082
|
+
this.#waiting = false;
|
|
2083
|
+
continue;
|
|
2084
|
+
}
|
|
2085
|
+
const data = this.#queue.pop();
|
|
2086
|
+
if (!data) continue;
|
|
2087
|
+
this.#runningNodes.add(`${generation}-${instance}`);
|
|
2088
|
+
await this.#processNext(data);
|
|
2089
|
+
if (this.opts.processIntervalMs > 0) {
|
|
2090
|
+
await wait(this.opts.processIntervalMs);
|
|
2091
|
+
}
|
|
2092
|
+
this.#runningNodes.delete(`${generation}-${instance}`);
|
|
2093
|
+
}
|
|
2094
|
+
this.#activeRunners--;
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* Processes the next item in the queue, if the queue is not
|
|
2098
|
+
* in a state that prevents it from processing the item.
|
|
2099
|
+
*/
|
|
2100
|
+
async #processNext(item) {
|
|
2101
|
+
if (!this.#state.is("running", "draining")) {
|
|
2102
|
+
this.#queue.push(item);
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
let rateLimited = false;
|
|
2106
|
+
if (!this.#state.is("draining")) {
|
|
2107
|
+
await this.#rateLimiter.waitAndConsume(1, {
|
|
2108
|
+
onRateLimit: () => {
|
|
2109
|
+
this.#emit("rate-limited", item);
|
|
2110
|
+
rateLimited = true;
|
|
2111
|
+
}
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
const startedAt = Date.now();
|
|
2115
|
+
this.#emit("processing", {
|
|
2116
|
+
...item,
|
|
2117
|
+
startedAt,
|
|
2118
|
+
rateLimited
|
|
2119
|
+
});
|
|
2120
|
+
const [, err] = await attempt(async () => {
|
|
2121
|
+
if (this.opts.taskTimeoutMs === 0) {
|
|
2122
|
+
return this.opts.process(item.data);
|
|
2123
|
+
}
|
|
2124
|
+
const result = await Promise.race([
|
|
2125
|
+
this.opts.process(item.data),
|
|
2126
|
+
wait(this.opts.taskTimeoutMs, new TimeoutError("Task timed out"))
|
|
2127
|
+
]);
|
|
2128
|
+
if (isTimeoutError(result)) {
|
|
2129
|
+
this.#emit("timeout", {
|
|
2130
|
+
...item,
|
|
2131
|
+
error: result
|
|
2132
|
+
});
|
|
2133
|
+
throw result;
|
|
2134
|
+
}
|
|
2135
|
+
return result;
|
|
2136
|
+
});
|
|
2137
|
+
const elapsed = Date.now() - startedAt;
|
|
2138
|
+
if (err) {
|
|
2139
|
+
this.#emit("error", {
|
|
2140
|
+
...item,
|
|
2141
|
+
error: err,
|
|
2142
|
+
rateLimited
|
|
2143
|
+
});
|
|
2144
|
+
} else {
|
|
2145
|
+
this.#emit("success", {
|
|
2146
|
+
...item,
|
|
2147
|
+
startedAt,
|
|
2148
|
+
elapsed,
|
|
2149
|
+
rateLimited
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2152
|
+
if (this.#queue.size() === 0 && this.#state.is("running")) {
|
|
2153
|
+
this.#emit("empty");
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
/**
|
|
2157
|
+
* Start the queue if it is not already started
|
|
2158
|
+
*/
|
|
2159
|
+
start() {
|
|
2160
|
+
if (this.#state.is("running")) return;
|
|
2161
|
+
this.#listen();
|
|
2162
|
+
this.#state.transition("running");
|
|
2163
|
+
this.#emit("start");
|
|
2164
|
+
this.#launchRunners();
|
|
2165
|
+
this.#emit("started");
|
|
2166
|
+
return Promise.resolve();
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Stop the queue
|
|
2170
|
+
*/
|
|
2171
|
+
stop() {
|
|
2172
|
+
if (this.#state.is("stopped")) return;
|
|
2173
|
+
this.#off();
|
|
2174
|
+
this.#state.transition("stopped");
|
|
2175
|
+
this.#emit("stopped");
|
|
2176
|
+
}
|
|
2177
|
+
/**
|
|
2178
|
+
* Pause the queue
|
|
2179
|
+
*/
|
|
2180
|
+
pause() {
|
|
2181
|
+
if (this.#state.is("paused")) return;
|
|
2182
|
+
this.#state.transition("paused");
|
|
2183
|
+
this.#emit("paused");
|
|
2184
|
+
return Promise.resolve();
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Resume the queue
|
|
2188
|
+
*/
|
|
2189
|
+
resume() {
|
|
2190
|
+
if (this.#state.is("running")) return;
|
|
2191
|
+
this.#listen();
|
|
2192
|
+
this.#state.transition("running");
|
|
2193
|
+
this.#launchRunners();
|
|
2194
|
+
this.#emit("resumed");
|
|
2195
|
+
return Promise.resolve();
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Processes a batch of items from the queue, and then
|
|
2199
|
+
* calls the before and after functions. Returns the
|
|
2200
|
+
* number of items processed.
|
|
2201
|
+
*/
|
|
2202
|
+
async #processBatch(limit = Infinity, beforeFn, afterFn) {
|
|
2203
|
+
let count = limit === Infinity ? this.#queue.size() : limit;
|
|
2204
|
+
const items = this.#queue.popMany(count);
|
|
2205
|
+
if (count < items.length) {
|
|
2206
|
+
count = items.length;
|
|
2207
|
+
}
|
|
2208
|
+
beforeFn?.(count);
|
|
2209
|
+
if (count !== 0) {
|
|
2210
|
+
for (const item of items) {
|
|
2211
|
+
await this.#processNext(item);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
afterFn?.(count);
|
|
2215
|
+
return count;
|
|
2216
|
+
}
|
|
2217
|
+
/**
|
|
2218
|
+
* Empty and process all items in the queue and
|
|
2219
|
+
* then stop the queue. Returns the number of items
|
|
2220
|
+
* processed.
|
|
2221
|
+
*/
|
|
2222
|
+
shutdown(force = false) {
|
|
2223
|
+
if (this.#state.is("draining", "stopped")) return Promise.resolve(0);
|
|
2224
|
+
if (force) {
|
|
2225
|
+
const count = this.purge();
|
|
2226
|
+
this.stop();
|
|
2227
|
+
this.#emit("shutdown", {
|
|
2228
|
+
force,
|
|
2229
|
+
pending: count
|
|
2230
|
+
});
|
|
2231
|
+
return Promise.resolve(count);
|
|
2232
|
+
}
|
|
2233
|
+
return this.#processBatch(Infinity, (pending) => {
|
|
2234
|
+
this.pause();
|
|
2235
|
+
this.#state.transition("draining");
|
|
2236
|
+
this.#off();
|
|
2237
|
+
this.#emit("drain", {
|
|
2238
|
+
pending
|
|
2239
|
+
});
|
|
2240
|
+
}, (drained) => {
|
|
2241
|
+
this.#emit("drained", force ? {
|
|
2242
|
+
pending: drained
|
|
2243
|
+
} : {
|
|
2244
|
+
drained
|
|
2245
|
+
});
|
|
2246
|
+
this.stop();
|
|
2247
|
+
this.#emit("shutdown", force ? {
|
|
2248
|
+
force,
|
|
2249
|
+
pending: drained
|
|
2250
|
+
} : {
|
|
2251
|
+
force
|
|
2252
|
+
});
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Executes `limit` items in the queue
|
|
2257
|
+
* and then emits a `flush` event. Returns the number
|
|
2258
|
+
* of items processed.
|
|
2259
|
+
*/
|
|
2260
|
+
async flush(limit = Infinity) {
|
|
2261
|
+
return this.#processBatch(limit, (pending) => this.#emit("flush", {
|
|
2262
|
+
pending
|
|
2263
|
+
}), (flushed) => this.#emit("flushed", {
|
|
2264
|
+
flushed
|
|
2265
|
+
}));
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* Clears the queue and emits a `purge` event. Returns
|
|
2269
|
+
* the number of items purged.
|
|
2270
|
+
*/
|
|
2271
|
+
purge() {
|
|
2272
|
+
const count = this.#queue.size();
|
|
2273
|
+
this.#queue.clear();
|
|
2274
|
+
this.#emit("purged", {
|
|
2275
|
+
count
|
|
2276
|
+
});
|
|
2277
|
+
return count;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Emit an event to the observer, which then gets
|
|
2281
|
+
* picked up by the queue and processed.
|
|
2282
|
+
*
|
|
2283
|
+
* @param data The data to add to the queue
|
|
2284
|
+
* @param priority The priority of the data
|
|
2285
|
+
*
|
|
2286
|
+
* @note If priority is provided, it will be used to determine the order of the data in the queue.
|
|
2287
|
+
* The higher the priority, the sooner the data will be processed.
|
|
2288
|
+
*
|
|
2289
|
+
* @note If priority is not provided, the data will be added to the queue with a priority of 0.
|
|
2290
|
+
*/
|
|
2291
|
+
add(data, priority) {
|
|
2292
|
+
if (!this.#state.is("running", "paused")) {
|
|
2293
|
+
this.#emit("rejected", {
|
|
2294
|
+
data,
|
|
2295
|
+
reason: QueueRejectionReason.notRunning
|
|
2296
|
+
});
|
|
2297
|
+
return false;
|
|
2298
|
+
}
|
|
2299
|
+
if (this.#queue.size() >= this.opts.maxQueueSize) {
|
|
2300
|
+
this.#emit("rejected", {
|
|
2301
|
+
data,
|
|
2302
|
+
reason: QueueRejectionReason.full
|
|
2303
|
+
});
|
|
2304
|
+
return false;
|
|
2305
|
+
}
|
|
2306
|
+
if (priority) {
|
|
2307
|
+
this.#priorites.set(data, priority);
|
|
2308
|
+
}
|
|
2309
|
+
this.opts.observer.emit(this.opts.event, data);
|
|
2310
|
+
return true;
|
|
2311
|
+
}
|
|
2312
|
+
debug(on = false) {
|
|
2313
|
+
this.#debugging = on;
|
|
2314
|
+
}
|
|
2315
|
+
#observerForQueue() {
|
|
2316
|
+
return this.opts.observer;
|
|
2317
|
+
}
|
|
2318
|
+
on(event, listener) {
|
|
2319
|
+
return this.#observerForQueue().on(`queue:${this.name}:${event}`, listener);
|
|
2320
|
+
}
|
|
2321
|
+
once(event, listener) {
|
|
2322
|
+
return this.#observerForQueue().once(`queue:${this.name}:${event}`, listener);
|
|
2323
|
+
}
|
|
2324
|
+
off(event, listener) {
|
|
2325
|
+
return this.#observerForQueue().off(`queue:${this.name}:${event}`, listener);
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* The name of the queue
|
|
2329
|
+
*/
|
|
2330
|
+
get name() {
|
|
2331
|
+
return this.opts.name;
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Whether the queue is waiting for the
|
|
2335
|
+
* the
|
|
2336
|
+
*/
|
|
2337
|
+
get isWaiting() {
|
|
2338
|
+
return this.#waiting;
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Whether the queue is idle
|
|
2342
|
+
*/
|
|
2343
|
+
get isIdle() {
|
|
2344
|
+
return this.#idle && this.#state.is("running");
|
|
2345
|
+
}
|
|
2346
|
+
/**
|
|
2347
|
+
* Whether the queue is running
|
|
2348
|
+
*/
|
|
2349
|
+
get isRunning() {
|
|
2350
|
+
return this.#state.is("running");
|
|
2351
|
+
}
|
|
2352
|
+
/**
|
|
2353
|
+
* Whether the queue is paused
|
|
2354
|
+
*/
|
|
2355
|
+
get isPaused() {
|
|
2356
|
+
return this.#state.is("paused");
|
|
2357
|
+
}
|
|
2358
|
+
/**
|
|
2359
|
+
* Whether the queue is stopped
|
|
2360
|
+
*/
|
|
2361
|
+
get isStopped() {
|
|
2362
|
+
return this.#state.is("stopped");
|
|
2363
|
+
}
|
|
2364
|
+
/**
|
|
2365
|
+
* Whether the queue is draining
|
|
2366
|
+
*/
|
|
2367
|
+
get isDraining() {
|
|
2368
|
+
return this.#state.is("draining");
|
|
2369
|
+
}
|
|
2370
|
+
/**
|
|
2371
|
+
* The current state of the queue
|
|
2372
|
+
*/
|
|
2373
|
+
get state() {
|
|
2374
|
+
return this.#state.state;
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* The number of items in the queue
|
|
2378
|
+
*/
|
|
2379
|
+
get pending() {
|
|
2380
|
+
return this.#queue.size();
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* The stats of the queue
|
|
2384
|
+
*/
|
|
2385
|
+
get stats() {
|
|
2386
|
+
return clone(this.#stats.stats);
|
|
2387
|
+
}
|
|
2388
|
+
get snapshot() {
|
|
2389
|
+
return {
|
|
2390
|
+
name: this.name,
|
|
2391
|
+
state: this.state,
|
|
2392
|
+
pending: this.pending,
|
|
2393
|
+
stats: this.stats,
|
|
2394
|
+
rateLimiter: this.#rateLimiter.snapshot,
|
|
2395
|
+
activeRunners: this.#activeRunners,
|
|
2396
|
+
runningNodes: this.#runningNodes,
|
|
2397
|
+
isIdle: this.isIdle,
|
|
2398
|
+
isWaiting: this.isWaiting,
|
|
2399
|
+
isRunning: this.isRunning,
|
|
2400
|
+
isPaused: this.isPaused,
|
|
2401
|
+
isStopped: this.isStopped,
|
|
2402
|
+
isDraining: this.isDraining,
|
|
2403
|
+
isEmpty: this.pending === 0
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2408
|
+
// node_modules/@logosdx/observer/dist/esm/engine.mjs
|
|
2409
|
+
var ObserverEngine = class _ObserverEngine {
|
|
2410
|
+
#listenerMap = /* @__PURE__ */ new Map();
|
|
2411
|
+
#rgxListenerMap = /* @__PURE__ */ new Map();
|
|
2412
|
+
#internalListener = new EventTarget();
|
|
2413
|
+
#emitValidator;
|
|
2414
|
+
#spy;
|
|
2415
|
+
// Hidden property for holding the spy function
|
|
2416
|
+
// when debugging is enabled. Used to restore the
|
|
2417
|
+
// original spy function when debugging is disabled.
|
|
2418
|
+
#__spy;
|
|
2419
|
+
// Instance-level AbortController for cleanup
|
|
2420
|
+
#instanceController = new AbortController();
|
|
2421
|
+
#instanceSignal;
|
|
2422
|
+
constructor(options) {
|
|
2423
|
+
if (options) {
|
|
2424
|
+
assert(!options.name || typeof options.name === "string", "Observable options.name must be a string", TypeError);
|
|
2425
|
+
assert(!options.spy || typeof options.spy === "function", "Observable options.spy must be a function", TypeError);
|
|
2426
|
+
assert(!options.emitValidator || typeof options.emitValidator === "function", "Observable options.emitValidator must be a function", TypeError);
|
|
2427
|
+
this.#spy = options.spy;
|
|
2428
|
+
}
|
|
2429
|
+
this.#instanceSignal = this.#instanceController.signal;
|
|
2430
|
+
const userSignal = options?.signal;
|
|
2431
|
+
const clearOnAbort = () => this.clear();
|
|
2432
|
+
this.#instanceSignal.addEventListener("abort", clearOnAbort, {
|
|
2433
|
+
once: true
|
|
2434
|
+
});
|
|
2435
|
+
if (userSignal) {
|
|
2436
|
+
userSignal.addEventListener("abort", clearOnAbort, {
|
|
2437
|
+
once: true
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
definePrivateProps(this, {
|
|
2441
|
+
on: this.on,
|
|
2442
|
+
once: this.once,
|
|
2443
|
+
emit: this.emit,
|
|
2444
|
+
off: this.off,
|
|
2445
|
+
observe: this.observe,
|
|
2446
|
+
debug: this.debug,
|
|
2447
|
+
$has: this.$has,
|
|
2448
|
+
$facts: this.$facts,
|
|
2449
|
+
$internals: this.$internals,
|
|
2450
|
+
name: options?.name || Math.random().toString(36).substring(7)
|
|
2451
|
+
});
|
|
2452
|
+
this.#emitValidator = options?.emitValidator;
|
|
2453
|
+
}
|
|
2454
|
+
name;
|
|
2455
|
+
/**
|
|
2456
|
+
* Returns facts about the the internal state of the observable instance.
|
|
2457
|
+
*/
|
|
2458
|
+
$facts() {
|
|
2459
|
+
const listenKeys = [
|
|
2460
|
+
...this.#listenerMap.keys()
|
|
2461
|
+
];
|
|
2462
|
+
const rgxKeys = [
|
|
2463
|
+
...this.#rgxListenerMap.keys()
|
|
2464
|
+
];
|
|
2465
|
+
const listenerCounts = Object.fromEntries([
|
|
2466
|
+
listenKeys.map((k) => [
|
|
2467
|
+
k,
|
|
2468
|
+
this.#listenerMap.get(k)?.size
|
|
2469
|
+
]),
|
|
2470
|
+
rgxKeys.map((k) => [
|
|
2471
|
+
k,
|
|
2472
|
+
this.#rgxListenerMap.get(k)?.size
|
|
2473
|
+
])
|
|
2474
|
+
].flat());
|
|
2475
|
+
return {
|
|
2476
|
+
listeners: listenKeys,
|
|
2477
|
+
rgxListeners: rgxKeys,
|
|
2478
|
+
listenerCounts,
|
|
2479
|
+
hasSpy: !!this.#spy
|
|
2480
|
+
};
|
|
2481
|
+
}
|
|
2482
|
+
/**
|
|
2483
|
+
* The internals of the observable instance.
|
|
2484
|
+
*
|
|
2485
|
+
* NOTE: Do not use this to try to meddle with the
|
|
2486
|
+
* internals of the observable instance. This is for
|
|
2487
|
+
* debugging purposes only.
|
|
2488
|
+
*/
|
|
2489
|
+
$internals() {
|
|
2490
|
+
return {
|
|
2491
|
+
listenerMap: clone(this.#listenerMap),
|
|
2492
|
+
rgxListenerMap: clone(this.#rgxListenerMap),
|
|
2493
|
+
internalListener: clone(this.#internalListener),
|
|
2494
|
+
name: this.name,
|
|
2495
|
+
spy: this.#spy
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
$has(event) {
|
|
2499
|
+
if (event instanceof RegExp) {
|
|
2500
|
+
return this.#rgxListenerMap.has(event.toString());
|
|
2501
|
+
}
|
|
2502
|
+
return this.#listenerMap.has(event) || this.#rgxListenerMap.has(event);
|
|
2503
|
+
}
|
|
2504
|
+
#currentSpy(...args) {
|
|
2505
|
+
if (this.#spy) {
|
|
2506
|
+
this.#spy.apply(this, args);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
/**
|
|
2510
|
+
* Enables or disables debugging for the observable instance.
|
|
2511
|
+
* Works in conjunction with your spy function. Provides a
|
|
2512
|
+
* stack trace of events that are triggered, listened to, and
|
|
2513
|
+
* cleaned up.
|
|
2514
|
+
*
|
|
2515
|
+
* @param on Whether to enable or disable debugging
|
|
2516
|
+
*/
|
|
2517
|
+
debug(on = true) {
|
|
2518
|
+
const original = this.#spy;
|
|
2519
|
+
const spy = (ev) => {
|
|
2520
|
+
const { event, fn, data, listener } = ev;
|
|
2521
|
+
console.info(makeEventTracer(event, fn, data || listener));
|
|
2522
|
+
original && original(ev);
|
|
2523
|
+
};
|
|
2524
|
+
if (on) {
|
|
2525
|
+
this.#spy = spy;
|
|
2526
|
+
this.#__spy = original;
|
|
2527
|
+
return;
|
|
2528
|
+
}
|
|
2529
|
+
this.#spy = this.#__spy;
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Sets the spy function for the observable instance.
|
|
2533
|
+
* @param spy The spy function to set
|
|
2534
|
+
* @param force Whether to force the spy function to be set even if one is already set
|
|
2535
|
+
*/
|
|
2536
|
+
spy(spy, force = false) {
|
|
2537
|
+
assert(isFunction(spy), "spy must be a function", TypeError);
|
|
2538
|
+
assert(force || this.#spy === void 0, "you already have a spy function set", TypeError);
|
|
2539
|
+
this.#spy = spy;
|
|
2540
|
+
}
|
|
2541
|
+
/**
|
|
2542
|
+
* Observes given component as an extension of this observable instance.
|
|
2543
|
+
* @param component Component to wrap events around
|
|
2544
|
+
* @param options Optional configuration including signal for cleanup
|
|
2545
|
+
*
|
|
2546
|
+
* @example
|
|
2547
|
+
*
|
|
2548
|
+
* const obs = new ObserverEngine();
|
|
2549
|
+
*
|
|
2550
|
+
* const modal = {};
|
|
2551
|
+
*
|
|
2552
|
+
* obs.observe(modal);
|
|
2553
|
+
*
|
|
2554
|
+
* modal.on('modal-open', () => {});
|
|
2555
|
+
*
|
|
2556
|
+
* obs.trigger('modal-open'); // opens modal
|
|
2557
|
+
* modal.trigger('modal-open'); // opens modal
|
|
2558
|
+
*
|
|
2559
|
+
* modal.cleanup(); // clears all event listeners
|
|
2560
|
+
*/
|
|
2561
|
+
observe(component, options) {
|
|
2562
|
+
const self = this;
|
|
2563
|
+
const userSignal = options?.signal;
|
|
2564
|
+
if (userSignal?.aborted) {
|
|
2565
|
+
definePrivateProps(component, {
|
|
2566
|
+
on: noop,
|
|
2567
|
+
once: noop,
|
|
2568
|
+
off: noop,
|
|
2569
|
+
emit: noop,
|
|
2570
|
+
clear: noop,
|
|
2571
|
+
cleanup: noop
|
|
2572
|
+
});
|
|
2573
|
+
return component;
|
|
2574
|
+
}
|
|
2575
|
+
const track = /* @__PURE__ */ new Map();
|
|
2576
|
+
const trackListener = (event, fn) => {
|
|
2577
|
+
const _set = track.get(event) || /* @__PURE__ */ new Set();
|
|
2578
|
+
_set.add(fn);
|
|
2579
|
+
track.set(event, _set);
|
|
2580
|
+
return fn;
|
|
2581
|
+
};
|
|
2582
|
+
const rmAll = () => {
|
|
2583
|
+
for (const entry of track.entries()) {
|
|
2584
|
+
const [ev, _set] = entry;
|
|
2585
|
+
[
|
|
2586
|
+
..._set
|
|
2587
|
+
].forEach((fn) => self.off(ev, fn));
|
|
2588
|
+
track.set(ev, /* @__PURE__ */ new Set());
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2591
|
+
const afterOff = (_event) => {
|
|
2592
|
+
const [event, callback] = _event.data;
|
|
2593
|
+
const _set = track.get(event);
|
|
2594
|
+
_set?.delete(callback);
|
|
2595
|
+
};
|
|
2596
|
+
this.#internalListener.addEventListener(InternalEvs.off, afterOff);
|
|
2597
|
+
this.#internalListener.addEventListener(InternalEvs.clear, rmAll);
|
|
2598
|
+
const on = (ev, fn) => {
|
|
2599
|
+
return self.on(ev, trackListener(ev, fn));
|
|
2600
|
+
};
|
|
2601
|
+
const once = (ev, fn) => {
|
|
2602
|
+
return self.once(ev, trackListener(ev, fn));
|
|
2603
|
+
};
|
|
2604
|
+
const off = (ev, fn) => {
|
|
2605
|
+
self.off(ev, fn);
|
|
2606
|
+
};
|
|
2607
|
+
const emit = (ev, data) => {
|
|
2608
|
+
return self.emit(ev, data);
|
|
2609
|
+
};
|
|
2610
|
+
const clear = () => rmAll();
|
|
2611
|
+
let observeAbortCtrl;
|
|
2612
|
+
const cleanup = () => {
|
|
2613
|
+
rmAll();
|
|
2614
|
+
self.#internalListener.removeEventListener(InternalEvs.off, afterOff);
|
|
2615
|
+
self.#internalListener.removeEventListener(InternalEvs.clear, rmAll);
|
|
2616
|
+
observeAbortCtrl?.abort();
|
|
2617
|
+
};
|
|
2618
|
+
if (userSignal) {
|
|
2619
|
+
observeAbortCtrl = new AbortController();
|
|
2620
|
+
const composedSignal = AbortSignal.any([
|
|
2621
|
+
this.#instanceSignal,
|
|
2622
|
+
userSignal
|
|
2623
|
+
]);
|
|
2624
|
+
composedSignal.addEventListener("abort", cleanup, {
|
|
2625
|
+
signal: observeAbortCtrl.signal
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
definePrivateProps(component, {
|
|
2629
|
+
on,
|
|
2630
|
+
once,
|
|
2631
|
+
off,
|
|
2632
|
+
emit,
|
|
2633
|
+
clear,
|
|
2634
|
+
cleanup
|
|
2635
|
+
});
|
|
2636
|
+
return component;
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Gets information about the event, whether it's a regex or not,
|
|
2640
|
+
* the event name, and the regex itself.
|
|
2641
|
+
*/
|
|
2642
|
+
#eventInfo(event) {
|
|
2643
|
+
const isRgx = event.constructor === RegExp;
|
|
2644
|
+
const eventName = event.toString();
|
|
2645
|
+
return {
|
|
2646
|
+
isRgx,
|
|
2647
|
+
eventName,
|
|
2648
|
+
rgx: event
|
|
2649
|
+
};
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* Returns all event names that match the regex
|
|
2653
|
+
*/
|
|
2654
|
+
#withRgxMatchKeys(rgx) {
|
|
2655
|
+
return [
|
|
2656
|
+
...this.#listenerMap.keys()
|
|
2657
|
+
].filter((k) => rgx.test(k));
|
|
2658
|
+
}
|
|
2659
|
+
/**
|
|
2660
|
+
* Returns all regexes that match the key
|
|
2661
|
+
*/
|
|
2662
|
+
#withKeyMatchRgx(key) {
|
|
2663
|
+
return [
|
|
2664
|
+
...this.#rgxListenerMap.keys()
|
|
2665
|
+
].filter((s) => rgxStrToRgx(s).test(key)).flat();
|
|
2666
|
+
}
|
|
2667
|
+
/**
|
|
2668
|
+
* Returns all event names that match the regex
|
|
2669
|
+
*/
|
|
2670
|
+
#matchStr(rgx) {
|
|
2671
|
+
const events = this.#withRgxMatchKeys(rgx);
|
|
2672
|
+
return arrOfMatchingValues(events, this.#listenerMap);
|
|
2673
|
+
}
|
|
2674
|
+
/**
|
|
2675
|
+
* Returns all regexes that match the key
|
|
2676
|
+
*/
|
|
2677
|
+
#matchRgx(str) {
|
|
2678
|
+
const events = this.#withKeyMatchRgx(str);
|
|
2679
|
+
return arrOfMatchingValues(events, this.#rgxListenerMap);
|
|
2680
|
+
}
|
|
2681
|
+
/**
|
|
2682
|
+
* Listen for an event
|
|
2683
|
+
* @param event
|
|
2684
|
+
* @param listenerOrOptions - Either a callback function or options object
|
|
2685
|
+
* @param options
|
|
2686
|
+
*/
|
|
2687
|
+
on(event, listenerOrOptions, options) {
|
|
2688
|
+
const isListenerFn = typeof listenerOrOptions === "function";
|
|
2689
|
+
const listener = isListenerFn ? listenerOrOptions : void 0;
|
|
2690
|
+
const resolvedOptions = isListenerFn ? options : listenerOrOptions;
|
|
2691
|
+
if (!resolvedOptions?.once) {
|
|
2692
|
+
validateEvent("on", {
|
|
2693
|
+
event,
|
|
2694
|
+
listener
|
|
2695
|
+
});
|
|
2696
|
+
validateListener("on", {
|
|
2697
|
+
event,
|
|
2698
|
+
listener
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
if (listener === void 0) {
|
|
2702
|
+
return new EventGenerator(this, event, resolvedOptions);
|
|
2703
|
+
}
|
|
2704
|
+
const userSignal = resolvedOptions?.signal;
|
|
2705
|
+
if (userSignal?.aborted) {
|
|
2706
|
+
return () => {
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
const { eventName, isRgx } = this.#eventInfo(event);
|
|
2710
|
+
const listenerMap = isRgx ? this.#rgxListenerMap : this.#listenerMap;
|
|
2711
|
+
this.#currentSpy({
|
|
2712
|
+
event,
|
|
2713
|
+
fn: resolvedOptions?.once ? "once" : "on",
|
|
2714
|
+
data: null,
|
|
2715
|
+
listener,
|
|
2716
|
+
context: this
|
|
2717
|
+
});
|
|
2718
|
+
const cbSet = listenerMap.get(eventName) || /* @__PURE__ */ new Set([
|
|
2719
|
+
listener
|
|
2720
|
+
]);
|
|
2721
|
+
if (cbSet && !cbSet.has(listener)) {
|
|
2722
|
+
cbSet.add(listener);
|
|
2723
|
+
}
|
|
2724
|
+
if (!listenerMap.has(eventName)) {
|
|
2725
|
+
listenerMap.set(eventName, cbSet);
|
|
2726
|
+
}
|
|
2727
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.on, [
|
|
2728
|
+
event,
|
|
2729
|
+
listener
|
|
2730
|
+
]));
|
|
2731
|
+
let cleanedUp = false;
|
|
2732
|
+
const cleanup = () => {
|
|
2733
|
+
if (cleanedUp) return;
|
|
2734
|
+
cleanedUp = true;
|
|
2735
|
+
this.#currentSpy({
|
|
2736
|
+
event,
|
|
2737
|
+
fn: "cleanup",
|
|
2738
|
+
data: null,
|
|
2739
|
+
listener,
|
|
2740
|
+
context: this
|
|
2741
|
+
});
|
|
2742
|
+
cbSet.delete(listener);
|
|
2743
|
+
if (cbSet.size === 0) {
|
|
2744
|
+
listenerMap.delete(eventName);
|
|
2745
|
+
}
|
|
2746
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.off, [
|
|
2747
|
+
event,
|
|
2748
|
+
listener
|
|
2749
|
+
]));
|
|
2750
|
+
};
|
|
2751
|
+
if (userSignal) {
|
|
2752
|
+
const abortHandler = () => {
|
|
2753
|
+
cleanup();
|
|
2754
|
+
this.#instanceSignal.removeEventListener("abort", abortHandler);
|
|
2755
|
+
};
|
|
2756
|
+
userSignal.addEventListener("abort", abortHandler, {
|
|
2757
|
+
once: true
|
|
2758
|
+
});
|
|
2759
|
+
this.#instanceSignal.addEventListener("abort", abortHandler, {
|
|
2760
|
+
once: true
|
|
2761
|
+
});
|
|
2762
|
+
const originalCleanup = cleanup;
|
|
2763
|
+
const wrappedCleanup = () => {
|
|
2764
|
+
originalCleanup();
|
|
2765
|
+
userSignal.removeEventListener("abort", abortHandler);
|
|
2766
|
+
this.#instanceSignal.removeEventListener("abort", abortHandler);
|
|
2767
|
+
};
|
|
2768
|
+
return wrappedCleanup;
|
|
2769
|
+
}
|
|
2770
|
+
return cleanup;
|
|
2771
|
+
}
|
|
2772
|
+
/**
|
|
2773
|
+
* Executes a callback once when the specified
|
|
2774
|
+
* event is emitted, or returns a promise that
|
|
2775
|
+
* resolves when the event is emitted
|
|
2776
|
+
*/
|
|
2777
|
+
once(event, listenerOrOptions, options) {
|
|
2778
|
+
const isListenerFn = typeof listenerOrOptions === "function";
|
|
2779
|
+
const listener = isListenerFn ? listenerOrOptions : void 0;
|
|
2780
|
+
const resolvedOptions = isListenerFn ? options : listenerOrOptions;
|
|
2781
|
+
validateEvent("once", {
|
|
2782
|
+
event,
|
|
2783
|
+
listener
|
|
2784
|
+
});
|
|
2785
|
+
validateListener("once", {
|
|
2786
|
+
event,
|
|
2787
|
+
listener
|
|
2788
|
+
});
|
|
2789
|
+
if (!listener) {
|
|
2790
|
+
const defer = new DeferredEvent();
|
|
2791
|
+
const userSignal = resolvedOptions?.signal;
|
|
2792
|
+
if (userSignal?.aborted) {
|
|
2793
|
+
defer.reject(userSignal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
2794
|
+
defer.promise.cleanup = () => {
|
|
2795
|
+
};
|
|
2796
|
+
return defer.promise;
|
|
2797
|
+
}
|
|
2798
|
+
let promiseAbortCtrl;
|
|
2799
|
+
const cleanup = this.once(event, (data) => {
|
|
2800
|
+
defer.resolve(data);
|
|
2801
|
+
promiseAbortCtrl?.abort();
|
|
2802
|
+
}, resolvedOptions);
|
|
2803
|
+
if (userSignal) {
|
|
2804
|
+
promiseAbortCtrl = new AbortController();
|
|
2805
|
+
userSignal.addEventListener("abort", () => {
|
|
2806
|
+
cleanup();
|
|
2807
|
+
defer.reject(userSignal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
2808
|
+
}, {
|
|
2809
|
+
signal: promiseAbortCtrl.signal
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
defer.promise.cleanup = () => {
|
|
2813
|
+
cleanup();
|
|
2814
|
+
promiseAbortCtrl?.abort();
|
|
2815
|
+
};
|
|
2816
|
+
return defer.promise;
|
|
2817
|
+
}
|
|
2818
|
+
const self = this;
|
|
2819
|
+
const runOnce = function(...args) {
|
|
2820
|
+
const { eventName, isRgx } = self.#eventInfo(event);
|
|
2821
|
+
const listenerMap = isRgx ? self.#rgxListenerMap : self.#listenerMap;
|
|
2822
|
+
const fns = listenerMap.get(eventName);
|
|
2823
|
+
if (fns) {
|
|
2824
|
+
fns.delete(runOnce);
|
|
2825
|
+
if (fns.size === 0) listenerMap.delete(eventName);
|
|
2826
|
+
}
|
|
2827
|
+
listener.apply(self, args);
|
|
2828
|
+
};
|
|
2829
|
+
return this.on(event, runOnce, {
|
|
2830
|
+
once: true,
|
|
2831
|
+
...resolvedOptions
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
/**
|
|
2835
|
+
* Stop listening for an event
|
|
2836
|
+
* @param event
|
|
2837
|
+
* @param listener
|
|
2838
|
+
*/
|
|
2839
|
+
off(event, listener) {
|
|
2840
|
+
validateEvent("off", {
|
|
2841
|
+
event,
|
|
2842
|
+
listener
|
|
2843
|
+
});
|
|
2844
|
+
this.#currentSpy({
|
|
2845
|
+
event,
|
|
2846
|
+
fn: "off",
|
|
2847
|
+
data: null,
|
|
2848
|
+
listener,
|
|
2849
|
+
context: this
|
|
2850
|
+
});
|
|
2851
|
+
const { eventName, isRgx, rgx } = this.#eventInfo(event);
|
|
2852
|
+
const matches = isRgx ? this.#withRgxMatchKeys(rgx) : [
|
|
2853
|
+
eventName
|
|
2854
|
+
];
|
|
2855
|
+
matches.forEach((_ev) => {
|
|
2856
|
+
const ev = _ev;
|
|
2857
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.off, [
|
|
2858
|
+
ev,
|
|
2859
|
+
listener
|
|
2860
|
+
]));
|
|
2861
|
+
if (listener) {
|
|
2862
|
+
const fns = this.#listenerMap.get(ev);
|
|
2863
|
+
if (fns) {
|
|
2864
|
+
fns.delete(listener);
|
|
2865
|
+
if (fns.size === 0) this.#listenerMap.delete(ev);
|
|
2866
|
+
}
|
|
2867
|
+
return;
|
|
2868
|
+
}
|
|
2869
|
+
this.#listenerMap.delete(ev);
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
/** Emits an event */
|
|
2873
|
+
emit(event, data) {
|
|
2874
|
+
validateEvent("emit", {
|
|
2875
|
+
event,
|
|
2876
|
+
data
|
|
2877
|
+
});
|
|
2878
|
+
if (this.#emitValidator) {
|
|
2879
|
+
this.#emitValidator(event, data, this);
|
|
2880
|
+
}
|
|
2881
|
+
this.#currentSpy({
|
|
2882
|
+
event,
|
|
2883
|
+
fn: "emit",
|
|
2884
|
+
data,
|
|
2885
|
+
listener: null,
|
|
2886
|
+
context: this
|
|
2887
|
+
});
|
|
2888
|
+
const { eventName, isRgx, rgx } = this.#eventInfo(event);
|
|
2889
|
+
if (!isRgx) {
|
|
2890
|
+
const cbs2 = this.#listenerMap.get(eventName);
|
|
2891
|
+
const rgxCbs = this.#matchRgx(eventName);
|
|
2892
|
+
if (cbs2) cbs2.forEach((fn) => fn.apply(this, [
|
|
2893
|
+
data,
|
|
2894
|
+
{
|
|
2895
|
+
event,
|
|
2896
|
+
listener: fn
|
|
2897
|
+
}
|
|
2898
|
+
]));
|
|
2899
|
+
if (rgxCbs) rgxCbs.forEach(({ func }) => func.apply(this, [
|
|
2900
|
+
{
|
|
2901
|
+
data,
|
|
2902
|
+
event,
|
|
2903
|
+
listener: func
|
|
2904
|
+
}
|
|
2905
|
+
]));
|
|
2906
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.emit, [
|
|
2907
|
+
eventName,
|
|
2908
|
+
data
|
|
2909
|
+
]));
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2912
|
+
const cbs = this.#matchStr(rgx);
|
|
2913
|
+
if (cbs) cbs.forEach(({ event: event2, func }) => func.apply(this, [
|
|
2914
|
+
data,
|
|
2915
|
+
{
|
|
2916
|
+
event: event2,
|
|
2917
|
+
listener: func
|
|
2918
|
+
}
|
|
2919
|
+
]));
|
|
2920
|
+
this.#withRgxMatchKeys(rgx).forEach((ev) => {
|
|
2921
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.emit, [
|
|
2922
|
+
ev,
|
|
2923
|
+
data
|
|
2924
|
+
]));
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
clear() {
|
|
2928
|
+
this.#listenerMap.clear();
|
|
2929
|
+
this.#rgxListenerMap.clear();
|
|
2930
|
+
this.#internalListener.dispatchEvent(new InternalEvent(InternalEvs.clear, [
|
|
2931
|
+
"clear",
|
|
2932
|
+
null
|
|
2933
|
+
]));
|
|
2934
|
+
}
|
|
2935
|
+
queue(event, process2, options) {
|
|
2936
|
+
return new EventQueue({
|
|
2937
|
+
...options,
|
|
2938
|
+
event,
|
|
2939
|
+
process: process2,
|
|
2940
|
+
observer: this
|
|
2941
|
+
});
|
|
2942
|
+
}
|
|
2943
|
+
/**
|
|
2944
|
+
* Checks if an event key passes through the filter/exclude pipeline.
|
|
2945
|
+
* Filter narrows first, then exclude removes from that set.
|
|
2946
|
+
*/
|
|
2947
|
+
static #passesFilter(event, options) {
|
|
2948
|
+
if (!options) return true;
|
|
2949
|
+
const { filter, exclude } = options;
|
|
2950
|
+
if (filter) {
|
|
2951
|
+
const passes = filter.some((f) => f instanceof RegExp ? f.test(event) : f === event);
|
|
2952
|
+
if (!passes) return false;
|
|
2953
|
+
}
|
|
2954
|
+
if (exclude) {
|
|
2955
|
+
const blocked = exclude.some((e) => e instanceof RegExp ? e.test(event) : e === event);
|
|
2956
|
+
if (blocked) return false;
|
|
2957
|
+
}
|
|
2958
|
+
return true;
|
|
2959
|
+
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Moves or copies listeners between two ObserverEngine instances.
|
|
2962
|
+
* Static methods on the same class can access # private fields directly.
|
|
2963
|
+
*/
|
|
2964
|
+
static #moveListeners(source, target, remove, options) {
|
|
2965
|
+
for (const [event, callbacks] of source.#listenerMap) {
|
|
2966
|
+
if (!_ObserverEngine.#passesFilter(event, options)) continue;
|
|
2967
|
+
const targetSet = target.#listenerMap.get(event) || /* @__PURE__ */ new Set();
|
|
2968
|
+
for (const cb of callbacks) {
|
|
2969
|
+
targetSet.add(cb);
|
|
2970
|
+
}
|
|
2971
|
+
target.#listenerMap.set(event, targetSet);
|
|
2972
|
+
if (remove) {
|
|
2973
|
+
source.#listenerMap.delete(event);
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
for (const [event, callbacks] of source.#rgxListenerMap) {
|
|
2977
|
+
if (!_ObserverEngine.#passesFilter(event, options)) continue;
|
|
2978
|
+
const targetSet = target.#rgxListenerMap.get(event) || /* @__PURE__ */ new Set();
|
|
2979
|
+
for (const cb of callbacks) {
|
|
2980
|
+
targetSet.add(cb);
|
|
2981
|
+
}
|
|
2982
|
+
target.#rgxListenerMap.set(event, targetSet);
|
|
2983
|
+
if (remove) {
|
|
2984
|
+
source.#rgxListenerMap.delete(event);
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Transfers all matching listeners from source to target, removing
|
|
2990
|
+
* them from the source. Target's existing listeners are preserved.
|
|
2991
|
+
*
|
|
2992
|
+
* Useful when cloning an engine (e.g. FetchEngine) and carrying
|
|
2993
|
+
* over observability listeners to the new instance.
|
|
2994
|
+
*
|
|
2995
|
+
* @example
|
|
2996
|
+
*
|
|
2997
|
+
* const old = new ObserverEngine();
|
|
2998
|
+
* const next = new ObserverEngine();
|
|
2999
|
+
*
|
|
3000
|
+
* old.on('ready', handler);
|
|
3001
|
+
*
|
|
3002
|
+
* ObserverEngine.transfer(old, next);
|
|
3003
|
+
* // `next` now owns the 'ready' listener; `old` has none
|
|
3004
|
+
*
|
|
3005
|
+
* @example
|
|
3006
|
+
*
|
|
3007
|
+
* // Transfer only specific events
|
|
3008
|
+
* ObserverEngine.transfer(old, next, {
|
|
3009
|
+
* filter: ['ready', /^user\./]
|
|
3010
|
+
* });
|
|
3011
|
+
*/
|
|
3012
|
+
static transfer(source, target, options) {
|
|
3013
|
+
_ObserverEngine.#moveListeners(source, target, true, options);
|
|
3014
|
+
}
|
|
3015
|
+
/**
|
|
3016
|
+
* Copies all matching listeners from source to target without
|
|
3017
|
+
* removing them from the source. Target's existing listeners
|
|
3018
|
+
* are preserved.
|
|
3019
|
+
*
|
|
3020
|
+
* Useful when forking an engine so both instances react to the
|
|
3021
|
+
* same events independently.
|
|
3022
|
+
*
|
|
3023
|
+
* @example
|
|
3024
|
+
*
|
|
3025
|
+
* const primary = new ObserverEngine();
|
|
3026
|
+
* const mirror = new ObserverEngine();
|
|
3027
|
+
*
|
|
3028
|
+
* primary.on('update', handler);
|
|
3029
|
+
*
|
|
3030
|
+
* ObserverEngine.copy(primary, mirror);
|
|
3031
|
+
* // Both engines now have the 'update' listener
|
|
3032
|
+
*
|
|
3033
|
+
* @example
|
|
3034
|
+
*
|
|
3035
|
+
* // Copy everything except internal events
|
|
3036
|
+
* ObserverEngine.copy(primary, mirror, {
|
|
3037
|
+
* exclude: [/^__/]
|
|
3038
|
+
* });
|
|
3039
|
+
*/
|
|
3040
|
+
static copy(source, target, options) {
|
|
3041
|
+
_ObserverEngine.#moveListeners(source, target, false, options);
|
|
3042
|
+
}
|
|
3043
|
+
};
|
|
3044
|
+
|
|
3045
|
+
// node_modules/@logosdx/observer/dist/esm/relay.mjs
|
|
3046
|
+
var ObserverRelay = class {
|
|
3047
|
+
#pub;
|
|
3048
|
+
#sub;
|
|
3049
|
+
#subEmit;
|
|
3050
|
+
#isShutdown = false;
|
|
3051
|
+
emit;
|
|
3052
|
+
on;
|
|
3053
|
+
once;
|
|
3054
|
+
off;
|
|
3055
|
+
queue;
|
|
3056
|
+
constructor(options) {
|
|
3057
|
+
const name = options?.name;
|
|
3058
|
+
this.#pub = new ObserverEngine({
|
|
3059
|
+
name: name ? `${name}:pub` : void 0,
|
|
3060
|
+
spy: options?.spy,
|
|
3061
|
+
signal: options?.signal,
|
|
3062
|
+
emitValidator: options?.emitValidator?.pub
|
|
3063
|
+
});
|
|
3064
|
+
this.#sub = new ObserverEngine({
|
|
3065
|
+
name: name ? `${name}:sub` : void 0,
|
|
3066
|
+
spy: options?.spy,
|
|
3067
|
+
signal: options?.signal,
|
|
3068
|
+
emitValidator: options?.emitValidator?.sub
|
|
3069
|
+
});
|
|
3070
|
+
this.on = this.#sub.on.bind(this.#sub);
|
|
3071
|
+
this.once = this.#sub.once.bind(this.#sub);
|
|
3072
|
+
this.off = this.#sub.off.bind(this.#sub);
|
|
3073
|
+
this.queue = this.#sub.queue.bind(this.#sub);
|
|
3074
|
+
this.#subEmit = this.#sub.emit.bind(this.#sub);
|
|
3075
|
+
const pubEmit = this.#pub.emit.bind(this.#pub);
|
|
3076
|
+
this.emit = (event, data) => {
|
|
3077
|
+
if (this.#isShutdown) return;
|
|
3078
|
+
pubEmit(event, data);
|
|
3079
|
+
};
|
|
3080
|
+
this.#pub.on(/.+/, ({ event, data }) => this.send(event, data));
|
|
3081
|
+
if (options?.signal) {
|
|
3082
|
+
options.signal.addEventListener("abort", () => {
|
|
3083
|
+
this.#isShutdown = true;
|
|
3084
|
+
});
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
receive(event, data, ctx) {
|
|
3088
|
+
if (this.#isShutdown) return;
|
|
3089
|
+
this.#subEmit(event, {
|
|
3090
|
+
data,
|
|
3091
|
+
ctx
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
spy(spy) {
|
|
3095
|
+
if (this.#isShutdown) return;
|
|
3096
|
+
this.#pub.spy(spy, true);
|
|
3097
|
+
this.#sub.spy(spy, true);
|
|
3098
|
+
}
|
|
3099
|
+
$has(event) {
|
|
3100
|
+
return {
|
|
3101
|
+
pub: this.#pub.$has(event),
|
|
3102
|
+
sub: this.#sub.$has(event)
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
$facts() {
|
|
3106
|
+
return {
|
|
3107
|
+
pub: this.#pub.$facts(),
|
|
3108
|
+
sub: this.#sub.$facts()
|
|
3109
|
+
};
|
|
3110
|
+
}
|
|
3111
|
+
$internals() {
|
|
3112
|
+
return {
|
|
3113
|
+
pub: this.#pub.$internals(),
|
|
3114
|
+
sub: this.#sub.$internals()
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
3117
|
+
get isShutdown() {
|
|
3118
|
+
return this.#isShutdown;
|
|
3119
|
+
}
|
|
3120
|
+
shutdown() {
|
|
3121
|
+
if (this.#isShutdown) return;
|
|
3122
|
+
this.#isShutdown = true;
|
|
3123
|
+
this.#pub.clear();
|
|
3124
|
+
this.#sub.clear();
|
|
3125
|
+
}
|
|
3126
|
+
};
|
|
3127
|
+
|
|
3128
|
+
// src/core/observer.ts
|
|
3129
|
+
var observer = new ObserverEngine({
|
|
3130
|
+
name: "noorm",
|
|
3131
|
+
spy: process.env["NOORM_DEBUG"] ? (action) => console.error(`[noorm:${action.fn}] ${String(action.event)}`) : void 0
|
|
3132
|
+
});
|
|
3133
|
+
|
|
3134
|
+
export { ObserverRelay, attempt, attemptSync, clone, gigabytes, makeNestedConfig, merge, observer, retry };
|
|
3135
|
+
//# sourceMappingURL=chunk-UDUDHOIB.js.map
|
|
3136
|
+
//# sourceMappingURL=chunk-UDUDHOIB.js.map
|