ttc-rate-limit 0.1.7 → 0.1.9
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/cluster.d.ts +10 -2
- package/dist/cluster.d.ts.map +1 -1
- package/dist/cluster.js +8 -7
- package/dist/cluster.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ratelimit.d.ts +98 -17
- package/dist/ratelimit.d.ts.map +1 -1
- package/dist/ratelimit.js +150 -49
- package/dist/ratelimit.js.map +1 -1
- package/dist/test.js +20 -5
- package/dist/test.js.map +1 -1
- package/dist/time.d.ts +7 -0
- package/dist/time.d.ts.map +1 -1
- package/dist/time.js +16 -0
- package/dist/time.js.map +1 -1
- package/package.json +1 -1
package/dist/cluster.d.ts
CHANGED
|
@@ -10,10 +10,18 @@ export declare class Cluster<T, R> {
|
|
|
10
10
|
constructor(type: 'random' | 'roundrobin');
|
|
11
11
|
on: (event: "completed" | "error", listener: (data: {
|
|
12
12
|
request: T;
|
|
13
|
-
response:
|
|
13
|
+
response: R;
|
|
14
|
+
config: {
|
|
15
|
+
_urId: string;
|
|
16
|
+
retryCount: number;
|
|
17
|
+
};
|
|
14
18
|
}) => void) => void;
|
|
15
19
|
addOption: (config: RateLimiterConfig<T, R>, specific?: boolean) => this;
|
|
16
|
-
invoke: (item: T,
|
|
20
|
+
invoke: (item: T, config?: {
|
|
21
|
+
preferredLimiterId?: string;
|
|
22
|
+
_urId?: string;
|
|
23
|
+
retryCount?: number;
|
|
24
|
+
}) => Promise<void>;
|
|
17
25
|
randomLimiter: () => RateLimiter<T, R>;
|
|
18
26
|
}
|
|
19
27
|
//# sourceMappingURL=cluster.d.ts.map
|
package/dist/cluster.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../src/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,qBAAa,OAAO,CAAC,CAAC,EAAE,CAAC;IAErB,MAAM,EAAE;QACJ,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;QAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAsB;IAEvB,OAAO,EAAE,YAAY,CAAsB;IAE3C,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAM;gBAEvB,IAAI,EAAE,QAAQ,GAAG,YAAY;IAMzC,EAAE,GAAI,OAAO,WAAW,GAAG,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../src/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,qBAAa,OAAO,CAAC,CAAC,EAAE,CAAC;IAErB,MAAM,EAAE;QACJ,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;QAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAsB;IAEvB,OAAO,EAAE,YAAY,CAAsB;IAE3C,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAM;gBAEvB,IAAI,EAAE,QAAQ,GAAG,YAAY;IAMzC,EAAE,GAAI,OAAO,WAAW,GAAG,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE;YACpF,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,MAAM,CAAC;SACtB,CAAA;KAAE,KAAK,IAAI,UAEX;IAED,SAAS,GAAI,QAAQ,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAU,OAAe,UAWtE;IAED,MAAM,GAAU,MAAM,CAAC,EAAE,SAAQ;QAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,KAAG,OAAO,CAAC,IAAI,CAAC,CA4BhB;IAED,aAAa,QAAO,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAGpC;CACJ"}
|
package/dist/cluster.js
CHANGED
|
@@ -23,11 +23,11 @@ class Cluster {
|
|
|
23
23
|
});
|
|
24
24
|
return this;
|
|
25
25
|
};
|
|
26
|
-
this.invoke = async (item,
|
|
26
|
+
this.invoke = async (item, config) => {
|
|
27
27
|
try {
|
|
28
28
|
let limiter;
|
|
29
|
-
if (preferredLimiterId) {
|
|
30
|
-
limiter = this.limiters.find(l => l.config.id === preferredLimiterId);
|
|
29
|
+
if (config?.preferredLimiterId) {
|
|
30
|
+
limiter = this.limiters.find(l => l.config.id === config.preferredLimiterId);
|
|
31
31
|
if (!limiter) {
|
|
32
32
|
limiter = this.randomLimiter();
|
|
33
33
|
}
|
|
@@ -42,14 +42,15 @@ class Cluster {
|
|
|
42
42
|
else {
|
|
43
43
|
limiter = this.limiters[0];
|
|
44
44
|
}
|
|
45
|
-
await limiter.invoke(item);
|
|
45
|
+
await limiter.invoke(item, config);
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const count = config?.retryCount || 0;
|
|
49
|
+
if (count >= 3) {
|
|
50
|
+
this.emitter.emit('error', { request: item, response: error.message });
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
|
-
return await this.invoke(item,
|
|
53
|
+
return await this.invoke(item, { ...config, retryCount: count + 1 });
|
|
53
54
|
}
|
|
54
55
|
};
|
|
55
56
|
this.randomLimiter = () => {
|
package/dist/cluster.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../src/cluster.ts"],"names":[],"mappings":";;;AAAA,2CAA6D;AAC7D,mCAAsC;AAEtC,MAAa,OAAO;IAWhB,YAAY,IAA6B;QATzC,WAAM,GAGF,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAEvB,YAAO,GAAiB,IAAI,qBAAY,EAAE,CAAC;QAE3C,aAAQ,GAAwB,EAAE,CAAC;QAQnC,OAAE,GAAG,CAAC,KAA4B,EAAE,
|
|
1
|
+
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../src/cluster.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAkE;AAAzD,wGAAA,WAAW,OAAA;AACpB,+BAAqC;AAA5B,mGAAA,WAAW,OAAA;AACpB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA"}
|
package/dist/ratelimit.d.ts
CHANGED
|
@@ -1,44 +1,125 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
2
|
import { TimeCluster } from "./time";
|
|
3
3
|
export declare const time: TimeCluster;
|
|
4
|
+
/**
|
|
5
|
+
* Configuration interface for the RateLimiter.
|
|
6
|
+
* @template T - The type of the input to the callback function.
|
|
7
|
+
* @template R - The type of the return value from the callback function.
|
|
8
|
+
*/
|
|
4
9
|
export interface RateLimiterConfig<T, R> {
|
|
10
|
+
/** Unique identifier for the rate limiter instance. */
|
|
5
11
|
id: string;
|
|
12
|
+
/** Number of requests allowed per time period. */
|
|
6
13
|
request: number;
|
|
14
|
+
/** Time period for the rate limit ('second', 'minute', 'hour', 'day'). */
|
|
7
15
|
per: 'second' | 'minute' | 'hour' | 'day';
|
|
16
|
+
/** Optional interval in seconds (calculated internally). */
|
|
8
17
|
interval?: number;
|
|
18
|
+
/** Callback function to execute for each request. */
|
|
9
19
|
cb: (input: T, limiterId: string) => Promise<R>;
|
|
20
|
+
/** Internal counter for requests (managed by the limiter). */
|
|
10
21
|
_count?: number;
|
|
22
|
+
/** Requests per second (calculated internally). */
|
|
11
23
|
rps?: number;
|
|
24
|
+
/** Internal timestamp marker for window tracking (managed by the limiter). */
|
|
12
25
|
_Tmarker?: number;
|
|
26
|
+
/** Mode of rate limiting: 'spread', 'burst', or 'hybrid'. */
|
|
13
27
|
mode: 'spread' | 'burst' | 'hybrid';
|
|
28
|
+
/** Maximum number of retries for failed requests. */
|
|
29
|
+
maxRetry?: number;
|
|
30
|
+
/** Ratio for hybrid mode (bursts in interval/ratio seconds with request/ratio calls). */
|
|
14
31
|
hybridRatio?: number;
|
|
15
32
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
/** Internal type for queue items. */
|
|
34
|
+
type RequestCacheItem<T> = {
|
|
35
|
+
input: T;
|
|
36
|
+
_urId: string;
|
|
37
|
+
retryCount: number;
|
|
19
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* A flexible rate limiter supporting spread, burst, and hybrid modes with event-driven architecture,
|
|
41
|
+
* automatic retries, and exponential back-off.
|
|
42
|
+
* @template T - The type of the input to the callback function.
|
|
43
|
+
* @template R - The type of the return value from the callback function.
|
|
44
|
+
*/
|
|
20
45
|
export declare class RateLimiter<T, R> {
|
|
46
|
+
/** The configuration for the rate limiter. */
|
|
21
47
|
config: RateLimiterConfig<T, R>;
|
|
22
|
-
queue
|
|
48
|
+
/** The main queue for pending requests. */
|
|
49
|
+
queue: Record<string, RequestCacheItem<T>>;
|
|
50
|
+
/** The back-off queue for retrying failed requests. */
|
|
51
|
+
back_off_queue: Record<string, RequestCacheItem<T>>;
|
|
52
|
+
/** Event manager for handling 'completed' and 'error' events. */
|
|
23
53
|
eventManager: EventEmitter;
|
|
54
|
+
/** The current state of the queue processing. */
|
|
55
|
+
_queueState: 'idle' | 'processing' | 'waiting';
|
|
56
|
+
/**
|
|
57
|
+
* Creates a new RateLimiter instance.
|
|
58
|
+
* @param config - The configuration for the rate limiter.
|
|
59
|
+
*/
|
|
24
60
|
constructor(config: RateLimiterConfig<T, R>);
|
|
61
|
+
/**
|
|
62
|
+
* Internal method to resolve and set up the rate limiter configuration.
|
|
63
|
+
*/
|
|
25
64
|
_resolve(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Registers an event listener for 'completed' or 'error' events.
|
|
67
|
+
* @param event - The event type to listen for.
|
|
68
|
+
* @param listener - The callback function for the event.
|
|
69
|
+
*/
|
|
26
70
|
on: (event: "completed" | "error", listener: (data: {
|
|
27
71
|
request: T;
|
|
28
72
|
response: any;
|
|
73
|
+
config?: any;
|
|
29
74
|
}) => void) => void;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Processes the queue of pending requests based on the configured mode.
|
|
77
|
+
*/
|
|
78
|
+
processQueue: () => Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Handles errors for a request, implementing retry logic with back-off.
|
|
81
|
+
* @param id - The unique ID of the request.
|
|
82
|
+
* @param input - The input data for the request.
|
|
83
|
+
* @param error - The error that occurred.
|
|
84
|
+
*/
|
|
85
|
+
handleError(id: string, input: T, error: any): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Implements the spread algorithm for rate limiting.
|
|
88
|
+
* @param input - The input data for the request.
|
|
89
|
+
* @param id - The unique ID of the request.
|
|
90
|
+
*/
|
|
91
|
+
spreadAlgorithm(input: T, id: string): Promise<{
|
|
92
|
+
status: string;
|
|
93
|
+
} | undefined>;
|
|
94
|
+
/**
|
|
95
|
+
* Implements the burst algorithm for rate limiting.
|
|
96
|
+
* @param input - The input data for the request.
|
|
97
|
+
* @param id - The unique ID of the request.
|
|
98
|
+
*/
|
|
99
|
+
burstAlgorithm(input: T, id: string): Promise<{
|
|
100
|
+
status: string;
|
|
101
|
+
} | undefined>;
|
|
102
|
+
/**
|
|
103
|
+
* Processes a single request using the appropriate algorithm.
|
|
104
|
+
* @param input - The input data for the request.
|
|
105
|
+
* @param id - The unique ID of the request.
|
|
106
|
+
*/
|
|
107
|
+
process(input: T, id: string): Promise<{
|
|
108
|
+
status: string;
|
|
109
|
+
} | undefined>;
|
|
110
|
+
/**
|
|
111
|
+
* Invokes a new request, adding it to the queue if necessary.
|
|
112
|
+
* @param input - The input data for the request.
|
|
113
|
+
* @param config - Optional configuration for the request.
|
|
114
|
+
*/
|
|
115
|
+
invoke(input: T, config?: {
|
|
116
|
+
preferredLimiterId?: string;
|
|
117
|
+
_urId?: string;
|
|
118
|
+
retryCount?: number;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
status: string;
|
|
121
|
+
message: string;
|
|
122
|
+
} | undefined>;
|
|
43
123
|
}
|
|
124
|
+
export {};
|
|
44
125
|
//# sourceMappingURL=ratelimit.d.ts.map
|
package/dist/ratelimit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ratelimit.d.ts","sourceRoot":"","sources":["../src/ratelimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAO,MAAM,IAAI,aAAsB,CAAC;AAExC,MAAM,WAAW,iBAAiB,CAAC,CAAC,EAAE,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ratelimit.d.ts","sourceRoot":"","sources":["../src/ratelimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAO,MAAM,IAAI,aAAsB,CAAC;AAExC;;;;GAIG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,EAAE,CAAC;IACnC,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,GAAG,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;IAC1C,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChD,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAGD,qCAAqC;AACrC,KAAK,gBAAgB,CAAC,CAAC,IAAI;IACvB,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,WAAW,CAAC,CAAC,EAAE,CAAC;IAEzB,8CAA8C;IAC9C,MAAM,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAM;IAChD,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAM;IACzD,iEAAiE;IACjE,YAAY,EAAE,YAAY,CAAC;IAC3B,iDAAiD;IACjD,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAU;IACxD;;;OAGG;gBACS,MAAM,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC;IAM3C;;OAEG;IACH,QAAQ;IA4BR;;;;OAIG;IACH,EAAE,GAAI,OAAO,WAAW,GAAG,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE;QACjD,OAAO,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,CAAA;KAC1C,KAAK,IAAI,UAET;IAED;;OAEG;IACH,YAAY,sBA0CX;IAED;;;;;OAKG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG;IA2BlD;;;;OAIG;IACG,eAAe,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM;;;IA8B1C;;;;OAIG;IACG,cAAc,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM;;;IA2DzC;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM;;;IAelC;;;;OAIG;IACG,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE;QAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB;;;;CAoBJ"}
|
package/dist/ratelimit.js
CHANGED
|
@@ -4,16 +4,84 @@ exports.RateLimiter = exports.time = void 0;
|
|
|
4
4
|
const events_1 = require("events");
|
|
5
5
|
const time_1 = require("./time");
|
|
6
6
|
exports.time = new time_1.TimeCluster(20);
|
|
7
|
+
/**
|
|
8
|
+
* A flexible rate limiter supporting spread, burst, and hybrid modes with event-driven architecture,
|
|
9
|
+
* automatic retries, and exponential back-off.
|
|
10
|
+
* @template T - The type of the input to the callback function.
|
|
11
|
+
* @template R - The type of the return value from the callback function.
|
|
12
|
+
*/
|
|
7
13
|
class RateLimiter {
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new RateLimiter instance.
|
|
16
|
+
* @param config - The configuration for the rate limiter.
|
|
17
|
+
*/
|
|
8
18
|
constructor(config) {
|
|
9
|
-
|
|
19
|
+
/** The main queue for pending requests. */
|
|
20
|
+
this.queue = {};
|
|
21
|
+
/** The back-off queue for retrying failed requests. */
|
|
22
|
+
this.back_off_queue = {};
|
|
23
|
+
/** The current state of the queue processing. */
|
|
24
|
+
this._queueState = 'idle';
|
|
25
|
+
/**
|
|
26
|
+
* Registers an event listener for 'completed' or 'error' events.
|
|
27
|
+
* @param event - The event type to listen for.
|
|
28
|
+
* @param listener - The callback function for the event.
|
|
29
|
+
*/
|
|
10
30
|
this.on = (event, listener) => {
|
|
11
31
|
this.eventManager.on(event, listener);
|
|
12
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Processes the queue of pending requests based on the configured mode.
|
|
35
|
+
*/
|
|
36
|
+
this.processQueue = async () => {
|
|
37
|
+
let queueIds = Object.keys(this.queue);
|
|
38
|
+
if (queueIds.length === 0) {
|
|
39
|
+
this._queueState = 'idle';
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this._queueState = 'processing';
|
|
43
|
+
if (this.config.mode === 'spread') {
|
|
44
|
+
while (queueIds.length > 0 && this.config._count < this.config.rps) {
|
|
45
|
+
const id = queueIds[0];
|
|
46
|
+
const item = this.queue[id];
|
|
47
|
+
await this.process(item.input, id);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
while (queueIds.length > 0) {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
const windowMs = this.config.interval * 1000;
|
|
54
|
+
// Reset if window expired
|
|
55
|
+
if (this.config._Tmarker && now - this.config._Tmarker >= windowMs) {
|
|
56
|
+
this.config._count = 0;
|
|
57
|
+
this.config._Tmarker = now;
|
|
58
|
+
}
|
|
59
|
+
// If we have capacity in current window
|
|
60
|
+
if (this.config._count < this.config.request) {
|
|
61
|
+
const id = queueIds[0];
|
|
62
|
+
const item = this.queue[id];
|
|
63
|
+
if (item) {
|
|
64
|
+
await this.process(item.input, id);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
queueIds = Object.keys(this.queue);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Wait for window reset
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
this._queueState = 'idle';
|
|
77
|
+
};
|
|
13
78
|
this.config = config;
|
|
14
79
|
this._resolve();
|
|
15
80
|
this.eventManager = new events_1.EventEmitter();
|
|
16
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Internal method to resolve and set up the rate limiter configuration.
|
|
84
|
+
*/
|
|
17
85
|
_resolve() {
|
|
18
86
|
const intervals = {
|
|
19
87
|
'second': 1,
|
|
@@ -34,37 +102,52 @@ class RateLimiter {
|
|
|
34
102
|
this.config.request = Math.ceil(this.config.request / (this.config.hybridRatio ?? 2));
|
|
35
103
|
}
|
|
36
104
|
this.config._count = 0;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
await this.invoke(item);
|
|
105
|
+
this.config.maxRetry = this.config.maxRetry || 3;
|
|
106
|
+
exports.time.intervalFor(async () => {
|
|
107
|
+
this.queue = { ...this.queue, ...this.back_off_queue };
|
|
108
|
+
this.back_off_queue = {};
|
|
109
|
+
if (this._queueState === 'idle') {
|
|
110
|
+
await this.processQueue();
|
|
44
111
|
}
|
|
112
|
+
}, 2);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handles errors for a request, implementing retry logic with back-off.
|
|
116
|
+
* @param id - The unique ID of the request.
|
|
117
|
+
* @param input - The input data for the request.
|
|
118
|
+
* @param error - The error that occurred.
|
|
119
|
+
*/
|
|
120
|
+
async handleError(id, input, error) {
|
|
121
|
+
const item = this.queue[id];
|
|
122
|
+
// if(!item) {
|
|
123
|
+
// console.log(input);
|
|
124
|
+
// return;
|
|
125
|
+
// }
|
|
126
|
+
if (item.retryCount < (this.config.maxRetry || 3)) {
|
|
127
|
+
delete this.queue[id];
|
|
128
|
+
item.retryCount++;
|
|
129
|
+
this.back_off_queue[id] = item;
|
|
130
|
+
// console.log(this.back_off_queue);
|
|
45
131
|
}
|
|
46
132
|
else {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
// If we have capacity in current window
|
|
56
|
-
if (this.config._count < this.config.request) {
|
|
57
|
-
const item = this.queue.shift();
|
|
58
|
-
await this.invoke(item);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
// Wait for window reset
|
|
62
|
-
break;
|
|
133
|
+
delete this.queue[id];
|
|
134
|
+
this.eventManager.emit('error', {
|
|
135
|
+
request: input,
|
|
136
|
+
response: error.message,
|
|
137
|
+
config: {
|
|
138
|
+
retryCount: item.retryCount,
|
|
139
|
+
_urId: id
|
|
63
140
|
}
|
|
64
|
-
}
|
|
141
|
+
});
|
|
142
|
+
// console.log(this.queue, this.back_off_queue)
|
|
65
143
|
}
|
|
66
144
|
}
|
|
67
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Implements the spread algorithm for rate limiting.
|
|
147
|
+
* @param input - The input data for the request.
|
|
148
|
+
* @param id - The unique ID of the request.
|
|
149
|
+
*/
|
|
150
|
+
async spreadAlgorithm(input, id) {
|
|
68
151
|
if (this.config._count < this.config.rps) {
|
|
69
152
|
this.config._count++;
|
|
70
153
|
if (this.config._count >= this.config.rps) {
|
|
@@ -72,32 +155,32 @@ class RateLimiter {
|
|
|
72
155
|
this.config._count = 0;
|
|
73
156
|
await this.processQueue();
|
|
74
157
|
}, this.config.interval);
|
|
158
|
+
this._queueState = 'waiting';
|
|
75
159
|
}
|
|
76
160
|
try {
|
|
77
161
|
const response = await this.config.cb(input, this.config.id);
|
|
162
|
+
delete this.queue[id];
|
|
78
163
|
this.eventManager.emit('completed', {
|
|
79
164
|
request: input,
|
|
80
165
|
response
|
|
81
166
|
});
|
|
82
|
-
return {
|
|
83
|
-
status: 'success',
|
|
84
|
-
};
|
|
85
167
|
}
|
|
86
168
|
catch (error) {
|
|
87
|
-
|
|
88
|
-
status: 'error',
|
|
89
|
-
message: error.message
|
|
90
|
-
};
|
|
169
|
+
await this.handleError(id, input, error);
|
|
91
170
|
}
|
|
92
171
|
}
|
|
93
172
|
else {
|
|
94
|
-
this.queue.push(input);
|
|
95
173
|
return {
|
|
96
174
|
status: 'queued',
|
|
97
175
|
};
|
|
98
176
|
}
|
|
99
177
|
}
|
|
100
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Implements the burst algorithm for rate limiting.
|
|
180
|
+
* @param input - The input data for the request.
|
|
181
|
+
* @param id - The unique ID of the request.
|
|
182
|
+
*/
|
|
183
|
+
async burstAlgorithm(input, id) {
|
|
101
184
|
const now = Date.now();
|
|
102
185
|
const windowMs = this.config.interval * 1000;
|
|
103
186
|
// console.log(windowMs, 'windowMs');
|
|
@@ -113,7 +196,6 @@ class RateLimiter {
|
|
|
113
196
|
const timeRemaining = windowMs - timeElapsed;
|
|
114
197
|
// If we've hit request limit but window hasn't expired, queue and wait
|
|
115
198
|
if (this.config._count >= this.config.request && timeRemaining > 0) {
|
|
116
|
-
this.queue.push(input);
|
|
117
199
|
return {
|
|
118
200
|
status: 'queued',
|
|
119
201
|
};
|
|
@@ -133,42 +215,61 @@ class RateLimiter {
|
|
|
133
215
|
this.config._count = 0;
|
|
134
216
|
await this.processQueue();
|
|
135
217
|
}, waitSeconds);
|
|
218
|
+
this._queueState = 'waiting';
|
|
136
219
|
}
|
|
137
220
|
try {
|
|
138
221
|
const response = await this.config.cb(input, this.config.id);
|
|
222
|
+
delete this.queue[id];
|
|
139
223
|
this.eventManager.emit('completed', {
|
|
140
224
|
request: input,
|
|
141
225
|
response
|
|
142
226
|
});
|
|
143
|
-
return {
|
|
144
|
-
status: 'success',
|
|
145
|
-
};
|
|
146
227
|
}
|
|
147
228
|
catch (error) {
|
|
148
|
-
|
|
149
|
-
status: 'error',
|
|
150
|
-
message: error.message
|
|
151
|
-
};
|
|
229
|
+
await this.handleError(id, input, error);
|
|
152
230
|
}
|
|
153
231
|
}
|
|
154
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Processes a single request using the appropriate algorithm.
|
|
234
|
+
* @param input - The input data for the request.
|
|
235
|
+
* @param id - The unique ID of the request.
|
|
236
|
+
*/
|
|
237
|
+
async process(input, id) {
|
|
155
238
|
let response = null;
|
|
156
|
-
// we need to ensure that the parametes are not in the queue
|
|
157
239
|
try {
|
|
158
240
|
if (this.config.mode === 'spread') {
|
|
159
|
-
response = await this.spreadAlgorithm(input);
|
|
241
|
+
response = await this.spreadAlgorithm(input, id);
|
|
160
242
|
}
|
|
161
243
|
else {
|
|
162
|
-
response = await this.burstAlgorithm(input);
|
|
244
|
+
response = await this.burstAlgorithm(input, id);
|
|
163
245
|
}
|
|
164
246
|
return response;
|
|
165
247
|
}
|
|
166
248
|
catch (error) {
|
|
249
|
+
await this.handleError(id, input, error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Invokes a new request, adding it to the queue if necessary.
|
|
254
|
+
* @param input - The input data for the request.
|
|
255
|
+
* @param config - Optional configuration for the request.
|
|
256
|
+
*/
|
|
257
|
+
async invoke(input, config) {
|
|
258
|
+
const id = config?._urId || crypto.randomUUID();
|
|
259
|
+
// Ensure the same input is not already in queue
|
|
260
|
+
if (this.queue[id]) {
|
|
261
|
+
// console.log('Request with same ID already in queue:', id);
|
|
167
262
|
return {
|
|
168
|
-
status: '
|
|
169
|
-
message:
|
|
263
|
+
status: 'queued',
|
|
264
|
+
message: 'Request already queued with same ID'
|
|
170
265
|
};
|
|
171
266
|
}
|
|
267
|
+
this.queue[id] = {
|
|
268
|
+
input,
|
|
269
|
+
_urId: id,
|
|
270
|
+
retryCount: config?.retryCount || 0
|
|
271
|
+
};
|
|
272
|
+
await this.process(input, id);
|
|
172
273
|
}
|
|
173
274
|
}
|
|
174
275
|
exports.RateLimiter = RateLimiter;
|
package/dist/ratelimit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ratelimit.js","sourceRoot":"","sources":["../src/ratelimit.ts"],"names":[],"mappings":";;;AAAA,mCAAsC;AACtC,iCAAqC;AAExB,QAAA,IAAI,GAAG,IAAI,kBAAW,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ratelimit.js","sourceRoot":"","sources":["../src/ratelimit.ts"],"names":[],"mappings":"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"}
|
package/dist/test.js
CHANGED
|
@@ -8,20 +8,35 @@ cluster.addOption({
|
|
|
8
8
|
per: 'minute',
|
|
9
9
|
mode: 'hybrid',
|
|
10
10
|
hybridRatio: 10,
|
|
11
|
+
maxRetry: 3,
|
|
11
12
|
cb: async (input) => {
|
|
12
|
-
|
|
13
|
+
if (['chat-5', 'chat-8'].includes(input.chatId)) {
|
|
14
|
+
throw new Error('Unable to process');
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return `Processed: ${input.modelId} - ${input.chatId} by Deepseek`;
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
20
|
}, true);
|
|
15
21
|
cluster.on('completed', (data) => {
|
|
16
|
-
console.log('Completed:', data.response);
|
|
22
|
+
// console.log('Completed:', data.response);
|
|
17
23
|
});
|
|
18
|
-
cluster.on('error', (data) => {
|
|
19
|
-
console.error('Error processing
|
|
24
|
+
cluster.on('error', async (data) => {
|
|
25
|
+
console.error('Error processing', data);
|
|
26
|
+
try {
|
|
27
|
+
// await cluster.invoke(data.request, data.config);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error('Retry failed for:', data, 'Error:', error.message);
|
|
31
|
+
}
|
|
20
32
|
});
|
|
21
|
-
|
|
33
|
+
const uuid = "bosss";
|
|
34
|
+
for (let i = 0; i < 10; i++) {
|
|
22
35
|
cluster.invoke({
|
|
23
36
|
modelId: 'gpt-4',
|
|
24
37
|
chatId: `chat-${i}`,
|
|
38
|
+
}, {
|
|
39
|
+
_urId: i.toString(),
|
|
25
40
|
});
|
|
26
41
|
}
|
|
27
42
|
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AACA,uCAAoC;AAQpC,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAe,YAAY,CAAC,CAAC;AAExD,OAAO,CAAC,SAAS,CAAC;IACd,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,GAAG;IACZ,GAAG,EAAE,QAAQ;IACb,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,EAAE;IACf,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChB,OAAO,cAAc,KAAK,CAAC,OAAO,MAAM,KAAK,CAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AACA,uCAAoC;AAQpC,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAe,YAAY,CAAC,CAAC;AAExD,OAAO,CAAC,SAAS,CAAC;IACd,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,GAAG;IACZ,GAAG,EAAE,QAAQ;IACb,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,EAAE;IACf,QAAQ,EAAE,CAAC;IACX,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChB,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,OAAO,cAAc,KAAK,CAAC,OAAO,MAAM,KAAK,CAAC,MAAM,cAAc,CAAC;QACvE,CAAC;IACL,CAAC;CACJ,EAAE,IAAI,CAAC,CAAC;AAET,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;IAC7B,4CAA4C;AAChD,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC/B,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC;QACD,mDAAmD;IACvD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACtE,CAAC;AACL,CAAC,CAAC,CAAC;AAGH,MAAM,IAAI,GAAG,OAAO,CAAC;AACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC;QACX,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,QAAQ,CAAC,EAAE;KACtB,EAAE;QACC,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE;KACtB,CAAC,CAAC;AACP,CAAC"}
|
package/dist/time.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
export declare class Interval {
|
|
2
2
|
callbacks: any[];
|
|
3
|
+
recurring: {
|
|
4
|
+
cb: (...args: any[]) => Promise<any>;
|
|
5
|
+
interval: number;
|
|
6
|
+
lastCall: number;
|
|
7
|
+
}[];
|
|
3
8
|
constructor();
|
|
4
9
|
add: (cb: (...args: any[]) => Promise<any>, timeout: number) => void;
|
|
10
|
+
addRecurring: (cb: (...args: any[]) => Promise<any>, interval: number) => void;
|
|
5
11
|
}
|
|
6
12
|
export declare class TimeCluster {
|
|
7
13
|
intervals: Interval[];
|
|
8
14
|
constructor(size: number);
|
|
9
15
|
waitFor: (cb: (...args: any[]) => Promise<any>, timeout: number) => void;
|
|
16
|
+
intervalFor: (cb: (...args: any[]) => Promise<any>, interval: number) => void;
|
|
10
17
|
}
|
|
11
18
|
//# sourceMappingURL=time.d.ts.map
|
package/dist/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IACjB,SAAS,EAAE,GAAG,EAAE,CAAM;;
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IACjB,SAAS,EAAE,GAAG,EAAE,CAAM;IACtB,SAAS,EAAE;QAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;;IAuB/F,GAAG,GAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,UAG3D;IAED,YAAY,GAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,UAAU,MAAM,UAErE;CACJ;AAED,qBAAa,WAAW;IAEpB,SAAS,aAAyB;gBAEtB,IAAI,EAAE,MAAM;IAMxB,OAAO,GAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,UAG/D;IAED,WAAW,GAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,UAAU,MAAM,UAGpE;CACJ"}
|
package/dist/time.js
CHANGED
|
@@ -4,12 +4,17 @@ exports.TimeCluster = exports.Interval = void 0;
|
|
|
4
4
|
class Interval {
|
|
5
5
|
constructor() {
|
|
6
6
|
this.callbacks = [];
|
|
7
|
+
this.recurring = [];
|
|
7
8
|
this.add = (cb, timeout) => {
|
|
8
9
|
const target = Date.now() + timeout * 1000;
|
|
9
10
|
this.callbacks.push({ cb, target });
|
|
10
11
|
};
|
|
12
|
+
this.addRecurring = (cb, interval) => {
|
|
13
|
+
this.recurring.push({ cb, interval, lastCall: Date.now() });
|
|
14
|
+
};
|
|
11
15
|
setInterval(async () => {
|
|
12
16
|
const time = Date.now();
|
|
17
|
+
// Handle one-time callbacks
|
|
13
18
|
for (let i = this.callbacks.length - 1; i >= 0; i--) {
|
|
14
19
|
const item = this.callbacks[i];
|
|
15
20
|
if (time >= item.target) {
|
|
@@ -17,6 +22,13 @@ class Interval {
|
|
|
17
22
|
this.callbacks.splice(i, 1);
|
|
18
23
|
}
|
|
19
24
|
}
|
|
25
|
+
// Handle recurring callbacks
|
|
26
|
+
for (const item of this.recurring) {
|
|
27
|
+
if (time - item.lastCall >= item.interval * 1000) {
|
|
28
|
+
await item.cb();
|
|
29
|
+
item.lastCall = time;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
20
32
|
}, 250);
|
|
21
33
|
}
|
|
22
34
|
}
|
|
@@ -28,6 +40,10 @@ class TimeCluster {
|
|
|
28
40
|
const interval = this.intervals[Math.floor(Math.random() * this.intervals.length)];
|
|
29
41
|
interval.add(cb, timeout);
|
|
30
42
|
};
|
|
43
|
+
this.intervalFor = (cb, interval) => {
|
|
44
|
+
const intervalInst = this.intervals[Math.floor(Math.random() * this.intervals.length)];
|
|
45
|
+
intervalInst.addRecurring(cb, interval);
|
|
46
|
+
};
|
|
31
47
|
for (let i = 0; i < size; i++) {
|
|
32
48
|
this.intervals.push(new Interval());
|
|
33
49
|
}
|
package/dist/time.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.js","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":";;;AAEA,MAAa,QAAQ;
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":";;;AAEA,MAAa,QAAQ;IAIjB;QAHA,cAAS,GAAU,EAAE,CAAC;QACtB,cAAS,GAAmF,EAAE,CAAC;QAuB/F,QAAG,GAAG,CAAC,EAAoC,EAAE,OAAe,EAAE,EAAE;YAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC;YAC3C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACxC,CAAC,CAAA;QAED,iBAAY,GAAG,CAAC,EAAoC,EAAE,QAAgB,EAAE,EAAE;YACtE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAChE,CAAC,CAAA;QA3BG,WAAW,CAAC,KAAK,IAAI,EAAE;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACxB,4BAA4B;YAC5B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAClD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC/B,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBACtB,MAAM,IAAI,CAAC,EAAE,EAAE,CAAC;oBAChB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChC,CAAC;YACL,CAAC;YACD,6BAA6B;YAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChC,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,CAAC;oBAC/C,MAAM,IAAI,CAAC,EAAE,EAAE,CAAC;oBAChB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACzB,CAAC;YACL,CAAC;QACL,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC;CAUJ;AAjCD,4BAiCC;AAED,MAAa,WAAW;IAIpB,YAAY,IAAY;QAFxB,cAAS,GAAG,IAAI,KAAK,EAAY,CAAC;QAQlC,YAAO,GAAG,CAAC,EAAoC,EAAE,OAAe,EAAE,EAAE;YAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YACnF,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAA;QAED,gBAAW,GAAG,CAAC,EAAoC,EAAE,QAAgB,EAAE,EAAE;YACrE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YACvF,YAAY,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC,CAAA;QAbG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC;IACL,CAAC;CAWJ;AAnBD,kCAmBC"}
|