@libp2p/utils 5.2.0 → 5.2.1-8bbd43628

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,86 @@
1
+ export interface RateLimiterInit {
2
+ /**
3
+ * Number of points
4
+ *
5
+ * @default 4
6
+ */
7
+ points?: number;
8
+ /**
9
+ * Per seconds
10
+ *
11
+ * @default 1
12
+ */
13
+ duration?: number;
14
+ /**
15
+ * Block if consumed more than points in current duration for blockDuration seconds
16
+ *
17
+ * @default 0
18
+ */
19
+ blockDuration?: number;
20
+ /**
21
+ * Execute allowed actions evenly over duration
22
+ *
23
+ * @default false
24
+ */
25
+ execEvenly?: boolean;
26
+ /**
27
+ * ms, works with execEvenly=true option
28
+ *
29
+ * @default duration * 1000 / points
30
+ */
31
+ execEvenlyMinDelayMs?: number;
32
+ /**
33
+ * @default rlflx
34
+ */
35
+ keyPrefix?: string;
36
+ }
37
+ export interface GetKeySecDurationOptions {
38
+ customDuration?: number;
39
+ }
40
+ export interface RateLimiterResult {
41
+ remainingPoints: number;
42
+ msBeforeNext: number;
43
+ consumedPoints: number;
44
+ isFirstInDuration: boolean;
45
+ }
46
+ export interface RateRecord {
47
+ value: number;
48
+ expiresAt?: Date;
49
+ timeoutId?: ReturnType<typeof setTimeout>;
50
+ }
51
+ export declare class RateLimiter {
52
+ readonly memoryStorage: MemoryStorage;
53
+ protected points: number;
54
+ protected duration: number;
55
+ protected blockDuration: number;
56
+ protected execEvenly: boolean;
57
+ protected execEvenlyMinDelayMs: number;
58
+ protected keyPrefix: string;
59
+ constructor(opts?: RateLimiterInit);
60
+ consume(key: string, pointsToConsume?: number, options?: GetKeySecDurationOptions): Promise<RateLimiterResult>;
61
+ penalty(key: string, points?: number, options?: GetKeySecDurationOptions): RateLimiterResult;
62
+ reward(key: string, points?: number, options?: GetKeySecDurationOptions): RateLimiterResult;
63
+ /**
64
+ * Block any key for secDuration seconds
65
+ *
66
+ * @param key
67
+ * @param secDuration
68
+ */
69
+ block(key: string, secDuration: number): RateLimiterResult;
70
+ set(key: string, points: number, secDuration?: number): RateLimiterResult;
71
+ get(key: string): RateLimiterResult | undefined;
72
+ delete(key: string): void;
73
+ private _getKeySecDuration;
74
+ getKey(key: string): string;
75
+ parseKey(rlKey: string): string;
76
+ }
77
+ declare class MemoryStorage {
78
+ readonly storage: Map<string, RateRecord>;
79
+ constructor();
80
+ incrby(key: string, value: number, durationSec: number): RateLimiterResult;
81
+ set(key: string, value: number, durationSec: number): RateLimiterResult;
82
+ get(key: string): RateLimiterResult | undefined;
83
+ delete(key: string): boolean;
84
+ }
85
+ export {};
86
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/rate-limiter.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAE7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;CAC1C;AAED,qBAAa,WAAW;IACtB,SAAgB,aAAa,EAAE,aAAa,CAAA;IAC5C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,aAAa,EAAE,MAAM,CAAA;IAC/B,SAAS,CAAC,UAAU,EAAE,OAAO,CAAA;IAC7B,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACtC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAA;gBAEd,IAAI,GAAE,eAAoB;IAUjC,OAAO,CAAE,GAAG,EAAE,MAAM,EAAE,eAAe,GAAE,MAAU,EAAE,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA2B5H,OAAO,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,EAAE,OAAO,GAAE,wBAA6B,GAAG,iBAAiB;IASpG,MAAM,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,EAAE,OAAO,GAAE,wBAA6B,GAAG,iBAAiB;IASnG;;;;;OAKG;IACH,KAAK,CAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,iBAAiB;IAc3D,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAE,MAAU,GAAG,iBAAiB;IAa7E,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAUhD,MAAM,CAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAI1B,OAAO,CAAC,kBAAkB;IAQ1B,MAAM,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAI5B,QAAQ,CAAE,KAAK,EAAE,MAAM,GAAG,MAAM;CAGjC;AAED,cAAM,aAAa;IACjB,SAAgB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;;IAMhD,MAAM,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,iBAAiB;IA0B3E,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,iBAAiB;IAiCxE,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAgBhD,MAAM,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO;CAc9B"}
@@ -0,0 +1,184 @@
1
+ import { CodeError } from '@libp2p/interface';
2
+ import delay from 'delay';
3
+ export class RateLimiter {
4
+ memoryStorage;
5
+ points;
6
+ duration;
7
+ blockDuration;
8
+ execEvenly;
9
+ execEvenlyMinDelayMs;
10
+ keyPrefix;
11
+ constructor(opts = {}) {
12
+ this.points = opts.points ?? 4;
13
+ this.duration = opts.duration ?? 1;
14
+ this.blockDuration = opts.blockDuration ?? 0;
15
+ this.execEvenly = opts.execEvenly ?? false;
16
+ this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs ?? (this.duration * 1000 / this.points);
17
+ this.keyPrefix = opts.keyPrefix ?? 'rlflx';
18
+ this.memoryStorage = new MemoryStorage();
19
+ }
20
+ async consume(key, pointsToConsume = 1, options = {}) {
21
+ const rlKey = this.getKey(key);
22
+ const secDuration = this._getKeySecDuration(options);
23
+ let res = this.memoryStorage.incrby(rlKey, pointsToConsume, secDuration);
24
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
25
+ if (res.consumedPoints > this.points) {
26
+ // Block only first time when consumed more than points
27
+ if (this.blockDuration > 0 && res.consumedPoints <= (this.points + pointsToConsume)) {
28
+ // Block key
29
+ res = this.memoryStorage.set(rlKey, res.consumedPoints, this.blockDuration);
30
+ }
31
+ throw new CodeError('Rate limit exceeded', 'ERR_RATE_LIMIT_EXCEEDED', res);
32
+ }
33
+ else if (this.execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
34
+ // Execute evenly
35
+ let delayMs = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
36
+ if (delayMs < this.execEvenlyMinDelayMs) {
37
+ delayMs = res.consumedPoints * this.execEvenlyMinDelayMs;
38
+ }
39
+ await delay(delayMs);
40
+ }
41
+ return res;
42
+ }
43
+ penalty(key, points = 1, options = {}) {
44
+ const rlKey = this.getKey(key);
45
+ const secDuration = this._getKeySecDuration(options);
46
+ const res = this.memoryStorage.incrby(rlKey, points, secDuration);
47
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
48
+ return res;
49
+ }
50
+ reward(key, points = 1, options = {}) {
51
+ const rlKey = this.getKey(key);
52
+ const secDuration = this._getKeySecDuration(options);
53
+ const res = this.memoryStorage.incrby(rlKey, -points, secDuration);
54
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
55
+ return res;
56
+ }
57
+ /**
58
+ * Block any key for secDuration seconds
59
+ *
60
+ * @param key
61
+ * @param secDuration
62
+ */
63
+ block(key, secDuration) {
64
+ const msDuration = secDuration * 1000;
65
+ const initPoints = this.points + 1;
66
+ this.memoryStorage.set(this.getKey(key), initPoints, secDuration);
67
+ return {
68
+ remainingPoints: 0,
69
+ msBeforeNext: msDuration === 0 ? -1 : msDuration,
70
+ consumedPoints: initPoints,
71
+ isFirstInDuration: false
72
+ };
73
+ }
74
+ set(key, points, secDuration = 0) {
75
+ const msDuration = (secDuration >= 0 ? secDuration : this.duration) * 1000;
76
+ this.memoryStorage.set(this.getKey(key), points, secDuration);
77
+ return {
78
+ remainingPoints: 0,
79
+ msBeforeNext: msDuration === 0 ? -1 : msDuration,
80
+ consumedPoints: points,
81
+ isFirstInDuration: false
82
+ };
83
+ }
84
+ get(key) {
85
+ const res = this.memoryStorage.get(this.getKey(key));
86
+ if (res != null) {
87
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
88
+ }
89
+ return res;
90
+ }
91
+ delete(key) {
92
+ this.memoryStorage.delete(this.getKey(key));
93
+ }
94
+ _getKeySecDuration(options) {
95
+ if (options?.customDuration != null && options.customDuration >= 0) {
96
+ return options.customDuration;
97
+ }
98
+ return this.duration;
99
+ }
100
+ getKey(key) {
101
+ return this.keyPrefix.length > 0 ? `${this.keyPrefix}:${key}` : key;
102
+ }
103
+ parseKey(rlKey) {
104
+ return rlKey.substring(this.keyPrefix.length);
105
+ }
106
+ }
107
+ class MemoryStorage {
108
+ storage;
109
+ constructor() {
110
+ this.storage = new Map();
111
+ }
112
+ incrby(key, value, durationSec) {
113
+ const existing = this.storage.get(key);
114
+ if (existing != null) {
115
+ const msBeforeExpires = existing.expiresAt != null
116
+ ? existing.expiresAt.getTime() - new Date().getTime()
117
+ : -1;
118
+ if (existing.expiresAt == null || msBeforeExpires > 0) {
119
+ // Change value
120
+ existing.value += value;
121
+ return {
122
+ remainingPoints: 0,
123
+ msBeforeNext: msBeforeExpires,
124
+ consumedPoints: existing.value,
125
+ isFirstInDuration: false
126
+ };
127
+ }
128
+ return this.set(key, value, durationSec);
129
+ }
130
+ return this.set(key, value, durationSec);
131
+ }
132
+ set(key, value, durationSec) {
133
+ const durationMs = durationSec * 1000;
134
+ const existing = this.storage.get(key);
135
+ if (existing != null) {
136
+ clearTimeout(existing.timeoutId);
137
+ }
138
+ const record = {
139
+ value,
140
+ expiresAt: durationMs > 0 ? new Date(Date.now() + durationMs) : undefined
141
+ };
142
+ this.storage.set(key, record);
143
+ if (durationMs > 0) {
144
+ record.timeoutId = setTimeout(() => {
145
+ this.storage.delete(key);
146
+ }, durationMs);
147
+ if (record.timeoutId.unref != null) {
148
+ record.timeoutId.unref();
149
+ }
150
+ }
151
+ return {
152
+ remainingPoints: 0,
153
+ msBeforeNext: durationMs === 0 ? -1 : durationMs,
154
+ consumedPoints: record.value,
155
+ isFirstInDuration: true
156
+ };
157
+ }
158
+ get(key) {
159
+ const existing = this.storage.get(key);
160
+ if (existing != null) {
161
+ const msBeforeExpires = existing.expiresAt != null
162
+ ? existing.expiresAt.getTime() - new Date().getTime()
163
+ : -1;
164
+ return {
165
+ remainingPoints: 0,
166
+ msBeforeNext: msBeforeExpires,
167
+ consumedPoints: existing.value,
168
+ isFirstInDuration: false
169
+ };
170
+ }
171
+ }
172
+ delete(key) {
173
+ const record = this.storage.get(key);
174
+ if (record != null) {
175
+ if (record.timeoutId != null) {
176
+ clearTimeout(record.timeoutId);
177
+ }
178
+ this.storage.delete(key);
179
+ return true;
180
+ }
181
+ return false;
182
+ }
183
+ }
184
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AA6DzB,MAAM,OAAO,WAAW;IACN,aAAa,CAAe;IAClC,MAAM,CAAQ;IACd,QAAQ,CAAQ;IAChB,aAAa,CAAQ;IACrB,UAAU,CAAS;IACnB,oBAAoB,CAAQ;IAC5B,SAAS,CAAQ;IAE3B,YAAa,OAAwB,EAAE;QACrC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;QAC9B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA;QAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,CAAA;QAC5C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,KAAK,CAAA;QAC1C,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;QAC7F,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAA;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,EAAE,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CAAE,GAAW,EAAE,kBAA0B,CAAC,EAAE,UAAoC,EAAE;QAC7F,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QACpD,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,WAAW,CAAC,CAAA;QACxE,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;QAEnE,IAAI,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACrC,uDAAuD;YACvD,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC;gBACpF,YAAY;gBACZ,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;YAC7E,CAAC;YAED,MAAM,IAAI,SAAS,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,GAAG,CAAC,CAAA;QAC5E,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC7E,iBAAiB;YACjB,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAA;YACrE,IAAI,OAAO,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBACxC,OAAO,GAAG,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,oBAAoB,CAAA;YAC1D,CAAC;YAED,MAAM,KAAK,CAAC,OAAO,CAAC,CAAA;QACtB,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,OAAO,CAAE,GAAW,EAAE,SAAiB,CAAC,EAAE,UAAoC,EAAE;QAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;QACjE,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;QAEnE,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,MAAM,CAAE,GAAW,EAAE,SAAiB,CAAC,EAAE,UAAoC,EAAE;QAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;QAClE,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;QAEnE,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAE,GAAW,EAAE,WAAmB;QACrC,MAAM,UAAU,GAAG,WAAW,GAAG,IAAI,CAAA;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QAElC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA;QAEjE,OAAO;YACL,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;YAChD,cAAc,EAAE,UAAU;YAC1B,iBAAiB,EAAE,KAAK;SACzB,CAAA;IACH,CAAC;IAED,GAAG,CAAE,GAAW,EAAE,MAAc,EAAE,cAAsB,CAAC;QACvD,MAAM,UAAU,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;QAE1E,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;QAE7D,OAAO;YACL,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;YAChD,cAAc,EAAE,MAAM;YACtB,iBAAiB,EAAE,KAAK;SACzB,CAAA;IACH,CAAC;IAED,GAAG,CAAE,GAAW;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QAEpD,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,MAAM,CAAE,GAAW;QACjB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IAC7C,CAAC;IAEO,kBAAkB,CAAE,OAAkC;QAC5D,IAAI,OAAO,EAAE,cAAc,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE,CAAC;YACnE,OAAO,OAAO,CAAC,cAAc,CAAA;QAC/B,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,MAAM,CAAE,GAAW;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IACrE,CAAC;IAED,QAAQ,CAAE,KAAa;QACrB,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC/C,CAAC;CACF;AAED,MAAM,aAAa;IACD,OAAO,CAAyB;IAEhD;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAA;IAC1B,CAAC;IAED,MAAM,CAAE,GAAW,EAAE,KAAa,EAAE,WAAmB;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAEtC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,eAAe,GAAG,QAAQ,CAAC,SAAS,IAAI,IAAI;gBAChD,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE;gBACrD,CAAC,CAAC,CAAC,CAAC,CAAA;YAEN,IAAI,QAAQ,CAAC,SAAS,IAAI,IAAI,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;gBACtD,eAAe;gBACf,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAA;gBAEvB,OAAO;oBACL,eAAe,EAAE,CAAC;oBAClB,YAAY,EAAE,eAAe;oBAC7B,cAAc,EAAE,QAAQ,CAAC,KAAK;oBAC9B,iBAAiB,EAAE,KAAK;iBACzB,CAAA;YACH,CAAC;YAED,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;QAC1C,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;IAC1C,CAAC;IAED,GAAG,CAAE,GAAW,EAAE,KAAa,EAAE,WAAmB;QAClD,MAAM,UAAU,GAAG,WAAW,GAAG,IAAI,CAAA;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAEtC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,MAAM,GAAe;YACzB,KAAK;YACL,SAAS,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;SAC1E,CAAA;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAE7B,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBACjC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC1B,CAAC,EAAE,UAAU,CAAC,CAAA;YAEd,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACnC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;YAC1B,CAAC;QACH,CAAC;QAED,OAAO;YACL,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;YAChD,cAAc,EAAE,MAAM,CAAC,KAAK;YAC5B,iBAAiB,EAAE,IAAI;SACxB,CAAA;IACH,CAAC;IAED,GAAG,CAAE,GAAW;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAEtC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,eAAe,GAAG,QAAQ,CAAC,SAAS,IAAI,IAAI;gBAChD,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE;gBACrD,CAAC,CAAC,CAAC,CAAC,CAAA;YACN,OAAO;gBACL,eAAe,EAAE,CAAC;gBAClB,YAAY,EAAE,eAAe;gBAC7B,cAAc,EAAE,QAAQ,CAAC,KAAK;gBAC9B,iBAAiB,EAAE,KAAK;aACzB,CAAA;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAE,GAAW;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAEpC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;gBAC7B,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAChC,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAExB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/utils",
3
- "version": "5.2.0",
3
+ "version": "5.2.1-8bbd43628",
4
4
  "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/utils#readme",
@@ -76,13 +76,17 @@
76
76
  "types": "./dist/src/multiaddr/is-private.d.ts",
77
77
  "import": "./dist/src/multiaddr/is-private.js"
78
78
  },
79
+ "./peer-queue": {
80
+ "types": "./dist/src/peer-queue.d.ts",
81
+ "import": "./dist/src/peer-queue.js"
82
+ },
79
83
  "./queue": {
80
84
  "types": "./dist/src/queue/index.d.ts",
81
85
  "import": "./dist/src/queue/index.js"
82
86
  },
83
- "./peer-queue": {
84
- "types": "./dist/src/peer-queue.d.ts",
85
- "import": "./dist/src/peer-queue.js"
87
+ "./rate-limiter": {
88
+ "types": "./dist/src/rate-limiter.d.ts",
89
+ "import": "./dist/src/rate-limiter.js"
86
90
  },
87
91
  "./stream-to-ma-conn": {
88
92
  "types": "./dist/src/stream-to-ma-conn.d.ts",
@@ -119,22 +123,23 @@
119
123
  },
120
124
  "dependencies": {
121
125
  "@chainsafe/is-ip": "^2.0.2",
122
- "@libp2p/interface": "^1.1.1",
123
- "@libp2p/logger": "^4.0.4",
126
+ "@libp2p/interface": "1.1.1-8bbd43628",
127
+ "@libp2p/logger": "4.0.4-8bbd43628",
124
128
  "@multiformats/multiaddr": "^12.1.10",
125
129
  "@multiformats/multiaddr-matcher": "^1.1.0",
130
+ "delay": "^6.0.0",
126
131
  "get-iterator": "^2.0.1",
127
132
  "is-loopback-addr": "^2.0.1",
128
- "it-pushable": "^3.2.2",
133
+ "it-pushable": "^3.2.3",
129
134
  "it-stream-types": "^2.0.1",
130
135
  "p-defer": "^4.0.0",
131
136
  "private-ip": "^3.0.1",
132
137
  "race-event": "^1.1.0",
133
- "race-signal": "^1.0.1",
134
- "uint8arraylist": "^2.4.3"
138
+ "race-signal": "^1.0.2",
139
+ "uint8arraylist": "^2.4.7"
135
140
  },
136
141
  "devDependencies": {
137
- "@libp2p/peer-id-factory": "^4.0.3",
142
+ "@libp2p/peer-id-factory": "4.0.4-8bbd43628",
138
143
  "aegir": "^42.0.0",
139
144
  "delay": "^6.0.0",
140
145
  "it-all": "^3.0.3",
@@ -0,0 +1,287 @@
1
+ import { CodeError } from '@libp2p/interface'
2
+ import delay from 'delay'
3
+
4
+ export interface RateLimiterInit {
5
+ /**
6
+ * Number of points
7
+ *
8
+ * @default 4
9
+ */
10
+ points?: number
11
+
12
+ /**
13
+ * Per seconds
14
+ *
15
+ * @default 1
16
+ */
17
+ duration?: number
18
+
19
+ /**
20
+ * Block if consumed more than points in current duration for blockDuration seconds
21
+ *
22
+ * @default 0
23
+ */
24
+ blockDuration?: number
25
+
26
+ /**
27
+ * Execute allowed actions evenly over duration
28
+ *
29
+ * @default false
30
+ */
31
+ execEvenly?: boolean
32
+
33
+ /**
34
+ * ms, works with execEvenly=true option
35
+ *
36
+ * @default duration * 1000 / points
37
+ */
38
+ execEvenlyMinDelayMs?: number
39
+
40
+ /**
41
+ * @default rlflx
42
+ */
43
+ keyPrefix?: string
44
+ }
45
+
46
+ export interface GetKeySecDurationOptions {
47
+ customDuration?: number
48
+ }
49
+
50
+ export interface RateLimiterResult {
51
+ remainingPoints: number
52
+ msBeforeNext: number
53
+ consumedPoints: number
54
+ isFirstInDuration: boolean
55
+ }
56
+
57
+ export interface RateRecord {
58
+ value: number
59
+ expiresAt?: Date
60
+ timeoutId?: ReturnType<typeof setTimeout>
61
+ }
62
+
63
+ export class RateLimiter {
64
+ public readonly memoryStorage: MemoryStorage
65
+ protected points: number
66
+ protected duration: number
67
+ protected blockDuration: number
68
+ protected execEvenly: boolean
69
+ protected execEvenlyMinDelayMs: number
70
+ protected keyPrefix: string
71
+
72
+ constructor (opts: RateLimiterInit = {}) {
73
+ this.points = opts.points ?? 4
74
+ this.duration = opts.duration ?? 1
75
+ this.blockDuration = opts.blockDuration ?? 0
76
+ this.execEvenly = opts.execEvenly ?? false
77
+ this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs ?? (this.duration * 1000 / this.points)
78
+ this.keyPrefix = opts.keyPrefix ?? 'rlflx'
79
+ this.memoryStorage = new MemoryStorage()
80
+ }
81
+
82
+ async consume (key: string, pointsToConsume: number = 1, options: GetKeySecDurationOptions = {}): Promise<RateLimiterResult> {
83
+ const rlKey = this.getKey(key)
84
+ const secDuration = this._getKeySecDuration(options)
85
+ let res = this.memoryStorage.incrby(rlKey, pointsToConsume, secDuration)
86
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0)
87
+
88
+ if (res.consumedPoints > this.points) {
89
+ // Block only first time when consumed more than points
90
+ if (this.blockDuration > 0 && res.consumedPoints <= (this.points + pointsToConsume)) {
91
+ // Block key
92
+ res = this.memoryStorage.set(rlKey, res.consumedPoints, this.blockDuration)
93
+ }
94
+
95
+ throw new CodeError('Rate limit exceeded', 'ERR_RATE_LIMIT_EXCEEDED', res)
96
+ } else if (this.execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
97
+ // Execute evenly
98
+ let delayMs = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2))
99
+ if (delayMs < this.execEvenlyMinDelayMs) {
100
+ delayMs = res.consumedPoints * this.execEvenlyMinDelayMs
101
+ }
102
+
103
+ await delay(delayMs)
104
+ }
105
+
106
+ return res
107
+ }
108
+
109
+ penalty (key: string, points: number = 1, options: GetKeySecDurationOptions = {}): RateLimiterResult {
110
+ const rlKey = this.getKey(key)
111
+ const secDuration = this._getKeySecDuration(options)
112
+ const res = this.memoryStorage.incrby(rlKey, points, secDuration)
113
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0)
114
+
115
+ return res
116
+ }
117
+
118
+ reward (key: string, points: number = 1, options: GetKeySecDurationOptions = {}): RateLimiterResult {
119
+ const rlKey = this.getKey(key)
120
+ const secDuration = this._getKeySecDuration(options)
121
+ const res = this.memoryStorage.incrby(rlKey, -points, secDuration)
122
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0)
123
+
124
+ return res
125
+ }
126
+
127
+ /**
128
+ * Block any key for secDuration seconds
129
+ *
130
+ * @param key
131
+ * @param secDuration
132
+ */
133
+ block (key: string, secDuration: number): RateLimiterResult {
134
+ const msDuration = secDuration * 1000
135
+ const initPoints = this.points + 1
136
+
137
+ this.memoryStorage.set(this.getKey(key), initPoints, secDuration)
138
+
139
+ return {
140
+ remainingPoints: 0,
141
+ msBeforeNext: msDuration === 0 ? -1 : msDuration,
142
+ consumedPoints: initPoints,
143
+ isFirstInDuration: false
144
+ }
145
+ }
146
+
147
+ set (key: string, points: number, secDuration: number = 0): RateLimiterResult {
148
+ const msDuration = (secDuration >= 0 ? secDuration : this.duration) * 1000
149
+
150
+ this.memoryStorage.set(this.getKey(key), points, secDuration)
151
+
152
+ return {
153
+ remainingPoints: 0,
154
+ msBeforeNext: msDuration === 0 ? -1 : msDuration,
155
+ consumedPoints: points,
156
+ isFirstInDuration: false
157
+ }
158
+ }
159
+
160
+ get (key: string): RateLimiterResult | undefined {
161
+ const res = this.memoryStorage.get(this.getKey(key))
162
+
163
+ if (res != null) {
164
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0)
165
+ }
166
+
167
+ return res
168
+ }
169
+
170
+ delete (key: string): void {
171
+ this.memoryStorage.delete(this.getKey(key))
172
+ }
173
+
174
+ private _getKeySecDuration (options?: GetKeySecDurationOptions): number {
175
+ if (options?.customDuration != null && options.customDuration >= 0) {
176
+ return options.customDuration
177
+ }
178
+
179
+ return this.duration
180
+ }
181
+
182
+ getKey (key: string): string {
183
+ return this.keyPrefix.length > 0 ? `${this.keyPrefix}:${key}` : key
184
+ }
185
+
186
+ parseKey (rlKey: string): string {
187
+ return rlKey.substring(this.keyPrefix.length)
188
+ }
189
+ }
190
+
191
+ class MemoryStorage {
192
+ public readonly storage: Map<string, RateRecord>
193
+
194
+ constructor () {
195
+ this.storage = new Map()
196
+ }
197
+
198
+ incrby (key: string, value: number, durationSec: number): RateLimiterResult {
199
+ const existing = this.storage.get(key)
200
+
201
+ if (existing != null) {
202
+ const msBeforeExpires = existing.expiresAt != null
203
+ ? existing.expiresAt.getTime() - new Date().getTime()
204
+ : -1
205
+
206
+ if (existing.expiresAt == null || msBeforeExpires > 0) {
207
+ // Change value
208
+ existing.value += value
209
+
210
+ return {
211
+ remainingPoints: 0,
212
+ msBeforeNext: msBeforeExpires,
213
+ consumedPoints: existing.value,
214
+ isFirstInDuration: false
215
+ }
216
+ }
217
+
218
+ return this.set(key, value, durationSec)
219
+ }
220
+
221
+ return this.set(key, value, durationSec)
222
+ }
223
+
224
+ set (key: string, value: number, durationSec: number): RateLimiterResult {
225
+ const durationMs = durationSec * 1000
226
+ const existing = this.storage.get(key)
227
+
228
+ if (existing != null) {
229
+ clearTimeout(existing.timeoutId)
230
+ }
231
+
232
+ const record: RateRecord = {
233
+ value,
234
+ expiresAt: durationMs > 0 ? new Date(Date.now() + durationMs) : undefined
235
+ }
236
+
237
+ this.storage.set(key, record)
238
+
239
+ if (durationMs > 0) {
240
+ record.timeoutId = setTimeout(() => {
241
+ this.storage.delete(key)
242
+ }, durationMs)
243
+
244
+ if (record.timeoutId.unref != null) {
245
+ record.timeoutId.unref()
246
+ }
247
+ }
248
+
249
+ return {
250
+ remainingPoints: 0,
251
+ msBeforeNext: durationMs === 0 ? -1 : durationMs,
252
+ consumedPoints: record.value,
253
+ isFirstInDuration: true
254
+ }
255
+ }
256
+
257
+ get (key: string): RateLimiterResult | undefined {
258
+ const existing = this.storage.get(key)
259
+
260
+ if (existing != null) {
261
+ const msBeforeExpires = existing.expiresAt != null
262
+ ? existing.expiresAt.getTime() - new Date().getTime()
263
+ : -1
264
+ return {
265
+ remainingPoints: 0,
266
+ msBeforeNext: msBeforeExpires,
267
+ consumedPoints: existing.value,
268
+ isFirstInDuration: false
269
+ }
270
+ }
271
+ }
272
+
273
+ delete (key: string): boolean {
274
+ const record = this.storage.get(key)
275
+
276
+ if (record != null) {
277
+ if (record.timeoutId != null) {
278
+ clearTimeout(record.timeoutId)
279
+ }
280
+
281
+ this.storage.delete(key)
282
+
283
+ return true
284
+ }
285
+ return false
286
+ }
287
+ }
@@ -1,60 +0,0 @@
1
- {
2
- "AbstractStream": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.abstract_stream.AbstractStream.html",
3
- "./abstract-stream:AbstractStream": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.abstract_stream.AbstractStream.html",
4
- "AbstractStreamInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.abstract_stream.AbstractStreamInit.html",
5
- "./abstract-stream:AbstractStreamInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.abstract_stream.AbstractStreamInit.html",
6
- "certifiedAddressesFirst": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.certifiedAddressesFirst.html",
7
- "./address-sort:certifiedAddressesFirst": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.certifiedAddressesFirst.html",
8
- "circuitRelayAddressesLast": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.circuitRelayAddressesLast.html",
9
- "./address-sort:circuitRelayAddressesLast": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.circuitRelayAddressesLast.html",
10
- "defaultAddressSort": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.defaultAddressSort.html",
11
- "./address-sort:defaultAddressSort": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.defaultAddressSort.html",
12
- "publicAddressesFirst": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.publicAddressesFirst.html",
13
- "./address-sort:publicAddressesFirst": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.address_sort.publicAddressesFirst.html",
14
- "arrayEquals": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.array_equals.arrayEquals.html",
15
- "./array-equals:arrayEquals": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.array_equals.arrayEquals.html",
16
- "closeSource": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.close_source.closeSource.html",
17
- "./close-source:closeSource": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.close_source.closeSource.html",
18
- "Errors": "https://libp2p.github.io/js-libp2p/variables/_libp2p_utils.ip_port_to_multiaddr.Errors.html",
19
- "./ip-port-to-multiaddr:Errors": "https://libp2p.github.io/js-libp2p/variables/_libp2p_utils.ip_port_to_multiaddr.Errors.html",
20
- "ipPortToMultiaddr": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.ip_port_to_multiaddr.ipPortToMultiaddr.html",
21
- "./ip-port-to-multiaddr:ipPortToMultiaddr": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.ip_port_to_multiaddr.ipPortToMultiaddr.html",
22
- "isPromise": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.is_promise.isPromise.html",
23
- "./is-promise:isPromise": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.is_promise.isPromise.html",
24
- "isLoopback": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.multiaddr_is_loopback.isLoopback.html",
25
- "./multiaddr/is-loopback:isLoopback": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.multiaddr_is_loopback.isLoopback.html",
26
- "isPrivate": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.multiaddr_is_private.isPrivate.html",
27
- "./multiaddr/is-private:isPrivate": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.multiaddr_is_private.isPrivate.html",
28
- "PeerQueue": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.peer_queue.PeerQueue.html",
29
- "./peer-queue:PeerQueue": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.peer_queue.PeerQueue.html",
30
- "PeerQueueOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.peer_queue.PeerQueueOptions.html",
31
- "./peer-queue:PeerQueueOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.peer_queue.PeerQueueOptions.html",
32
- "Queue": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.queue.Queue.html",
33
- "./queue:Queue": "https://libp2p.github.io/js-libp2p/classes/_libp2p_utils.queue.Queue.html",
34
- "JobMatcher": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.JobMatcher.html",
35
- "./queue:JobMatcher": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.JobMatcher.html",
36
- "QueueAddOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueAddOptions.html",
37
- "./queue:QueueAddOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueAddOptions.html",
38
- "QueueEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueEvents.html",
39
- "./queue:QueueEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueEvents.html",
40
- "QueueInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueInit.html",
41
- "./queue:QueueInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.QueueInit.html",
42
- "RunFunction": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.RunFunction.html",
43
- "./queue:RunFunction": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.queue.RunFunction.html",
44
- "JobStatus": "https://libp2p.github.io/js-libp2p/types/_libp2p_utils.queue.JobStatus.html",
45
- "./queue:JobStatus": "https://libp2p.github.io/js-libp2p/types/_libp2p_utils.queue.JobStatus.html",
46
- "StreamProperties": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.stream_to_ma_conn.StreamProperties.html",
47
- "./stream-to-ma-conn:StreamProperties": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.stream_to_ma_conn.StreamProperties.html",
48
- "streamToMaConnection": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.stream_to_ma_conn.streamToMaConnection.html",
49
- "./stream-to-ma-conn:streamToMaConnection": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.stream_to_ma_conn.streamToMaConnection.html",
50
- "CreateTrackedListInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_list.CreateTrackedListInit.html",
51
- "./tracked-list:CreateTrackedListInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_list.CreateTrackedListInit.html",
52
- "trackedList": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.tracked_list.trackedList.html",
53
- "./tracked-list:trackedList": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.tracked_list.trackedList.html",
54
- "CreateTrackedMapInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_map.CreateTrackedMapInit.html",
55
- "./tracked-map:CreateTrackedMapInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_map.CreateTrackedMapInit.html",
56
- "TrackedMapInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_map.TrackedMapInit.html",
57
- "./tracked-map:TrackedMapInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_utils.tracked_map.TrackedMapInit.html",
58
- "trackedMap": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.tracked_map.trackedMap.html",
59
- "./tracked-map:trackedMap": "https://libp2p.github.io/js-libp2p/functions/_libp2p_utils.tracked_map.trackedMap.html"
60
- }