hanzio 1.0.0

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.
Files changed (51) hide show
  1. package/README.md +510 -0
  2. package/dist/api-wrapper/index.d.ts +84 -0
  3. package/dist/api-wrapper/index.js +250 -0
  4. package/dist/array/index.d.ts +22 -0
  5. package/dist/cache/index.d.ts +19 -0
  6. package/dist/date/index.d.ts +11 -0
  7. package/dist/gzip/index.d.ts +2 -0
  8. package/dist/gzip/index.js +16 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +1565 -0
  11. package/dist/jwt/index.d.ts +3 -0
  12. package/dist/jwt/index.js +19 -0
  13. package/dist/math/index.d.ts +2 -0
  14. package/dist/math/linearRegressionTrend.d.ts +5 -0
  15. package/dist/math/metricsSeriesColors.d.ts +42 -0
  16. package/dist/p-queue/index.d.ts +95 -0
  17. package/dist/p-queue/index.js +439 -0
  18. package/dist/promise/index.d.ts +21 -0
  19. package/dist/sitemap/index.d.ts +14 -0
  20. package/dist/sitemap/index.js +552 -0
  21. package/dist/state/index.d.ts +101 -0
  22. package/dist/string/index.d.ts +8 -0
  23. package/dist/typedswitch/index.d.ts +124 -0
  24. package/dist/url/index.d.ts +1 -0
  25. package/dist/zod/index.d.ts +8 -0
  26. package/dist/zod/index.js +210 -0
  27. package/dist/zod/jsonToZodSchemaMapper.d.ts +6 -0
  28. package/dist/zod/zodMinMaxFilter.d.ts +14 -0
  29. package/dist/zod/zodToTypeString.d.ts +9 -0
  30. package/package.json +102 -0
  31. package/src/api-wrapper/index.ts +492 -0
  32. package/src/array/index.ts +187 -0
  33. package/src/cache/index.ts +154 -0
  34. package/src/date/index.ts +54 -0
  35. package/src/gzip/index.ts +29 -0
  36. package/src/index.ts +12 -0
  37. package/src/jwt/index.ts +25 -0
  38. package/src/math/index.ts +11 -0
  39. package/src/math/linearRegressionTrend.ts +36 -0
  40. package/src/math/metricsSeriesColors.ts +208 -0
  41. package/src/p-queue/index.ts +690 -0
  42. package/src/promise/index.ts +73 -0
  43. package/src/sitemap/index.ts +195 -0
  44. package/src/state/index.ts +331 -0
  45. package/src/string/index.ts +86 -0
  46. package/src/typedswitch/index.ts +309 -0
  47. package/src/url/index.ts +5 -0
  48. package/src/zod/index.ts +29 -0
  49. package/src/zod/jsonToZodSchemaMapper.ts +44 -0
  50. package/src/zod/zodMinMaxFilter.ts +28 -0
  51. package/src/zod/zodToTypeString.ts +222 -0
@@ -0,0 +1,3 @@
1
+ import * as jose from 'jose';
2
+ export declare function jwtSign<_Payload extends object>(payload: jose.JWTPayload, secret: string): Promise<string>;
3
+ export declare function jwtVerify<Payload extends object>(token: string, secret: string): Promise<Payload | null>;
@@ -0,0 +1,19 @@
1
+ // src/jwt/index.ts
2
+ import * as jose from "jose";
3
+ async function jwtSign(payload, secret) {
4
+ const secretKey = new TextEncoder().encode(secret);
5
+ return await new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().sign(secretKey);
6
+ }
7
+ async function jwtVerify2(token, secret) {
8
+ try {
9
+ const secretKey = new TextEncoder().encode(secret);
10
+ const { payload } = await jose.jwtVerify(token, secretKey);
11
+ return payload;
12
+ } catch (_error) {
13
+ return null;
14
+ }
15
+ }
16
+ export {
17
+ jwtVerify2 as jwtVerify,
18
+ jwtSign
19
+ };
@@ -0,0 +1,2 @@
1
+ export { linearRegressionTrend } from './linearRegressionTrend';
2
+ export { createResolveColorsByKeys, getHeatmapCellStyle, hashStringToColorIndex, METRICS_SERIES_PALETTE_SIZE, type ResolveColorsByKeysResult, resolveSeriesColorMap, seriesColorKey, withAlpha } from './metricsSeriesColors';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Least-squares linear regression for y at x = 0, 1, …, n − 1.
3
+ * Returns fitted y for each index, or [] if n < 2 or any input is non-finite.
4
+ */
5
+ export declare function linearRegressionTrend(values: number[]): number[];
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shared metrics chart series color assignment for web (CSS tokens) and Expo (hex palette).
3
+ * Same hash + collision strategy so labels map to the same slot index everywhere.
4
+ */
5
+ /** Matches PrimeVue semantic palette slot count (cyan…blue) and Expo SERIES_COLORS length */
6
+ export declare const METRICS_SERIES_PALETTE_SIZE = 10;
7
+ /**
8
+ * FNV-1a 32-bit hash — stable palette index for a string key.
9
+ */
10
+ export declare function hashStringToColorIndex(str: string): number;
11
+ /**
12
+ * Prefer human-visible label so charts and tables agree on the same color key.
13
+ */
14
+ export declare function seriesColorKey(label: string | undefined, key: string): string;
15
+ /**
16
+ * Map each distinct key to a palette index (hash preference, then max-min circular spacing).
17
+ */
18
+ export declare function resolveSeriesColorMap(keys: string[]): Map<string, number>;
19
+ export type ResolveColorsByKeysResult = {
20
+ getColor: (key: string) => string;
21
+ getHoverColor: (key: string) => string;
22
+ };
23
+ /**
24
+ * Resolve stable colors per key using palette index → RGB/CSS from the caller.
25
+ */
26
+ export declare function createResolveColorsByKeys(keys: string[], getSeriesColor: (index: number) => string, getSeriesHoverColor: (index: number) => string): ResolveColorsByKeysResult;
27
+ /**
28
+ * Add alpha to hex, rgb(), or rgba() strings.
29
+ */
30
+ export declare function withAlpha(color: string, alpha: number): string;
31
+ /**
32
+ * Heatmap cell background from normalized value intensity.
33
+ */
34
+ export declare function getHeatmapCellStyle(params: {
35
+ value: number | null | undefined;
36
+ min: number;
37
+ max: number;
38
+ baseColor: string;
39
+ neutralColor?: string;
40
+ minAlpha?: number;
41
+ maxAlpha?: number;
42
+ }): Record<string, string>;
@@ -0,0 +1,95 @@
1
+ export type RunFunction = () => Promise<unknown> | unknown;
2
+ export type Queue<Element, Options> = {
3
+ size: number;
4
+ filter: (options: Readonly<Partial<Options>>) => Element[];
5
+ dequeue: () => Element | undefined;
6
+ enqueue: (run: Element, options?: Partial<Options>) => void;
7
+ setPriority: (id: string, priority: number) => void;
8
+ remove?: (id: string) => void;
9
+ };
10
+ export type TaskOptions = {
11
+ readonly signal?: AbortSignal | undefined;
12
+ };
13
+ type TimeoutOptions = {
14
+ timeout?: number;
15
+ };
16
+ export type QueueAddOptions = {
17
+ readonly priority?: number;
18
+ id?: string;
19
+ } & TaskOptions & TimeoutOptions;
20
+ export type Options<QueueType extends Queue<RunFunction, QueueOptions> = PriorityQueue, QueueOptions extends QueueAddOptions = QueueAddOptions> = {
21
+ readonly concurrency?: number;
22
+ readonly autoStart?: boolean;
23
+ readonly queueClass?: new () => QueueType;
24
+ readonly intervalCap?: number;
25
+ readonly interval?: number;
26
+ readonly carryoverIntervalCount?: boolean;
27
+ readonly carryoverConcurrencyCount?: boolean;
28
+ readonly strict?: boolean;
29
+ } & TimeoutOptions;
30
+ type Task<TaskResultType> = ((options: TaskOptions) => PromiseLike<TaskResultType>) | ((options: TaskOptions) => TaskResultType);
31
+ type EventMap = {
32
+ active: [];
33
+ idle: [];
34
+ empty: [];
35
+ add: [];
36
+ next: [];
37
+ completed: [unknown];
38
+ error: [unknown];
39
+ pendingZero: [];
40
+ rateLimit: [];
41
+ rateLimitCleared: [];
42
+ };
43
+ type EventName = keyof EventMap;
44
+ type Listener<Event extends EventName> = (...arguments_: EventMap[Event]) => void;
45
+ export declare class TimeoutError extends Error {
46
+ constructor(message: string);
47
+ }
48
+ export type PriorityQueueOptions = {
49
+ priority?: number;
50
+ } & QueueAddOptions;
51
+ export declare class PriorityQueue implements Queue<RunFunction, PriorityQueueOptions> {
52
+ #private;
53
+ enqueue(run: RunFunction, options?: Partial<PriorityQueueOptions>): void;
54
+ dequeue(): RunFunction | undefined;
55
+ filter(options: Readonly<Partial<PriorityQueueOptions>>): RunFunction[];
56
+ setPriority(id: string, priority: number): void;
57
+ remove(id: string): void;
58
+ get size(): number;
59
+ }
60
+ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsType> = PriorityQueue, EnqueueOptionsType extends QueueAddOptions = QueueAddOptions> {
61
+ #private;
62
+ timeout?: number;
63
+ constructor(options?: Options<QueueType, EnqueueOptionsType>);
64
+ on<Event extends EventName>(event: Event, listener: Listener<Event>): this;
65
+ off<Event extends EventName>(event: Event, listener: Listener<Event>): this;
66
+ emit<Event extends EventName>(event: Event, ...arguments_: EventMap[Event]): boolean;
67
+ get concurrency(): number;
68
+ set concurrency(newConcurrency: number);
69
+ get size(): number;
70
+ sizeBy(options: Readonly<Partial<EnqueueOptionsType>>): number;
71
+ get pending(): number;
72
+ get isPaused(): boolean;
73
+ get isRateLimited(): boolean;
74
+ get isSaturated(): boolean;
75
+ get runningTasks(): ReadonlyArray<{
76
+ readonly id?: string;
77
+ readonly priority: number;
78
+ readonly startTime: number;
79
+ readonly timeout?: number;
80
+ }>;
81
+ setPriority(id: string, priority: number): void;
82
+ add<TaskResultType>(function_: Task<TaskResultType>, options?: Partial<EnqueueOptionsType>): Promise<TaskResultType>;
83
+ addAll<TaskResultsType>(functions: ReadonlyArray<Task<TaskResultsType>>, options?: Partial<EnqueueOptionsType>): Promise<TaskResultsType[]>;
84
+ start(): this;
85
+ pause(): void;
86
+ clear(): void;
87
+ onEmpty(): Promise<void>;
88
+ onIdle(): Promise<void>;
89
+ onPendingZero(): Promise<void>;
90
+ onRateLimit(): Promise<void>;
91
+ onRateLimitCleared(): Promise<void>;
92
+ onError(): Promise<never>;
93
+ onSizeLessThan(limit: number): Promise<void>;
94
+ }
95
+ export {};
@@ -0,0 +1,439 @@
1
+ // src/p-queue/index.ts
2
+ class TimeoutError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "TimeoutError";
6
+ }
7
+ }
8
+
9
+ class PriorityQueue {
10
+ #queue = [];
11
+ enqueue(run, options = {}) {
12
+ const element = {
13
+ priority: options.priority ?? 0,
14
+ id: options.id,
15
+ run
16
+ };
17
+ const index = this.#queue.findIndex((item) => item.priority < element.priority);
18
+ if (index === -1) {
19
+ this.#queue.push(element);
20
+ return;
21
+ }
22
+ this.#queue.splice(index, 0, element);
23
+ }
24
+ dequeue() {
25
+ return this.#queue.shift()?.run;
26
+ }
27
+ filter(options) {
28
+ return this.#queue.filter((item) => Object.entries(options).every(([key, value]) => item[key] === value)).map((item) => item.run);
29
+ }
30
+ setPriority(id, priority) {
31
+ const index = this.#queue.findIndex((item2) => item2.id === id);
32
+ if (index === -1) {
33
+ throw new ReferenceError(`No promise function with the id "${id}" exists in the queue.`);
34
+ }
35
+ const [item] = this.#queue.splice(index, 1);
36
+ this.enqueue(item.run, { ...item, priority });
37
+ }
38
+ remove(id) {
39
+ const index = this.#queue.findIndex((item) => item.id === id);
40
+ if (index !== -1) {
41
+ this.#queue.splice(index, 1);
42
+ }
43
+ }
44
+ get size() {
45
+ return this.#queue.length;
46
+ }
47
+ }
48
+
49
+ class PQueue {
50
+ #listeners = new Map;
51
+ #queue;
52
+ #queueClass;
53
+ #pending = 0;
54
+ #concurrency;
55
+ #isPaused;
56
+ #intervalCap;
57
+ #interval;
58
+ #carryoverIntervalCount;
59
+ #strict;
60
+ #intervalCount = 0;
61
+ #intervalEnd = 0;
62
+ #intervalTimer;
63
+ #strictTimestamps = [];
64
+ #rateLimited = false;
65
+ #idCounter = 1n;
66
+ #runningTasks = new Map;
67
+ timeout;
68
+ constructor(options = {}) {
69
+ const {
70
+ concurrency = Number.POSITIVE_INFINITY,
71
+ autoStart = true,
72
+ queueClass = PriorityQueue,
73
+ intervalCap = Number.POSITIVE_INFINITY,
74
+ interval = 0,
75
+ carryoverIntervalCount,
76
+ carryoverConcurrencyCount,
77
+ strict = false,
78
+ timeout
79
+ } = options;
80
+ if (!(typeof concurrency === "number" && concurrency >= 1)) {
81
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
82
+ }
83
+ if (!(typeof intervalCap === "number" && intervalCap >= 1)) {
84
+ throw new TypeError("Expected `intervalCap` to be a number from 1 and up");
85
+ }
86
+ if (!(typeof interval === "number" && Number.isFinite(interval) && interval >= 0)) {
87
+ throw new TypeError("Expected `interval` to be a finite number >= 0");
88
+ }
89
+ if (strict && interval === 0) {
90
+ throw new TypeError("The `strict` option requires a non-zero `interval`");
91
+ }
92
+ if (strict && intervalCap === Number.POSITIVE_INFINITY) {
93
+ throw new TypeError("The `strict` option requires a finite `intervalCap`");
94
+ }
95
+ if (timeout !== undefined && !(Number.isFinite(timeout) && timeout > 0)) {
96
+ throw new TypeError("Expected `timeout` to be a positive finite number");
97
+ }
98
+ this.#queueClass = queueClass;
99
+ this.#queue = new queueClass;
100
+ this.#concurrency = concurrency;
101
+ this.#isPaused = !autoStart;
102
+ this.#intervalCap = intervalCap;
103
+ this.#interval = interval;
104
+ this.#carryoverIntervalCount = carryoverIntervalCount ?? carryoverConcurrencyCount ?? false;
105
+ this.#strict = strict;
106
+ this.timeout = timeout;
107
+ }
108
+ on(event, listener) {
109
+ const listeners = this.#listeners.get(event) ?? new Set;
110
+ listeners.add(listener);
111
+ this.#listeners.set(event, listeners);
112
+ return this;
113
+ }
114
+ off(event, listener) {
115
+ this.#listeners.get(event)?.delete(listener);
116
+ return this;
117
+ }
118
+ emit(event, ...arguments_) {
119
+ const listeners = this.#listeners.get(event);
120
+ if (!listeners || listeners.size === 0) {
121
+ return false;
122
+ }
123
+ for (const listener of [...listeners]) {
124
+ listener(...arguments_);
125
+ }
126
+ return true;
127
+ }
128
+ get concurrency() {
129
+ return this.#concurrency;
130
+ }
131
+ set concurrency(newConcurrency) {
132
+ if (!(typeof newConcurrency === "number" && newConcurrency >= 1)) {
133
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
134
+ }
135
+ this.#concurrency = newConcurrency;
136
+ this.#processQueue();
137
+ }
138
+ get size() {
139
+ return this.#queue.size;
140
+ }
141
+ sizeBy(options) {
142
+ return this.#queue.filter(options).length;
143
+ }
144
+ get pending() {
145
+ return this.#pending;
146
+ }
147
+ get isPaused() {
148
+ return this.#isPaused;
149
+ }
150
+ get isRateLimited() {
151
+ this.#updateRateLimitState();
152
+ return this.#rateLimited;
153
+ }
154
+ get isSaturated() {
155
+ return this.#pending >= this.#concurrency && this.#queue.size > 0 || this.isRateLimited && this.#queue.size > 0;
156
+ }
157
+ get runningTasks() {
158
+ return [...this.#runningTasks.values()].map((task) => ({ ...task }));
159
+ }
160
+ setPriority(id, priority) {
161
+ if (typeof priority !== "number" || !Number.isFinite(priority)) {
162
+ throw new TypeError("Expected `priority` to be a finite number");
163
+ }
164
+ this.#queue.setPriority(id, priority);
165
+ }
166
+ async add(function_, options = {}) {
167
+ const taskOptions = {
168
+ timeout: this.timeout,
169
+ ...options,
170
+ id: options.id ?? (this.#idCounter++).toString()
171
+ };
172
+ return new Promise((resolve, reject) => {
173
+ const taskSymbol = Symbol(taskOptions.id);
174
+ let didRun = false;
175
+ let queuedAbortHandler;
176
+ let runningAbortHandler;
177
+ const cleanupQueuedAbort = () => {
178
+ if (queuedAbortHandler) {
179
+ taskOptions.signal?.removeEventListener("abort", queuedAbortHandler);
180
+ queuedAbortHandler = undefined;
181
+ }
182
+ };
183
+ const run = async () => {
184
+ didRun = true;
185
+ cleanupQueuedAbort();
186
+ this.#pending++;
187
+ this.#runningTasks.set(taskSymbol, {
188
+ id: taskOptions.id,
189
+ priority: taskOptions.priority ?? 0,
190
+ startTime: Date.now(),
191
+ timeout: taskOptions.timeout
192
+ });
193
+ try {
194
+ taskOptions.signal?.throwIfAborted();
195
+ const operation = Promise.resolve(function_({ signal: taskOptions.signal }));
196
+ const result = await this.#withTimeoutAndAbort(operation, taskOptions, (listener) => {
197
+ runningAbortHandler = listener;
198
+ });
199
+ resolve(result);
200
+ this.emit("completed", result);
201
+ } catch (error) {
202
+ reject(error);
203
+ this.emit("error", error);
204
+ } finally {
205
+ if (runningAbortHandler) {
206
+ taskOptions.signal?.removeEventListener("abort", runningAbortHandler);
207
+ }
208
+ this.#runningTasks.delete(taskSymbol);
209
+ queueMicrotask(() => {
210
+ this.#next();
211
+ });
212
+ }
213
+ };
214
+ if (taskOptions.signal?.aborted) {
215
+ reject(taskOptions.signal.reason);
216
+ return;
217
+ }
218
+ if (taskOptions.signal) {
219
+ queuedAbortHandler = () => {
220
+ if (didRun) {
221
+ return;
222
+ }
223
+ this.#queue.remove?.(taskOptions.id);
224
+ reject(taskOptions.signal?.reason);
225
+ this.emit("next");
226
+ this.#tryToStartAnother();
227
+ };
228
+ taskOptions.signal.addEventListener("abort", queuedAbortHandler, {
229
+ once: true
230
+ });
231
+ }
232
+ this.#queue.enqueue(run, taskOptions);
233
+ this.emit("add");
234
+ this.#processQueue();
235
+ });
236
+ }
237
+ async addAll(functions, options) {
238
+ return Promise.all(functions.map(async (function_) => this.add(function_, options)));
239
+ }
240
+ start() {
241
+ if (!this.#isPaused) {
242
+ return this;
243
+ }
244
+ this.#isPaused = false;
245
+ this.#processQueue();
246
+ return this;
247
+ }
248
+ pause() {
249
+ this.#isPaused = true;
250
+ }
251
+ clear() {
252
+ this.#queue = new this.#queueClass;
253
+ this.#clearIntervalTimer();
254
+ this.#updateRateLimitState();
255
+ this.emit("empty");
256
+ if (this.#pending === 0) {
257
+ this.emit("idle");
258
+ }
259
+ this.emit("next");
260
+ }
261
+ async onEmpty() {
262
+ if (this.#queue.size === 0) {
263
+ return;
264
+ }
265
+ await this.#onEvent("empty");
266
+ }
267
+ async onIdle() {
268
+ if (this.#queue.size === 0 && this.#pending === 0) {
269
+ return;
270
+ }
271
+ await this.#onEvent("idle");
272
+ }
273
+ async onPendingZero() {
274
+ if (this.#pending === 0) {
275
+ return;
276
+ }
277
+ await this.#onEvent("pendingZero");
278
+ }
279
+ async onRateLimit() {
280
+ if (this.isRateLimited) {
281
+ return;
282
+ }
283
+ await this.#onEvent("rateLimit");
284
+ }
285
+ async onRateLimitCleared() {
286
+ if (!this.isRateLimited) {
287
+ return;
288
+ }
289
+ await this.#onEvent("rateLimitCleared");
290
+ }
291
+ onError() {
292
+ return new Promise((_resolve, reject) => {
293
+ const listener = (error) => {
294
+ this.off("error", listener);
295
+ reject(error);
296
+ };
297
+ this.on("error", listener);
298
+ });
299
+ }
300
+ async onSizeLessThan(limit) {
301
+ if (this.#queue.size < limit) {
302
+ return;
303
+ }
304
+ await this.#onEvent("next", () => this.#queue.size < limit);
305
+ }
306
+ async#onEvent(event, filter) {
307
+ return new Promise((resolve) => {
308
+ const listener = () => {
309
+ if (filter && !filter()) {
310
+ return;
311
+ }
312
+ this.off(event, listener);
313
+ resolve();
314
+ };
315
+ this.on(event, listener);
316
+ });
317
+ }
318
+ async#withTimeoutAndAbort(operation, options, setAbortListener) {
319
+ const races = [operation];
320
+ let timeoutId;
321
+ if (options.timeout) {
322
+ races.push(new Promise((_resolve, reject) => {
323
+ timeoutId = setTimeout(() => {
324
+ reject(new TimeoutError(`Task timed out after ${options.timeout}ms`));
325
+ }, options.timeout);
326
+ }));
327
+ }
328
+ if (options.signal) {
329
+ races.push(new Promise((_resolve, reject) => {
330
+ const listener = () => {
331
+ reject(options.signal?.reason);
332
+ };
333
+ setAbortListener(listener);
334
+ options.signal?.addEventListener("abort", listener, { once: true });
335
+ }));
336
+ }
337
+ try {
338
+ return await Promise.race(races);
339
+ } finally {
340
+ if (timeoutId) {
341
+ clearTimeout(timeoutId);
342
+ }
343
+ }
344
+ }
345
+ #next() {
346
+ this.#pending--;
347
+ if (this.#pending === 0) {
348
+ this.emit("pendingZero");
349
+ }
350
+ this.#processQueue();
351
+ this.emit("next");
352
+ }
353
+ #processQueue() {
354
+ while (this.#tryToStartAnother()) {}
355
+ this.#updateRateLimitState();
356
+ }
357
+ #tryToStartAnother() {
358
+ if (this.#queue.size === 0) {
359
+ this.#clearIntervalTimer();
360
+ this.emit("empty");
361
+ if (this.#pending === 0) {
362
+ this.emit("idle");
363
+ }
364
+ return false;
365
+ }
366
+ if (this.#isPaused || this.#pending >= this.#concurrency || !this.#doesIntervalAllowAnother()) {
367
+ return false;
368
+ }
369
+ const job = this.#queue.dequeue();
370
+ if (!job) {
371
+ return false;
372
+ }
373
+ this.#consumeIntervalSlot();
374
+ this.emit("active");
375
+ job();
376
+ return true;
377
+ }
378
+ #doesIntervalAllowAnother() {
379
+ if (this.#intervalCap === Number.POSITIVE_INFINITY || this.#interval === 0) {
380
+ return true;
381
+ }
382
+ const now = Date.now();
383
+ if (this.#strict) {
384
+ this.#strictTimestamps = this.#strictTimestamps.filter((timestamp) => now - timestamp < this.#interval);
385
+ if (this.#strictTimestamps.length < this.#intervalCap) {
386
+ return true;
387
+ }
388
+ this.#scheduleIntervalResume(this.#interval - (now - this.#strictTimestamps[0]));
389
+ return false;
390
+ }
391
+ if (this.#intervalEnd === 0 || now >= this.#intervalEnd) {
392
+ this.#intervalCount = this.#carryoverIntervalCount ? this.#pending : 0;
393
+ this.#intervalEnd = now + this.#interval;
394
+ }
395
+ if (this.#intervalCount < this.#intervalCap) {
396
+ return true;
397
+ }
398
+ this.#scheduleIntervalResume(this.#intervalEnd - now);
399
+ return false;
400
+ }
401
+ #consumeIntervalSlot() {
402
+ if (this.#intervalCap === Number.POSITIVE_INFINITY || this.#interval === 0) {
403
+ return;
404
+ }
405
+ if (this.#strict) {
406
+ this.#strictTimestamps.push(Date.now());
407
+ return;
408
+ }
409
+ this.#intervalCount++;
410
+ }
411
+ #scheduleIntervalResume(delay) {
412
+ if (this.#intervalTimer) {
413
+ return;
414
+ }
415
+ this.#intervalTimer = setTimeout(() => {
416
+ this.#intervalTimer = undefined;
417
+ this.#processQueue();
418
+ }, Math.max(0, delay));
419
+ }
420
+ #clearIntervalTimer() {
421
+ if (this.#intervalTimer) {
422
+ clearTimeout(this.#intervalTimer);
423
+ this.#intervalTimer = undefined;
424
+ }
425
+ }
426
+ #updateRateLimitState() {
427
+ const previous = this.#rateLimited;
428
+ const isRateLimited = this.#queue.size > 0 && this.#intervalCap !== Number.POSITIVE_INFINITY && this.#interval > 0 && !this.#doesIntervalAllowAnother();
429
+ this.#rateLimited = isRateLimited;
430
+ if (previous !== isRateLimited) {
431
+ this.emit(isRateLimited ? "rateLimit" : "rateLimitCleared");
432
+ }
433
+ }
434
+ }
435
+ export {
436
+ PQueue as default,
437
+ TimeoutError,
438
+ PriorityQueue
439
+ };
@@ -0,0 +1,21 @@
1
+ export type BackgroundPromiseOptions = {
2
+ onError?: (error: unknown) => void;
3
+ onSuccess?: () => void;
4
+ scheduler?: (callback: () => void) => void;
5
+ };
6
+ export type Success<T> = {
7
+ data: T;
8
+ error: null;
9
+ };
10
+ export type Failure<E> = {
11
+ data: null;
12
+ error: E;
13
+ };
14
+ export type Result<T, E = Error> = Success<T> | Failure<E>;
15
+ export declare function isSuccess<T, E>(result: Result<T, E>): result is Success<T>;
16
+ export declare function isFailure<T, E>(result: Result<T, E>): result is Failure<E>;
17
+ export declare function unwrapResult<T, E>(result: Result<T, E>): T;
18
+ export declare function backgroundPromise<T>(promiseFactory: () => Promise<T>, options?: BackgroundPromiseOptions): void;
19
+ export declare function backgroundPromiseSync<T>(promiseFactory: () => Promise<T>, options?: BackgroundPromiseOptions): void;
20
+ export declare function promiseTimeout(ms: number): Promise<void>;
21
+ export declare function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>>;
@@ -0,0 +1,14 @@
1
+ interface SitemapOptions {
2
+ filterIndexes?: string;
3
+ concurrency?: number;
4
+ maxDepth?: number;
5
+ timeout?: number;
6
+ }
7
+ /**
8
+ * Gets all URLs from a domain by discovering and crawling its sitemaps
9
+ * @param domain - The root domain (e.g., 'https://example.com')
10
+ * @param options - Configuration options for the crawler
11
+ * @returns Promise<string[]> - Array of unique URLs found in the sitemap
12
+ */
13
+ export declare const getDomainSitemap: (domain: string, options?: SitemapOptions) => Promise<string[]>;
14
+ export {};