express-rate-limit 6.6.0 → 6.7.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.
package/changelog.md CHANGED
@@ -6,21 +6,50 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to
7
7
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
- ## [6.5.0](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.5.0)
9
+ ## [6.7.0](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.7.0)
10
10
 
11
- ## Changed
11
+ ### Changed
12
+
13
+ - Updated links to point to new express-rate-limit organization on GitHub.
14
+ - Added advertisement to Readme for project sponsor
15
+ [Zuplo](https://zuplo.link/express-rate-limit).
16
+ - Updated TypeScript version and other dev dependencies
17
+ - Changed CI test suite: dropped node.js 12, added node.js 19
18
+
19
+ No functional changes.
20
+
21
+ ## [6.6.0](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.6.0)
22
+
23
+ ### Added
24
+
25
+ - Added `shutdown` method to the Store interface and the MemoryStore.
26
+
27
+ ## [6.5.2](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.5.2)
28
+
29
+ ### Fixed
30
+
31
+ - Fixed an issue with missing types in ESM monorepos.
32
+
33
+ ## [6.5.1](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.5.1)
34
+
35
+ ### Added
12
36
 
13
37
  - The message option can now be a (sync/asynx) function that returns a value
14
38
  (#311)
39
+
40
+ ### Changed
41
+
15
42
  - Updated all dependencies
16
43
 
44
+ Note: 6.5.0 was not released due to CI automation issues.
45
+
17
46
  ## [6.4.0](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.3.0)
18
47
 
19
48
  ### Added
20
49
 
21
50
  - Adds Express 5 (`5.0.0-beta.1`) as a supported peer dependency (#304)
22
51
 
23
- ## Changed
52
+ ### Changed
24
53
 
25
54
  - Tests are now run on Node 12, 14, 16 and 18 on CI (#305)
26
55
  - Updated all development dependencies (#306)
package/dist/index.cjs CHANGED
@@ -79,11 +79,14 @@ var promisifyStore = (passedStore) => {
79
79
  class PromisifiedStore {
80
80
  async increment(key) {
81
81
  return new Promise((resolve, reject) => {
82
- legacyStore.incr(key, (error, totalHits, resetTime) => {
83
- if (error)
84
- reject(error);
85
- resolve({ totalHits, resetTime });
86
- });
82
+ legacyStore.incr(
83
+ key,
84
+ (error, totalHits, resetTime) => {
85
+ if (error)
86
+ reject(error);
87
+ resolve({ totalHits, resetTime });
88
+ }
89
+ );
87
90
  });
88
91
  }
89
92
  async decrement(key) {
@@ -116,13 +119,18 @@ var parseOptions = (passedOptions) => {
116
119
  skip: (_request, _response) => false,
117
120
  keyGenerator(request, _response) {
118
121
  if (!request.ip) {
119
- console.error("WARN | `express-rate-limit` | `request.ip` is undefined. You can avoid this by providing a custom `keyGenerator` function, but it may be indicative of a larger issue.");
122
+ console.error(
123
+ "WARN | `express-rate-limit` | `request.ip` is undefined. You can avoid this by providing a custom `keyGenerator` function, but it may be indicative of a larger issue."
124
+ );
120
125
  }
121
126
  return request.ip;
122
127
  },
123
128
  async handler(request, response, _next, _optionsUsed) {
124
129
  response.status(config.statusCode);
125
- const message = typeof config.message === "function" ? await config.message(request, response) : config.message;
130
+ const message = typeof config.message === "function" ? await config.message(
131
+ request,
132
+ response
133
+ ) : config.message;
126
134
  if (!response.writableEnded) {
127
135
  response.send(message != null ? message : "Too many requests, please try again later.");
128
136
  }
@@ -133,7 +141,9 @@ var parseOptions = (passedOptions) => {
133
141
  store: promisifyStore((_c = notUndefinedOptions.store) != null ? _c : new MemoryStore())
134
142
  };
135
143
  if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || typeof config.store.resetAll !== "undefined" && typeof config.store.resetAll !== "function" || typeof config.store.init !== "undefined" && typeof config.store.init !== "function") {
136
- throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");
144
+ throw new TypeError(
145
+ "An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
146
+ );
137
147
  }
138
148
  return config;
139
149
  };
@@ -148,79 +158,92 @@ var rateLimit = (passedOptions) => {
148
158
  const options = parseOptions(passedOptions != null ? passedOptions : {});
149
159
  if (typeof options.store.init === "function")
150
160
  options.store.init(options);
151
- const middleware = handleAsyncErrors(async (request, response, next) => {
152
- const skip = await options.skip(request, response);
153
- if (skip) {
154
- next();
155
- return;
156
- }
157
- const augmentedRequest = request;
158
- const key = await options.keyGenerator(request, response);
159
- const { totalHits, resetTime } = await options.store.increment(key);
160
- const retrieveQuota = typeof options.max === "function" ? options.max(request, response) : options.max;
161
- const maxHits = await retrieveQuota;
162
- augmentedRequest[options.requestPropertyName] = {
163
- limit: maxHits,
164
- current: totalHits,
165
- remaining: Math.max(maxHits - totalHits, 0),
166
- resetTime
167
- };
168
- if (options.legacyHeaders && !response.headersSent) {
169
- response.setHeader("X-RateLimit-Limit", maxHits);
170
- response.setHeader("X-RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
171
- if (resetTime instanceof Date) {
172
- response.setHeader("Date", new Date().toUTCString());
173
- response.setHeader("X-RateLimit-Reset", Math.ceil(resetTime.getTime() / 1e3));
161
+ const middleware = handleAsyncErrors(
162
+ async (request, response, next) => {
163
+ const skip = await options.skip(request, response);
164
+ if (skip) {
165
+ next();
166
+ return;
174
167
  }
175
- }
176
- if (options.standardHeaders && !response.headersSent) {
177
- response.setHeader("RateLimit-Limit", maxHits);
178
- response.setHeader("RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
179
- if (resetTime) {
180
- const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
181
- response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
168
+ const augmentedRequest = request;
169
+ const key = await options.keyGenerator(request, response);
170
+ const { totalHits, resetTime } = await options.store.increment(key);
171
+ const retrieveQuota = typeof options.max === "function" ? options.max(request, response) : options.max;
172
+ const maxHits = await retrieveQuota;
173
+ augmentedRequest[options.requestPropertyName] = {
174
+ limit: maxHits,
175
+ current: totalHits,
176
+ remaining: Math.max(maxHits - totalHits, 0),
177
+ resetTime
178
+ };
179
+ if (options.legacyHeaders && !response.headersSent) {
180
+ response.setHeader("X-RateLimit-Limit", maxHits);
181
+ response.setHeader(
182
+ "X-RateLimit-Remaining",
183
+ augmentedRequest[options.requestPropertyName].remaining
184
+ );
185
+ if (resetTime instanceof Date) {
186
+ response.setHeader("Date", new Date().toUTCString());
187
+ response.setHeader(
188
+ "X-RateLimit-Reset",
189
+ Math.ceil(resetTime.getTime() / 1e3)
190
+ );
191
+ }
182
192
  }
183
- }
184
- if (options.skipFailedRequests || options.skipSuccessfulRequests) {
185
- let decremented = false;
186
- const decrementKey = async () => {
187
- if (!decremented) {
188
- await options.store.decrement(key);
189
- decremented = true;
193
+ if (options.standardHeaders && !response.headersSent) {
194
+ response.setHeader("RateLimit-Limit", maxHits);
195
+ response.setHeader(
196
+ "RateLimit-Remaining",
197
+ augmentedRequest[options.requestPropertyName].remaining
198
+ );
199
+ if (resetTime) {
200
+ const deltaSeconds = Math.ceil(
201
+ (resetTime.getTime() - Date.now()) / 1e3
202
+ );
203
+ response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
190
204
  }
191
- };
192
- if (options.skipFailedRequests) {
193
- response.on("finish", async () => {
194
- if (!options.requestWasSuccessful(request, response))
195
- await decrementKey();
196
- });
197
- response.on("close", async () => {
198
- if (!response.writableEnded)
199
- await decrementKey();
200
- });
201
- response.on("error", async () => {
202
- await decrementKey();
203
- });
204
205
  }
205
- if (options.skipSuccessfulRequests) {
206
- response.on("finish", async () => {
207
- if (options.requestWasSuccessful(request, response))
206
+ if (options.skipFailedRequests || options.skipSuccessfulRequests) {
207
+ let decremented = false;
208
+ const decrementKey = async () => {
209
+ if (!decremented) {
210
+ await options.store.decrement(key);
211
+ decremented = true;
212
+ }
213
+ };
214
+ if (options.skipFailedRequests) {
215
+ response.on("finish", async () => {
216
+ if (!options.requestWasSuccessful(request, response))
217
+ await decrementKey();
218
+ });
219
+ response.on("close", async () => {
220
+ if (!response.writableEnded)
221
+ await decrementKey();
222
+ });
223
+ response.on("error", async () => {
208
224
  await decrementKey();
209
- });
225
+ });
226
+ }
227
+ if (options.skipSuccessfulRequests) {
228
+ response.on("finish", async () => {
229
+ if (options.requestWasSuccessful(request, response))
230
+ await decrementKey();
231
+ });
232
+ }
210
233
  }
211
- }
212
- if (maxHits && totalHits === maxHits + 1) {
213
- options.onLimitReached(request, response, options);
214
- }
215
- if (maxHits && totalHits > maxHits) {
216
- if ((options.legacyHeaders || options.standardHeaders) && !response.headersSent) {
217
- response.setHeader("Retry-After", Math.ceil(options.windowMs / 1e3));
234
+ if (maxHits && totalHits === maxHits + 1) {
235
+ options.onLimitReached(request, response, options);
236
+ }
237
+ if (maxHits && totalHits > maxHits) {
238
+ if ((options.legacyHeaders || options.standardHeaders) && !response.headersSent) {
239
+ response.setHeader("Retry-After", Math.ceil(options.windowMs / 1e3));
240
+ }
241
+ options.handler(request, response, next, options);
242
+ return;
218
243
  }
219
- options.handler(request, response, next, options);
220
- return;
244
+ next();
221
245
  }
222
- next();
223
- });
246
+ );
224
247
  middleware.resetKey = options.store.resetKey.bind(options.store);
225
248
  return middleware;
226
249
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by dts-bundle-generator v6.12.0
1
+ // Generated by dts-bundle-generator v7.0.0
2
2
 
3
3
  import { NextFunction, Request, RequestHandler, Response } from 'express';
4
4
 
@@ -66,7 +66,7 @@ export declare type RateLimitRequestHandler = RequestHandler & {
66
66
  *
67
67
  * @deprecated 6.x - Implement the `Store` interface instead.
68
68
  */
69
- export interface LegacyStore {
69
+ export declare type LegacyStore = {
70
70
  /**
71
71
  * Method to increment a client's hit counter.
72
72
  *
@@ -90,11 +90,11 @@ export interface LegacyStore {
90
90
  * Method to reset everyone's hit counter.
91
91
  */
92
92
  resetAll?: () => void;
93
- }
93
+ };
94
94
  /**
95
95
  * An interface that all hit counter stores must implement.
96
96
  */
97
- export interface Store {
97
+ export declare type Store = {
98
98
  /**
99
99
  * Method that initializes the store, and has access to the options passed to
100
100
  * the middleware too.
@@ -130,11 +130,11 @@ export interface Store {
130
130
  * Method to shutdown the store, stop timers, and release all resources.
131
131
  */
132
132
  shutdown?: () => Promise<void> | void;
133
- }
133
+ };
134
134
  /**
135
135
  * The configuration options for the rate limiter.
136
136
  */
137
- export interface Options {
137
+ export declare type Options = {
138
138
  /**
139
139
  * How long we should remember the requests.
140
140
  *
@@ -252,7 +252,7 @@ export interface Options {
252
252
  * @deprecated 6.x - This option was renamed to `standardHeaders`.
253
253
  */
254
254
  draft_polli_ratelimit_headers?: boolean;
255
- }
255
+ };
256
256
  /**
257
257
  * The extended request object that includes information about the client's
258
258
  * rate limit.
@@ -264,12 +264,12 @@ export declare type AugmentedRequest = Request & {
264
264
  * The rate limit related information for each client included in the
265
265
  * Express request object.
266
266
  */
267
- export interface RateLimitInfo {
267
+ export declare type RateLimitInfo = {
268
268
  readonly limit: number;
269
269
  readonly current: number;
270
270
  readonly remaining: number;
271
271
  readonly resetTime: Date | undefined;
272
- }
272
+ };
273
273
  /**
274
274
  *
275
275
  * Create an instance of IP rate-limiting middleware for Express.
package/dist/index.mjs CHANGED
@@ -51,11 +51,14 @@ var promisifyStore = (passedStore) => {
51
51
  class PromisifiedStore {
52
52
  async increment(key) {
53
53
  return new Promise((resolve, reject) => {
54
- legacyStore.incr(key, (error, totalHits, resetTime) => {
55
- if (error)
56
- reject(error);
57
- resolve({ totalHits, resetTime });
58
- });
54
+ legacyStore.incr(
55
+ key,
56
+ (error, totalHits, resetTime) => {
57
+ if (error)
58
+ reject(error);
59
+ resolve({ totalHits, resetTime });
60
+ }
61
+ );
59
62
  });
60
63
  }
61
64
  async decrement(key) {
@@ -88,13 +91,18 @@ var parseOptions = (passedOptions) => {
88
91
  skip: (_request, _response) => false,
89
92
  keyGenerator(request, _response) {
90
93
  if (!request.ip) {
91
- console.error("WARN | `express-rate-limit` | `request.ip` is undefined. You can avoid this by providing a custom `keyGenerator` function, but it may be indicative of a larger issue.");
94
+ console.error(
95
+ "WARN | `express-rate-limit` | `request.ip` is undefined. You can avoid this by providing a custom `keyGenerator` function, but it may be indicative of a larger issue."
96
+ );
92
97
  }
93
98
  return request.ip;
94
99
  },
95
100
  async handler(request, response, _next, _optionsUsed) {
96
101
  response.status(config.statusCode);
97
- const message = typeof config.message === "function" ? await config.message(request, response) : config.message;
102
+ const message = typeof config.message === "function" ? await config.message(
103
+ request,
104
+ response
105
+ ) : config.message;
98
106
  if (!response.writableEnded) {
99
107
  response.send(message != null ? message : "Too many requests, please try again later.");
100
108
  }
@@ -105,7 +113,9 @@ var parseOptions = (passedOptions) => {
105
113
  store: promisifyStore((_c = notUndefinedOptions.store) != null ? _c : new MemoryStore())
106
114
  };
107
115
  if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || typeof config.store.resetAll !== "undefined" && typeof config.store.resetAll !== "function" || typeof config.store.init !== "undefined" && typeof config.store.init !== "function") {
108
- throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");
116
+ throw new TypeError(
117
+ "An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
118
+ );
109
119
  }
110
120
  return config;
111
121
  };
@@ -120,79 +130,92 @@ var rateLimit = (passedOptions) => {
120
130
  const options = parseOptions(passedOptions != null ? passedOptions : {});
121
131
  if (typeof options.store.init === "function")
122
132
  options.store.init(options);
123
- const middleware = handleAsyncErrors(async (request, response, next) => {
124
- const skip = await options.skip(request, response);
125
- if (skip) {
126
- next();
127
- return;
128
- }
129
- const augmentedRequest = request;
130
- const key = await options.keyGenerator(request, response);
131
- const { totalHits, resetTime } = await options.store.increment(key);
132
- const retrieveQuota = typeof options.max === "function" ? options.max(request, response) : options.max;
133
- const maxHits = await retrieveQuota;
134
- augmentedRequest[options.requestPropertyName] = {
135
- limit: maxHits,
136
- current: totalHits,
137
- remaining: Math.max(maxHits - totalHits, 0),
138
- resetTime
139
- };
140
- if (options.legacyHeaders && !response.headersSent) {
141
- response.setHeader("X-RateLimit-Limit", maxHits);
142
- response.setHeader("X-RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
143
- if (resetTime instanceof Date) {
144
- response.setHeader("Date", new Date().toUTCString());
145
- response.setHeader("X-RateLimit-Reset", Math.ceil(resetTime.getTime() / 1e3));
133
+ const middleware = handleAsyncErrors(
134
+ async (request, response, next) => {
135
+ const skip = await options.skip(request, response);
136
+ if (skip) {
137
+ next();
138
+ return;
146
139
  }
147
- }
148
- if (options.standardHeaders && !response.headersSent) {
149
- response.setHeader("RateLimit-Limit", maxHits);
150
- response.setHeader("RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
151
- if (resetTime) {
152
- const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
153
- response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
140
+ const augmentedRequest = request;
141
+ const key = await options.keyGenerator(request, response);
142
+ const { totalHits, resetTime } = await options.store.increment(key);
143
+ const retrieveQuota = typeof options.max === "function" ? options.max(request, response) : options.max;
144
+ const maxHits = await retrieveQuota;
145
+ augmentedRequest[options.requestPropertyName] = {
146
+ limit: maxHits,
147
+ current: totalHits,
148
+ remaining: Math.max(maxHits - totalHits, 0),
149
+ resetTime
150
+ };
151
+ if (options.legacyHeaders && !response.headersSent) {
152
+ response.setHeader("X-RateLimit-Limit", maxHits);
153
+ response.setHeader(
154
+ "X-RateLimit-Remaining",
155
+ augmentedRequest[options.requestPropertyName].remaining
156
+ );
157
+ if (resetTime instanceof Date) {
158
+ response.setHeader("Date", new Date().toUTCString());
159
+ response.setHeader(
160
+ "X-RateLimit-Reset",
161
+ Math.ceil(resetTime.getTime() / 1e3)
162
+ );
163
+ }
154
164
  }
155
- }
156
- if (options.skipFailedRequests || options.skipSuccessfulRequests) {
157
- let decremented = false;
158
- const decrementKey = async () => {
159
- if (!decremented) {
160
- await options.store.decrement(key);
161
- decremented = true;
165
+ if (options.standardHeaders && !response.headersSent) {
166
+ response.setHeader("RateLimit-Limit", maxHits);
167
+ response.setHeader(
168
+ "RateLimit-Remaining",
169
+ augmentedRequest[options.requestPropertyName].remaining
170
+ );
171
+ if (resetTime) {
172
+ const deltaSeconds = Math.ceil(
173
+ (resetTime.getTime() - Date.now()) / 1e3
174
+ );
175
+ response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
162
176
  }
163
- };
164
- if (options.skipFailedRequests) {
165
- response.on("finish", async () => {
166
- if (!options.requestWasSuccessful(request, response))
167
- await decrementKey();
168
- });
169
- response.on("close", async () => {
170
- if (!response.writableEnded)
171
- await decrementKey();
172
- });
173
- response.on("error", async () => {
174
- await decrementKey();
175
- });
176
177
  }
177
- if (options.skipSuccessfulRequests) {
178
- response.on("finish", async () => {
179
- if (options.requestWasSuccessful(request, response))
178
+ if (options.skipFailedRequests || options.skipSuccessfulRequests) {
179
+ let decremented = false;
180
+ const decrementKey = async () => {
181
+ if (!decremented) {
182
+ await options.store.decrement(key);
183
+ decremented = true;
184
+ }
185
+ };
186
+ if (options.skipFailedRequests) {
187
+ response.on("finish", async () => {
188
+ if (!options.requestWasSuccessful(request, response))
189
+ await decrementKey();
190
+ });
191
+ response.on("close", async () => {
192
+ if (!response.writableEnded)
193
+ await decrementKey();
194
+ });
195
+ response.on("error", async () => {
180
196
  await decrementKey();
181
- });
197
+ });
198
+ }
199
+ if (options.skipSuccessfulRequests) {
200
+ response.on("finish", async () => {
201
+ if (options.requestWasSuccessful(request, response))
202
+ await decrementKey();
203
+ });
204
+ }
182
205
  }
183
- }
184
- if (maxHits && totalHits === maxHits + 1) {
185
- options.onLimitReached(request, response, options);
186
- }
187
- if (maxHits && totalHits > maxHits) {
188
- if ((options.legacyHeaders || options.standardHeaders) && !response.headersSent) {
189
- response.setHeader("Retry-After", Math.ceil(options.windowMs / 1e3));
206
+ if (maxHits && totalHits === maxHits + 1) {
207
+ options.onLimitReached(request, response, options);
208
+ }
209
+ if (maxHits && totalHits > maxHits) {
210
+ if ((options.legacyHeaders || options.standardHeaders) && !response.headersSent) {
211
+ response.setHeader("Retry-After", Math.ceil(options.windowMs / 1e3));
212
+ }
213
+ options.handler(request, response, next, options);
214
+ return;
190
215
  }
191
- options.handler(request, response, next, options);
192
- return;
216
+ next();
193
217
  }
194
- next();
195
- });
218
+ );
196
219
  middleware.resetKey = options.store.resetKey.bind(options.store);
197
220
  return middleware;
198
221
  };
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "express-rate-limit",
3
- "version": "6.6.0",
3
+ "version": "6.7.0",
4
4
  "description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
5
5
  "author": {
6
6
  "name": "Nathan Friedly",
7
7
  "url": "http://nfriedly.com/"
8
8
  },
9
9
  "license": "MIT",
10
- "homepage": "https://github.com/nfriedly/express-rate-limit",
11
- "repository": "https://github.com/nfriedly/express-rate-limit",
10
+ "homepage": "https://github.com/express-rate-limit/express-rate-limit",
11
+ "repository": "https://github.com/express-rate-limit/express-rate-limit",
12
12
  "keywords": [
13
13
  "express-rate-limit",
14
14
  "express",
@@ -71,24 +71,24 @@
71
71
  "express": "^4 || ^5"
72
72
  },
73
73
  "devDependencies": {
74
- "@jest/globals": "28.1.3",
75
- "@types/express": "4.17.13",
76
- "@types/jest": "28.1.6",
77
- "@types/node": "18.0.6",
74
+ "@jest/globals": "29.3.1",
75
+ "@types/express": "4.17.14",
76
+ "@types/jest": "29.2.3",
77
+ "@types/node": "18.11.9",
78
78
  "@types/supertest": "2.0.12",
79
79
  "cross-env": "7.0.3",
80
- "del-cli": "4.0.1",
81
- "dts-bundle-generator": "6.12.0",
82
- "esbuild": "0.14.49",
83
- "express": "4.18.1",
84
- "husky": "8.0.1",
85
- "jest": "28.1.3",
80
+ "del-cli": "5.0.0",
81
+ "dts-bundle-generator": "7.0.0",
82
+ "esbuild": "0.15.14",
83
+ "express": "4.18.2",
84
+ "husky": "8.0.2",
85
+ "jest": "29.3.1",
86
86
  "lint-staged": "13.0.3",
87
87
  "npm-run-all": "4.1.5",
88
- "supertest": "6.2.4",
89
- "ts-jest": "28.0.7",
88
+ "supertest": "6.3.1",
89
+ "ts-jest": "29.0.3",
90
90
  "ts-node": "10.9.1",
91
- "typescript": "4.7.4",
91
+ "typescript": "4.8.4",
92
92
  "xo": "0.49.0"
93
93
  },
94
94
  "xo": {
@@ -100,7 +100,8 @@
100
100
  "@typescript-eslint/consistent-indexed-object-style": [
101
101
  "error",
102
102
  "index-signature"
103
- ]
103
+ ],
104
+ "n/no-unsupported-features/es-syntax": 0
104
105
  }
105
106
  },
106
107
  "prettier": {
package/readme.md CHANGED
@@ -1,8 +1,18 @@
1
1
  # <div align="center"> Express Rate Limit </div>
2
2
 
3
+ ---
4
+
5
+ Sponsored by [Zuplo](https://zuplo.link/express-rate-limit) a fully-managed API
6
+ Gateway for developers. Add
7
+ [dynamic rate-limiting](https://zuplo.link/dynamic-rate-limiting),
8
+ authentication and more to any API in minutes. Learn more at
9
+ [zuplo.com](https://zuplo.link/express-rate-limit)
10
+
11
+ ---
12
+
3
13
  <div align="center">
4
14
 
5
- [![Tests](https://github.com/nfriedly/express-rate-limit/workflows/Test/badge.svg)](https://github.com/nfriedly/express-rate-limit/actions)
15
+ [![Tests](https://github.com/express-rate-limit/express-rate-limit/workflows/Test/badge.svg)](https://github.com/express-rate-limit/express-rate-limit/actions)
6
16
  [![npm version](https://img.shields.io/npm/v/express-rate-limit.svg)](https://npmjs.org/package/express-rate-limit 'View this project on NPM')
7
17
  [![npm downloads](https://img.shields.io/npm/dm/express-rate-limit)](https://www.npmjs.com/package/express-rate-limit)
8
18
 
@@ -41,9 +51,9 @@ From Github Releases:
41
51
 
42
52
  ```sh
43
53
  # Using npm
44
- > npm install https://github.com/nfriedly/express-rate-limit/releases/download/v{version}/express-rate-limit.tgz
54
+ > npm install https://github.com/express-rate-limit/express-rate-limit/releases/download/v{version}/express-rate-limit.tgz
45
55
  # Using yarn or pnpm
46
- > yarn/pnpm add https://github.com/nfriedly/express-rate-limit/releases/download/v{version}/express-rate-limit.tgz
56
+ > yarn/pnpm add https://github.com/express-rate-limit/express-rate-limit/releases/download/v{version}/express-rate-limit.tgz
47
57
  ```
48
58
 
49
59
  Replace `{version}` with the version of the package that you want to your, e.g.:
@@ -180,10 +190,9 @@ app.get('/ip', (request, response) => response.send(request.ip))
180
190
  ```
181
191
 
182
192
  Go to `/ip` and see the IP address returned in the response. If it matches your
183
- IP address (which you can get by going to http://ip.nfriedly.com/ or
184
- https://api.ipify.org/), then the number of proxies is correct and the rate
185
- limiter should now work correctly. If not, then keep increasing the number until
186
- it does.
193
+ public IP address, then the number of proxies is correct and the rate limiter
194
+ should now work correctly. If not, then keep increasing the number until it
195
+ does.
187
196
 
188
197
  For more information about the `trust proxy` setting, take a look at the
189
198
  [official Express documentation](https://expressjs.com/en/guide/behind-proxies.html).
@@ -387,7 +396,7 @@ objects that is called when a client has reached their rate limit, and will be
387
396
  rate limited on their next request.
388
397
 
389
398
  This method was
390
- [deprecated in v6](https://github.com/nfriedly/express-rate-limit/releases/v6.0.0) -
399
+ [deprecated in v6](https://github.com/express-rate-limit/express-rate-limit/releases/v6.0.0) -
391
400
  Please use a custom `handler` that checks the number of hits instead.
392
401
 
393
402
  ### `skip`
@@ -456,7 +465,7 @@ Here is a list of external stores:
456
465
  | [`precise-memory-rate-limit`](https://www.npmjs.com/package/precise-memory-rate-limit) | A memory store similar to the built-in one, except that it stores a distinct timestamp for each key. | Legacy |
457
466
 
458
467
  Take a look at
459
- [this guide](https://github.com/nfriedly/express-rate-limit/wiki/Creating-Your-Own-Store)
468
+ [this guide](https://github.com/express-rate-limit/express-rate-limit/wiki/Creating-Your-Own-Store)
460
469
  if you wish to create your own store.
461
470
 
462
471
  ## Request API
@@ -480,9 +489,10 @@ method.
480
489
  ## Issues and Contributing
481
490
 
482
491
  If you encounter a bug or want to see something added/changed, please go ahead
483
- and [open an issue](https://github.com/nfriedly/express-rate-limit/issues/new)!
492
+ and
493
+ [open an issue](https://github.com/nfriexpress-rate-limitedly/express-rate-limit/issues/new)!
484
494
  If you need help with something, feel free to
485
- [start a discussion](https://github.com/nfriedly/express-rate-limit/discussions/new)!
495
+ [start a discussion](https://github.com/express-rate-limit/express-rate-limit/discussions/new)!
486
496
 
487
497
  If you wish to contribute to the library, thanks! First, please read
488
498
  [the contributing guide](contributing.md). Then you can pick up any issue and