revert: newly compiled typescript wrapper

This commit is contained in:
Rim 2025-04-19 23:56:28 -04:00
parent 30ec61f44d
commit 898fe19823
15 changed files with 848 additions and 3777 deletions

301
node_modules/.package-lock.json generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,838 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// source/index.ts
var source_exports = {};
__export(source_exports, {
MemoryStore: () => MemoryStore,
default: () => lib_default,
rateLimit: () => lib_default
});
module.exports = __toCommonJS(source_exports);
// source/headers.ts
var import_node_buffer = require("buffer");
var import_node_crypto = require("crypto");
var SUPPORTED_DRAFT_VERSIONS = ["draft-6", "draft-7", "draft-8"];
var getResetSeconds = (resetTime, windowMs) => {
let resetSeconds = void 0;
if (resetTime) {
const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
resetSeconds = Math.max(0, deltaSeconds);
} else if (windowMs) {
resetSeconds = Math.ceil(windowMs / 1e3);
}
return resetSeconds;
};
var getPartitionKey = (key) => {
const hash = (0, import_node_crypto.createHash)("sha256");
hash.update(key);
const partitionKey = hash.digest("hex").slice(0, 12);
return import_node_buffer.Buffer.from(partitionKey).toString("base64");
};
var setLegacyHeaders = (response, info) => {
if (response.headersSent)
return;
response.setHeader("X-RateLimit-Limit", info.limit.toString());
response.setHeader("X-RateLimit-Remaining", info.remaining.toString());
if (info.resetTime instanceof Date) {
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
response.setHeader(
"X-RateLimit-Reset",
Math.ceil(info.resetTime.getTime() / 1e3).toString()
);
}
};
var setDraft6Headers = (response, info, windowMs) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime);
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
response.setHeader("RateLimit-Limit", info.limit.toString());
response.setHeader("RateLimit-Remaining", info.remaining.toString());
if (resetSeconds)
response.setHeader("RateLimit-Reset", resetSeconds.toString());
};
var setDraft7Headers = (response, info, windowMs) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
response.setHeader(
"RateLimit",
`limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`
);
};
var setDraft8Headers = (response, info, windowMs, name, key) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
const partitionKey = getPartitionKey(key);
const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;
const header = `r=${info.remaining}; t=${resetSeconds}`;
response.append("RateLimit-Policy", `"${name}"; ${policy}`);
response.append("RateLimit", `"${name}"; ${header}`);
};
var setRetryAfterHeader = (response, info, windowMs) => {
if (response.headersSent)
return;
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
response.setHeader("Retry-After", resetSeconds.toString());
};
// source/validations.ts
var import_node_net = require("net");
var ValidationError = class extends Error {
/**
* The code must be a string, in snake case and all capital, that starts with
* the substring `ERR_ERL_`.
*
* The message must be a string, starting with an uppercase character,
* describing the issue in detail.
*/
constructor(code, message) {
const url = `https://express-rate-limit.github.io/${code}/`;
super(`${message} See ${url} for more information.`);
this.name = this.constructor.name;
this.code = code;
this.help = url;
}
};
var ChangeWarning = class extends ValidationError {
};
var usedStores = /* @__PURE__ */ new Set();
var singleCountKeys = /* @__PURE__ */ new WeakMap();
var validations = {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
enabled: {
default: true
},
// Should be EnabledValidations type, but that's a circular reference
disable() {
for (const k of Object.keys(this.enabled))
this.enabled[k] = false;
},
/**
* Checks whether the IP address is valid, and that it does not have a port
* number in it.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
*
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
*
* @returns {void}
*/
ip(ip) {
if (ip === void 0) {
throw new ValidationError(
"ERR_ERL_UNDEFINED_IP_ADDRESS",
`An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`
);
}
if (!(0, import_node_net.isIP)(ip)) {
throw new ValidationError(
"ERR_ERL_INVALID_IP_ADDRESS",
`An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`
);
}
},
/**
* Makes sure the trust proxy setting is not set to `true`.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
trustProxy(request) {
if (request.app.get("trust proxy") === true) {
throw new ValidationError(
"ERR_ERL_PERMISSIVE_TRUST_PROXY",
`The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`
);
}
},
/**
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
* header is present.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
xForwardedForHeader(request) {
if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
throw new ValidationError(
"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR",
`The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`
);
}
},
/**
* Ensures totalHits value from store is a positive integer.
*
* @param hits {any} - The `totalHits` returned by the store.
*/
positiveHits(hits) {
if (typeof hits !== "number" || hits < 1 || hits !== Math.round(hits)) {
throw new ValidationError(
"ERR_ERL_INVALID_HITS",
`The totalHits value returned from the store must be a positive integer, got ${hits}`
);
}
},
/**
* Ensures a single store instance is not used with multiple express-rate-limit instances
*/
unsharedStore(store) {
if (usedStores.has(store)) {
const maybeUniquePrefix = store?.localKeys ? "" : " (with a unique prefix)";
throw new ValidationError(
"ERR_ERL_STORE_REUSE",
`A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`
);
}
usedStores.add(store);
},
/**
* Ensures a given key is incremented only once per request.
*
* @param request {Request} - The Express request object.
* @param store {Store} - The store class.
* @param key {string} - The key used to store the client's hit count.
*
* @returns {void}
*/
singleCount(request, store, key) {
let storeKeys = singleCountKeys.get(request);
if (!storeKeys) {
storeKeys = /* @__PURE__ */ new Map();
singleCountKeys.set(request, storeKeys);
}
const storeKey = store.localKeys ? store : store.constructor.name;
let keys = storeKeys.get(storeKey);
if (!keys) {
keys = [];
storeKeys.set(storeKey, keys);
}
const prefixedKey = `${store.prefix ?? ""}${key}`;
if (keys.includes(prefixedKey)) {
throw new ValidationError(
"ERR_ERL_DOUBLE_COUNT",
`The hit count for ${key} was incremented more than once for a single request.`
);
}
keys.push(prefixedKey);
},
/**
* Warns the user that the behaviour for `max: 0` / `limit: 0` is
* changing in the next major release.
*
* @param limit {number} - The maximum number of hits per client.
*
* @returns {void}
*/
limit(limit) {
if (limit === 0) {
throw new ChangeWarning(
"WRN_ERL_MAX_ZERO",
`Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7`
);
}
},
/**
* Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
* and will be removed in the next major release.
*
* @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
*
* @returns {void}
*/
draftPolliHeaders(draft_polli_ratelimit_headers) {
if (draft_polli_ratelimit_headers) {
throw new ChangeWarning(
"WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS",
`The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`
);
}
},
/**
* Warns the user that the `onLimitReached` option is deprecated and
* will be removed in the next major release.
*
* @param onLimitReached {any | undefined} - The maximum number of hits per client.
*
* @returns {void}
*/
onLimitReached(onLimitReached) {
if (onLimitReached) {
throw new ChangeWarning(
"WRN_ERL_DEPRECATED_ON_LIMIT_REACHED",
`The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.`
);
}
},
/**
* Warns the user when an invalid/unsupported version of the draft spec is passed.
*
* @param version {any | undefined} - The version passed by the user.
*
* @returns {void}
*/
headersDraftVersion(version) {
if (typeof version !== "string" || !SUPPORTED_DRAFT_VERSIONS.includes(version)) {
const versionString = SUPPORTED_DRAFT_VERSIONS.join(", ");
throw new ValidationError(
"ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION",
`standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`
);
}
},
/**
* Warns the user when the selected headers option requires a reset time but
* the store does not provide one.
*
* @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
*
* @returns {void}
*/
headersResetTime(resetTime) {
if (!resetTime) {
throw new ValidationError(
"ERR_ERL_HEADERS_NO_RESET",
`standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`
);
}
},
/**
* Checks the options.validate setting to ensure that only recognized
* validations are enabled or disabled.
*
* If any unrecognized values are found, an error is logged that
* includes the list of supported vaidations.
*/
validationsConfig() {
const supportedValidations = Object.keys(this).filter(
(k) => !["enabled", "disable"].includes(k)
);
supportedValidations.push("default");
for (const key of Object.keys(this.enabled)) {
if (!supportedValidations.includes(key)) {
throw new ValidationError(
"ERR_ERL_UNKNOWN_VALIDATION",
`options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(
", "
)}.`
);
}
}
},
/**
* Checks to see if the instance was created inside of a request handler,
* which would prevent it from working correctly, with the default memory
* store (or any other store with localKeys.)
*/
creationStack(store) {
const { stack } = new Error(
"express-rate-limit validation check (set options.validate.creationStack=false to disable)"
);
if (stack?.includes("Layer.handle [as handle_request]")) {
if (!store.localKeys) {
throw new ValidationError(
"ERR_ERL_CREATED_IN_REQUEST_HANDLER",
"express-rate-limit instance should *usually* be created at app initialization, not when responding to a request."
);
}
throw new ValidationError(
"ERR_ERL_CREATED_IN_REQUEST_HANDLER",
`express-rate-limit instance should be created at app initialization, not when responding to a request.`
);
}
}
};
var getValidations = (_enabled) => {
let enabled;
if (typeof _enabled === "boolean") {
enabled = {
default: _enabled
};
} else {
enabled = {
default: true,
..._enabled
};
}
const wrappedValidations = {
enabled
};
for (const [name, validation] of Object.entries(validations)) {
if (typeof validation === "function")
wrappedValidations[name] = (...args) => {
if (!(enabled[name] ?? enabled.default)) {
return;
}
try {
;
validation.apply(
wrappedValidations,
args
);
} catch (error) {
if (error instanceof ChangeWarning)
console.warn(error);
else
console.error(error);
}
};
}
return wrappedValidations;
};
// source/memory-store.ts
var MemoryStore = class {
constructor() {
/**
* These two maps store usage (requests) and reset time by key (for example, IP
* addresses or API keys).
*
* They are split into two to avoid having to iterate through the entire set to
* determine which ones need reset. Instead, `Client`s are moved from `previous`
* to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients
* left in `previous`, i.e., those that have not made any recent requests, are
* known to be expired and can be deleted in bulk.
*/
this.previous = /* @__PURE__ */ new Map();
this.current = /* @__PURE__ */ new Map();
/**
* Confirmation that the keys incremented in once instance of MemoryStore
* cannot affect other instances.
*/
this.localKeys = true;
}
/**
* Method that initializes the store.
*
* @param options {Options} - The options used to setup the middleware.
*/
init(options) {
this.windowMs = options.windowMs;
if (this.interval)
clearInterval(this.interval);
this.interval = setInterval(() => {
this.clearExpired();
}, this.windowMs);
if (this.interval.unref)
this.interval.unref();
}
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
*
* @public
*/
async get(key) {
return this.current.get(key) ?? this.previous.get(key);
}
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*
* @public
*/
async increment(key) {
const client = this.getClient(key);
const now = Date.now();
if (client.resetTime.getTime() <= now) {
this.resetClient(client, now);
}
client.totalHits++;
return client;
}
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
async decrement(key) {
const client = this.getClient(key);
if (client.totalHits > 0)
client.totalHits--;
}
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
async resetKey(key) {
this.current.delete(key);
this.previous.delete(key);
}
/**
* Method to reset everyone's hit counter.
*
* @public
*/
async resetAll() {
this.current.clear();
this.previous.clear();
}
/**
* Method to stop the timer (if currently running) and prevent any memory
* leaks.
*
* @public
*/
shutdown() {
clearInterval(this.interval);
void this.resetAll();
}
/**
* Recycles a client by setting its hit count to zero, and reset time to
* `windowMs` milliseconds from now.
*
* NOT to be confused with `#resetKey()`, which removes a client from both the
* `current` and `previous` maps.
*
* @param client {Client} - The client to recycle.
* @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
*
* @return {Client} - The modified client that was passed in, to allow for chaining.
*/
resetClient(client, now = Date.now()) {
client.totalHits = 0;
client.resetTime.setTime(now + this.windowMs);
return client;
}
/**
* Retrieves or creates a client, given a key. Also ensures that the client being
* returned is in the `current` map.
*
* @param key {string} - The key under which the client is (or is to be) stored.
*
* @returns {Client} - The requested client.
*/
getClient(key) {
if (this.current.has(key))
return this.current.get(key);
let client;
if (this.previous.has(key)) {
client = this.previous.get(key);
this.previous.delete(key);
} else {
client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };
this.resetClient(client);
}
this.current.set(key, client);
return client;
}
/**
* Move current clients to previous, create a new map for current.
*
* This function is called every `windowMs`.
*/
clearExpired() {
this.previous = this.current;
this.current = /* @__PURE__ */ new Map();
}
};
// source/lib.ts
var isLegacyStore = (store) => (
// Check that `incr` exists but `increment` does not - store authors might want
// to keep both around for backwards compatibility.
typeof store.incr === "function" && typeof store.increment !== "function"
);
var promisifyStore = (passedStore) => {
if (!isLegacyStore(passedStore)) {
return passedStore;
}
const legacyStore = passedStore;
class PromisifiedStore {
async increment(key) {
return new Promise((resolve, reject) => {
legacyStore.incr(
key,
(error, totalHits, resetTime) => {
if (error)
reject(error);
resolve({ totalHits, resetTime });
}
);
});
}
async decrement(key) {
return legacyStore.decrement(key);
}
async resetKey(key) {
return legacyStore.resetKey(key);
}
/* istanbul ignore next */
async resetAll() {
if (typeof legacyStore.resetAll === "function")
return legacyStore.resetAll();
}
}
return new PromisifiedStore();
};
var getOptionsFromConfig = (config) => {
const { validations: validations2, ...directlyPassableEntries } = config;
return {
...directlyPassableEntries,
validate: validations2.enabled
};
};
var omitUndefinedOptions = (passedOptions) => {
const omittedOptions = {};
for (const k of Object.keys(passedOptions)) {
const key = k;
if (passedOptions[key] !== void 0) {
omittedOptions[key] = passedOptions[key];
}
}
return omittedOptions;
};
var parseOptions = (passedOptions) => {
const notUndefinedOptions = omitUndefinedOptions(passedOptions);
const validations2 = getValidations(notUndefinedOptions?.validate ?? true);
validations2.validationsConfig();
validations2.draftPolliHeaders(
// @ts-expect-error see the note above.
notUndefinedOptions.draft_polli_ratelimit_headers
);
validations2.onLimitReached(notUndefinedOptions.onLimitReached);
let standardHeaders = notUndefinedOptions.standardHeaders ?? false;
if (standardHeaders === true)
standardHeaders = "draft-6";
const config = {
windowMs: 60 * 1e3,
limit: passedOptions.max ?? 5,
// `max` is deprecated, but support it anyways.
message: "Too many requests, please try again later.",
statusCode: 429,
legacyHeaders: passedOptions.headers ?? true,
identifier(request, _response) {
let duration = "";
const property = config.requestPropertyName;
const { limit } = request[property];
const seconds = config.windowMs / 1e3;
const minutes = config.windowMs / (1e3 * 60);
const hours = config.windowMs / (1e3 * 60 * 60);
const days = config.windowMs / (1e3 * 60 * 60 * 24);
if (seconds < 60)
duration = `${seconds}sec`;
else if (minutes < 60)
duration = `${minutes}min`;
else if (hours < 24)
duration = `${hours}hr${hours > 1 ? "s" : ""}`;
else
duration = `${days}day${days > 1 ? "s" : ""}`;
return `${limit}-in-${duration}`;
},
requestPropertyName: "rateLimit",
skipFailedRequests: false,
skipSuccessfulRequests: false,
requestWasSuccessful: (_request, response) => response.statusCode < 400,
skip: (_request, _response) => false,
keyGenerator(request, _response) {
validations2.ip(request.ip);
validations2.trustProxy(request);
validations2.xForwardedForHeader(request);
return request.ip;
},
async handler(request, response, _next, _optionsUsed) {
response.status(config.statusCode);
const message = typeof config.message === "function" ? await config.message(
request,
response
) : config.message;
if (!response.writableEnded) {
response.send(message);
}
},
passOnStoreError: false,
// Allow the default options to be overriden by the passed options.
...notUndefinedOptions,
// `standardHeaders` is resolved into a draft version above, use that.
standardHeaders,
// Note that this field is declared after the user's options are spread in,
// so that this field doesn't get overriden with an un-promisified store!
store: promisifyStore(notUndefinedOptions.store ?? new MemoryStore()),
// Print an error to the console if a few known misconfigurations are detected.
validations: validations2
};
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== "function" || config.store.init !== void 0 && typeof config.store.init !== "function") {
throw new TypeError(
"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
);
}
return config;
};
var handleAsyncErrors = (fn) => async (request, response, next) => {
try {
await Promise.resolve(fn(request, response, next)).catch(next);
} catch (error) {
next(error);
}
};
var rateLimit = (passedOptions) => {
const config = parseOptions(passedOptions ?? {});
const options = getOptionsFromConfig(config);
config.validations.creationStack(config.store);
config.validations.unsharedStore(config.store);
if (typeof config.store.init === "function")
config.store.init(options);
const middleware = handleAsyncErrors(
async (request, response, next) => {
const skip = await config.skip(request, response);
if (skip) {
next();
return;
}
const augmentedRequest = request;
const key = await config.keyGenerator(request, response);
let totalHits = 0;
let resetTime;
try {
const incrementResult = await config.store.increment(key);
totalHits = incrementResult.totalHits;
resetTime = incrementResult.resetTime;
} catch (error) {
if (config.passOnStoreError) {
console.error(
"express-rate-limit: error from store, allowing request without rate-limiting.",
error
);
next();
return;
}
throw error;
}
config.validations.positiveHits(totalHits);
config.validations.singleCount(request, config.store, key);
const retrieveLimit = typeof config.limit === "function" ? config.limit(request, response) : config.limit;
const limit = await retrieveLimit;
config.validations.limit(limit);
const info = {
limit,
used: totalHits,
remaining: Math.max(limit - totalHits, 0),
resetTime
};
Object.defineProperty(info, "current", {
configurable: false,
enumerable: false,
value: totalHits
});
augmentedRequest[config.requestPropertyName] = info;
if (config.legacyHeaders && !response.headersSent) {
setLegacyHeaders(response, info);
}
if (config.standardHeaders && !response.headersSent) {
switch (config.standardHeaders) {
case "draft-6": {
setDraft6Headers(response, info, config.windowMs);
break;
}
case "draft-7": {
config.validations.headersResetTime(info.resetTime);
setDraft7Headers(response, info, config.windowMs);
break;
}
case "draft-8": {
const retrieveName = typeof config.identifier === "function" ? config.identifier(request, response) : config.identifier;
const name = await retrieveName;
config.validations.headersResetTime(info.resetTime);
setDraft8Headers(response, info, config.windowMs, name, key);
break;
}
default: {
config.validations.headersDraftVersion(config.standardHeaders);
break;
}
}
}
if (config.skipFailedRequests || config.skipSuccessfulRequests) {
let decremented = false;
const decrementKey = async () => {
if (!decremented) {
await config.store.decrement(key);
decremented = true;
}
};
if (config.skipFailedRequests) {
response.on("finish", async () => {
if (!await config.requestWasSuccessful(request, response))
await decrementKey();
});
response.on("close", async () => {
if (!response.writableEnded)
await decrementKey();
});
response.on("error", async () => {
await decrementKey();
});
}
if (config.skipSuccessfulRequests) {
response.on("finish", async () => {
if (await config.requestWasSuccessful(request, response))
await decrementKey();
});
}
}
config.validations.disable();
if (totalHits > limit) {
if (config.legacyHeaders || config.standardHeaders) {
setRetryAfterHeader(response, info, config.windowMs);
}
config.handler(request, response, next, options);
return;
}
next();
}
);
const getThrowFn = () => {
throw new Error("The current store does not support the get/getKey method");
};
middleware.resetKey = config.store.resetKey.bind(config.store);
middleware.getKey = typeof config.store.get === "function" ? config.store.get.bind(config.store) : getThrowFn;
return middleware;
};
var lib_default = rateLimit;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MemoryStore,
rateLimit
});
module.exports = rateLimit; module.exports.default = rateLimit; module.exports.rateLimit = rateLimit; module.exports.MemoryStore = MemoryStore;

View File

@ -1,584 +0,0 @@
// Generated by dts-bundle-generator v8.0.1
import { NextFunction, Request, RequestHandler, Response } from 'express';
declare const validations: {
enabled: {
[key: string]: boolean;
};
disable(): void;
/**
* Checks whether the IP address is valid, and that it does not have a port
* number in it.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
*
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
*
* @returns {void}
*/
ip(ip: string | undefined): void;
/**
* Makes sure the trust proxy setting is not set to `true`.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
trustProxy(request: Request): void;
/**
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
* header is present.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
xForwardedForHeader(request: Request): void;
/**
* Ensures totalHits value from store is a positive integer.
*
* @param hits {any} - The `totalHits` returned by the store.
*/
positiveHits(hits: any): void;
/**
* Ensures a single store instance is not used with multiple express-rate-limit instances
*/
unsharedStore(store: Store): void;
/**
* Ensures a given key is incremented only once per request.
*
* @param request {Request} - The Express request object.
* @param store {Store} - The store class.
* @param key {string} - The key used to store the client's hit count.
*
* @returns {void}
*/
singleCount(request: Request, store: Store, key: string): void;
/**
* Warns the user that the behaviour for `max: 0` / `limit: 0` is
* changing in the next major release.
*
* @param limit {number} - The maximum number of hits per client.
*
* @returns {void}
*/
limit(limit: number): void;
/**
* Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
* and will be removed in the next major release.
*
* @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
*
* @returns {void}
*/
draftPolliHeaders(draft_polli_ratelimit_headers?: any): void;
/**
* Warns the user that the `onLimitReached` option is deprecated and
* will be removed in the next major release.
*
* @param onLimitReached {any | undefined} - The maximum number of hits per client.
*
* @returns {void}
*/
onLimitReached(onLimitReached?: any): void;
/**
* Warns the user when an invalid/unsupported version of the draft spec is passed.
*
* @param version {any | undefined} - The version passed by the user.
*
* @returns {void}
*/
headersDraftVersion(version?: any): void;
/**
* Warns the user when the selected headers option requires a reset time but
* the store does not provide one.
*
* @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
*
* @returns {void}
*/
headersResetTime(resetTime?: Date): void;
/**
* Checks the options.validate setting to ensure that only recognized
* validations are enabled or disabled.
*
* If any unrecognized values are found, an error is logged that
* includes the list of supported vaidations.
*/
validationsConfig(): void;
/**
* Checks to see if the instance was created inside of a request handler,
* which would prevent it from working correctly, with the default memory
* store (or any other store with localKeys.)
*/
creationStack(store: Store): void;
};
export type Validations = typeof validations;
declare const SUPPORTED_DRAFT_VERSIONS: string[];
/**
* Callback that fires when a client's hit counter is incremented.
*
* @param error {Error | undefined} - The error that occurred, if any.
* @param totalHits {number} - The number of hits for that client so far.
* @param resetTime {Date | undefined} - The time when the counter resets.
*/
export type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
/**
* Method (in the form of middleware) to generate/retrieve a value based on the
* incoming request.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
*
* @returns {T} - The value needed.
*/
export type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param next {NextFunction} - The Express `next` function, can be called to skip responding.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
/**
* Event callback that is triggered on a client's first request that exceeds the limit
* but not for subsequent requests. May be used for logging, etc. Should *not*
* send a response.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
/**
* Data returned from the `Store` when a client's hit counter is incremented.
*
* @property totalHits {number} - The number of hits for that client so far.
* @property resetTime {Date | undefined} - The time when the counter resets.
*/
export type ClientRateLimitInfo = {
totalHits: number;
resetTime: Date | undefined;
};
export type IncrementResponse = ClientRateLimitInfo;
/**
* A modified Express request handler with the rate limit functions.
*/
export type RateLimitRequestHandler = RequestHandler & {
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
getKey: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
};
/**
* An interface that all hit counter stores must implement.
*
* @deprecated 6.x - Implement the `Store` interface instead.
*/
export type LegacyStore = {
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
*/
incr: (key: string, callback: IncrementCallback) => void;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => void;
};
/**
* An interface that all hit counter stores must implement.
*/
export type Store = {
/**
* Method that initializes the store, and has access to the options passed to
* the middleware too.
*
* @param options {Options} - The options used to setup the middleware.
*/
init?: (options: Options) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
get?: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {IncrementResponse | undefined} - The number of hits and reset time for that client.
*/
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => Promise<void> | void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => Promise<void> | void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => Promise<void> | void;
/**
* Method to shutdown the store, stop timers, and release all resources.
*/
shutdown?: () => Promise<void> | void;
/**
* Flag to indicate that keys incremented in one instance of this store can
* not affect other instances. Typically false if a database is used, true for
* MemoryStore.
*
* Used to help detect double-counting misconfigurations.
*/
localKeys?: boolean;
/**
* Optional value that the store prepends to keys
*
* Used by the double-count check to avoid false-positives when a key is counted twice, but with different prefixes
*/
prefix?: string;
};
export type DraftHeadersVersion = (typeof SUPPORTED_DRAFT_VERSIONS)[number];
/**
* Validate configuration object for enabling or disabling specific validations.
*
* The keys must also be keys in the validations object, except `enable`, `disable`,
* and `default`.
*/
export type EnabledValidations = {
[key in keyof Omit<Validations, "enabled" | "disable"> | "default"]?: boolean;
};
/**
* The configuration options for the rate limiter.
*/
export type Options = {
/**
* How long we should remember the requests.
*
* Defaults to `60000` ms (= 1 minute).
*/
windowMs: number;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* Defaults to `5`.
*/
limit: number | ValueDeterminingMiddleware<number>;
/**
* The response body to send back when a client is rate limited.
*
* Defaults to `'Too many requests, please try again later.'`
*/
message: any | ValueDeterminingMiddleware<any>;
/**
* The HTTP status code to send back when a client is rate limited.
*
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
*/
statusCode: number;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* Defaults to `true` (for backward compatibility).
*/
legacyHeaders: boolean;
/**
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
*
* Defaults to `false` (for backward compatibility, but its use is recommended).
*/
standardHeaders: boolean | DraftHeadersVersion;
/**
* The name used to identify the quota policy in the `RateLimit` headers as per
* the 8th draft of the IETF specification.
*
* Defaults to `{limit}-in-{window}`.
*/
identifier: string | ValueDeterminingMiddleware<string>;
/**
* The name of the property on the request object to store the rate limit info.
*
* Defaults to `rateLimit`.
*/
requestPropertyName: string;
/**
* If `true`, the library will (by default) skip all requests that have a 4XX
* or 5XX status.
*
* Defaults to `false`.
*/
skipFailedRequests: boolean;
/**
* If `true`, the library will (by default) skip all requests that have a
* status code less than 400.
*
* Defaults to `false`.
*/
skipSuccessfulRequests: boolean;
/**
* Method to generate custom identifiers for clients.
*
* By default, the client's IP address is used.
*/
keyGenerator: ValueDeterminingMiddleware<string>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* By default, sends back the `statusCode` and `message` set via the options.
*/
handler: RateLimitExceededEventHandler;
/**
* Method (in the form of middleware) to determine whether or not this request
* counts towards a client's quota.
*
* By default, skips no requests.
*/
skip: ValueDeterminingMiddleware<boolean>;
/**
* Method to determine whether or not the request counts as 'succesful'. Used
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
*
* By default, requests with a response status code less than 400 are considered
* successful.
*/
requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
/**
* The `Store` to use to store the hit count for each client.
*
* By default, the built-in `MemoryStore` will be used.
*/
store: Store | LegacyStore;
/**
* The list of validation checks that should run.
*/
validate: boolean | EnabledValidations;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
*/
headers?: boolean;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* @deprecated 7.x - This option was renamed to `limit`. However, it will not
* be removed from the library in the foreseeable future.
*/
max?: number | ValueDeterminingMiddleware<number>;
/**
* If the Store generates an error, allow the request to pass.
*/
passOnStoreError: boolean;
};
/**
* The extended request object that includes information about the client's
* rate limit.
*/
export type AugmentedRequest = Request & {
[key: string]: RateLimitInfo;
};
/**
* The rate limit related information for each client included in the
* Express request object.
*/
export type RateLimitInfo = {
limit: number;
used: number;
remaining: number;
resetTime: Date | undefined;
};
/**
*
* Create an instance of IP rate-limiting middleware for Express.
*
* @param passedOptions {Options} - Options to configure the rate limiter.
*
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
*
* @public
*/
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
/**
* The record that stores information about a client - namely, how many times
* they have hit the endpoint, and when their hit count resets.
*
* Similar to `ClientRateLimitInfo`, except `resetTime` is a compulsory field.
*/
export type Client = {
totalHits: number;
resetTime: Date;
};
/**
* A `Store` that stores the hit count for each client in memory.
*
* @public
*/
export declare class MemoryStore implements Store {
/**
* The duration of time before which all hit counts are reset (in milliseconds).
*/
windowMs: number;
/**
* These two maps store usage (requests) and reset time by key (for example, IP
* addresses or API keys).
*
* They are split into two to avoid having to iterate through the entire set to
* determine which ones need reset. Instead, `Client`s are moved from `previous`
* to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients
* left in `previous`, i.e., those that have not made any recent requests, are
* known to be expired and can be deleted in bulk.
*/
previous: Map<string, Client>;
current: Map<string, Client>;
/**
* A reference to the active timer.
*/
interval?: NodeJS.Timeout;
/**
* Confirmation that the keys incremented in once instance of MemoryStore
* cannot affect other instances.
*/
localKeys: boolean;
/**
* Method that initializes the store.
*
* @param options {Options} - The options used to setup the middleware.
*/
init(options: Options): void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
*
* @public
*/
get(key: string): Promise<ClientRateLimitInfo | undefined>;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*
* @public
*/
increment(key: string): Promise<ClientRateLimitInfo>;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
decrement(key: string): Promise<void>;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
resetKey(key: string): Promise<void>;
/**
* Method to reset everyone's hit counter.
*
* @public
*/
resetAll(): Promise<void>;
/**
* Method to stop the timer (if currently running) and prevent any memory
* leaks.
*
* @public
*/
shutdown(): void;
/**
* Recycles a client by setting its hit count to zero, and reset time to
* `windowMs` milliseconds from now.
*
* NOT to be confused with `#resetKey()`, which removes a client from both the
* `current` and `previous` maps.
*
* @param client {Client} - The client to recycle.
* @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
*
* @return {Client} - The modified client that was passed in, to allow for chaining.
*/
private resetClient;
/**
* Retrieves or creates a client, given a key. Also ensures that the client being
* returned is in the `current` map.
*
* @param key {string} - The key under which the client is (or is to be) stored.
*
* @returns {Client} - The requested client.
*/
private getClient;
/**
* Move current clients to previous, create a new map for current.
*
* This function is called every `windowMs`.
*/
private clearExpired;
}
export {
rateLimit as default,
};
export {};

View File

@ -1,584 +0,0 @@
// Generated by dts-bundle-generator v8.0.1
import { NextFunction, Request, RequestHandler, Response } from 'express';
declare const validations: {
enabled: {
[key: string]: boolean;
};
disable(): void;
/**
* Checks whether the IP address is valid, and that it does not have a port
* number in it.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
*
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
*
* @returns {void}
*/
ip(ip: string | undefined): void;
/**
* Makes sure the trust proxy setting is not set to `true`.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
trustProxy(request: Request): void;
/**
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
* header is present.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
xForwardedForHeader(request: Request): void;
/**
* Ensures totalHits value from store is a positive integer.
*
* @param hits {any} - The `totalHits` returned by the store.
*/
positiveHits(hits: any): void;
/**
* Ensures a single store instance is not used with multiple express-rate-limit instances
*/
unsharedStore(store: Store): void;
/**
* Ensures a given key is incremented only once per request.
*
* @param request {Request} - The Express request object.
* @param store {Store} - The store class.
* @param key {string} - The key used to store the client's hit count.
*
* @returns {void}
*/
singleCount(request: Request, store: Store, key: string): void;
/**
* Warns the user that the behaviour for `max: 0` / `limit: 0` is
* changing in the next major release.
*
* @param limit {number} - The maximum number of hits per client.
*
* @returns {void}
*/
limit(limit: number): void;
/**
* Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
* and will be removed in the next major release.
*
* @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
*
* @returns {void}
*/
draftPolliHeaders(draft_polli_ratelimit_headers?: any): void;
/**
* Warns the user that the `onLimitReached` option is deprecated and
* will be removed in the next major release.
*
* @param onLimitReached {any | undefined} - The maximum number of hits per client.
*
* @returns {void}
*/
onLimitReached(onLimitReached?: any): void;
/**
* Warns the user when an invalid/unsupported version of the draft spec is passed.
*
* @param version {any | undefined} - The version passed by the user.
*
* @returns {void}
*/
headersDraftVersion(version?: any): void;
/**
* Warns the user when the selected headers option requires a reset time but
* the store does not provide one.
*
* @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
*
* @returns {void}
*/
headersResetTime(resetTime?: Date): void;
/**
* Checks the options.validate setting to ensure that only recognized
* validations are enabled or disabled.
*
* If any unrecognized values are found, an error is logged that
* includes the list of supported vaidations.
*/
validationsConfig(): void;
/**
* Checks to see if the instance was created inside of a request handler,
* which would prevent it from working correctly, with the default memory
* store (or any other store with localKeys.)
*/
creationStack(store: Store): void;
};
export type Validations = typeof validations;
declare const SUPPORTED_DRAFT_VERSIONS: string[];
/**
* Callback that fires when a client's hit counter is incremented.
*
* @param error {Error | undefined} - The error that occurred, if any.
* @param totalHits {number} - The number of hits for that client so far.
* @param resetTime {Date | undefined} - The time when the counter resets.
*/
export type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
/**
* Method (in the form of middleware) to generate/retrieve a value based on the
* incoming request.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
*
* @returns {T} - The value needed.
*/
export type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param next {NextFunction} - The Express `next` function, can be called to skip responding.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
/**
* Event callback that is triggered on a client's first request that exceeds the limit
* but not for subsequent requests. May be used for logging, etc. Should *not*
* send a response.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
/**
* Data returned from the `Store` when a client's hit counter is incremented.
*
* @property totalHits {number} - The number of hits for that client so far.
* @property resetTime {Date | undefined} - The time when the counter resets.
*/
export type ClientRateLimitInfo = {
totalHits: number;
resetTime: Date | undefined;
};
export type IncrementResponse = ClientRateLimitInfo;
/**
* A modified Express request handler with the rate limit functions.
*/
export type RateLimitRequestHandler = RequestHandler & {
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
getKey: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
};
/**
* An interface that all hit counter stores must implement.
*
* @deprecated 6.x - Implement the `Store` interface instead.
*/
export type LegacyStore = {
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
*/
incr: (key: string, callback: IncrementCallback) => void;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => void;
};
/**
* An interface that all hit counter stores must implement.
*/
export type Store = {
/**
* Method that initializes the store, and has access to the options passed to
* the middleware too.
*
* @param options {Options} - The options used to setup the middleware.
*/
init?: (options: Options) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
get?: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {IncrementResponse | undefined} - The number of hits and reset time for that client.
*/
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => Promise<void> | void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => Promise<void> | void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => Promise<void> | void;
/**
* Method to shutdown the store, stop timers, and release all resources.
*/
shutdown?: () => Promise<void> | void;
/**
* Flag to indicate that keys incremented in one instance of this store can
* not affect other instances. Typically false if a database is used, true for
* MemoryStore.
*
* Used to help detect double-counting misconfigurations.
*/
localKeys?: boolean;
/**
* Optional value that the store prepends to keys
*
* Used by the double-count check to avoid false-positives when a key is counted twice, but with different prefixes
*/
prefix?: string;
};
export type DraftHeadersVersion = (typeof SUPPORTED_DRAFT_VERSIONS)[number];
/**
* Validate configuration object for enabling or disabling specific validations.
*
* The keys must also be keys in the validations object, except `enable`, `disable`,
* and `default`.
*/
export type EnabledValidations = {
[key in keyof Omit<Validations, "enabled" | "disable"> | "default"]?: boolean;
};
/**
* The configuration options for the rate limiter.
*/
export type Options = {
/**
* How long we should remember the requests.
*
* Defaults to `60000` ms (= 1 minute).
*/
windowMs: number;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* Defaults to `5`.
*/
limit: number | ValueDeterminingMiddleware<number>;
/**
* The response body to send back when a client is rate limited.
*
* Defaults to `'Too many requests, please try again later.'`
*/
message: any | ValueDeterminingMiddleware<any>;
/**
* The HTTP status code to send back when a client is rate limited.
*
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
*/
statusCode: number;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* Defaults to `true` (for backward compatibility).
*/
legacyHeaders: boolean;
/**
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
*
* Defaults to `false` (for backward compatibility, but its use is recommended).
*/
standardHeaders: boolean | DraftHeadersVersion;
/**
* The name used to identify the quota policy in the `RateLimit` headers as per
* the 8th draft of the IETF specification.
*
* Defaults to `{limit}-in-{window}`.
*/
identifier: string | ValueDeterminingMiddleware<string>;
/**
* The name of the property on the request object to store the rate limit info.
*
* Defaults to `rateLimit`.
*/
requestPropertyName: string;
/**
* If `true`, the library will (by default) skip all requests that have a 4XX
* or 5XX status.
*
* Defaults to `false`.
*/
skipFailedRequests: boolean;
/**
* If `true`, the library will (by default) skip all requests that have a
* status code less than 400.
*
* Defaults to `false`.
*/
skipSuccessfulRequests: boolean;
/**
* Method to generate custom identifiers for clients.
*
* By default, the client's IP address is used.
*/
keyGenerator: ValueDeterminingMiddleware<string>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* By default, sends back the `statusCode` and `message` set via the options.
*/
handler: RateLimitExceededEventHandler;
/**
* Method (in the form of middleware) to determine whether or not this request
* counts towards a client's quota.
*
* By default, skips no requests.
*/
skip: ValueDeterminingMiddleware<boolean>;
/**
* Method to determine whether or not the request counts as 'succesful'. Used
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
*
* By default, requests with a response status code less than 400 are considered
* successful.
*/
requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
/**
* The `Store` to use to store the hit count for each client.
*
* By default, the built-in `MemoryStore` will be used.
*/
store: Store | LegacyStore;
/**
* The list of validation checks that should run.
*/
validate: boolean | EnabledValidations;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
*/
headers?: boolean;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* @deprecated 7.x - This option was renamed to `limit`. However, it will not
* be removed from the library in the foreseeable future.
*/
max?: number | ValueDeterminingMiddleware<number>;
/**
* If the Store generates an error, allow the request to pass.
*/
passOnStoreError: boolean;
};
/**
* The extended request object that includes information about the client's
* rate limit.
*/
export type AugmentedRequest = Request & {
[key: string]: RateLimitInfo;
};
/**
* The rate limit related information for each client included in the
* Express request object.
*/
export type RateLimitInfo = {
limit: number;
used: number;
remaining: number;
resetTime: Date | undefined;
};
/**
*
* Create an instance of IP rate-limiting middleware for Express.
*
* @param passedOptions {Options} - Options to configure the rate limiter.
*
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
*
* @public
*/
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
/**
* The record that stores information about a client - namely, how many times
* they have hit the endpoint, and when their hit count resets.
*
* Similar to `ClientRateLimitInfo`, except `resetTime` is a compulsory field.
*/
export type Client = {
totalHits: number;
resetTime: Date;
};
/**
* A `Store` that stores the hit count for each client in memory.
*
* @public
*/
export declare class MemoryStore implements Store {
/**
* The duration of time before which all hit counts are reset (in milliseconds).
*/
windowMs: number;
/**
* These two maps store usage (requests) and reset time by key (for example, IP
* addresses or API keys).
*
* They are split into two to avoid having to iterate through the entire set to
* determine which ones need reset. Instead, `Client`s are moved from `previous`
* to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients
* left in `previous`, i.e., those that have not made any recent requests, are
* known to be expired and can be deleted in bulk.
*/
previous: Map<string, Client>;
current: Map<string, Client>;
/**
* A reference to the active timer.
*/
interval?: NodeJS.Timeout;
/**
* Confirmation that the keys incremented in once instance of MemoryStore
* cannot affect other instances.
*/
localKeys: boolean;
/**
* Method that initializes the store.
*
* @param options {Options} - The options used to setup the middleware.
*/
init(options: Options): void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
*
* @public
*/
get(key: string): Promise<ClientRateLimitInfo | undefined>;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*
* @public
*/
increment(key: string): Promise<ClientRateLimitInfo>;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
decrement(key: string): Promise<void>;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
resetKey(key: string): Promise<void>;
/**
* Method to reset everyone's hit counter.
*
* @public
*/
resetAll(): Promise<void>;
/**
* Method to stop the timer (if currently running) and prevent any memory
* leaks.
*
* @public
*/
shutdown(): void;
/**
* Recycles a client by setting its hit count to zero, and reset time to
* `windowMs` milliseconds from now.
*
* NOT to be confused with `#resetKey()`, which removes a client from both the
* `current` and `previous` maps.
*
* @param client {Client} - The client to recycle.
* @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
*
* @return {Client} - The modified client that was passed in, to allow for chaining.
*/
private resetClient;
/**
* Retrieves or creates a client, given a key. Also ensures that the client being
* returned is in the `current` map.
*
* @param key {string} - The key under which the client is (or is to be) stored.
*
* @returns {Client} - The requested client.
*/
private getClient;
/**
* Move current clients to previous, create a new map for current.
*
* This function is called every `windowMs`.
*/
private clearExpired;
}
export {
rateLimit as default,
};
export {};

View File

@ -1,584 +0,0 @@
// Generated by dts-bundle-generator v8.0.1
import { NextFunction, Request, RequestHandler, Response } from 'express';
declare const validations: {
enabled: {
[key: string]: boolean;
};
disable(): void;
/**
* Checks whether the IP address is valid, and that it does not have a port
* number in it.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
*
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
*
* @returns {void}
*/
ip(ip: string | undefined): void;
/**
* Makes sure the trust proxy setting is not set to `true`.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
trustProxy(request: Request): void;
/**
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
* header is present.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
xForwardedForHeader(request: Request): void;
/**
* Ensures totalHits value from store is a positive integer.
*
* @param hits {any} - The `totalHits` returned by the store.
*/
positiveHits(hits: any): void;
/**
* Ensures a single store instance is not used with multiple express-rate-limit instances
*/
unsharedStore(store: Store): void;
/**
* Ensures a given key is incremented only once per request.
*
* @param request {Request} - The Express request object.
* @param store {Store} - The store class.
* @param key {string} - The key used to store the client's hit count.
*
* @returns {void}
*/
singleCount(request: Request, store: Store, key: string): void;
/**
* Warns the user that the behaviour for `max: 0` / `limit: 0` is
* changing in the next major release.
*
* @param limit {number} - The maximum number of hits per client.
*
* @returns {void}
*/
limit(limit: number): void;
/**
* Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
* and will be removed in the next major release.
*
* @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
*
* @returns {void}
*/
draftPolliHeaders(draft_polli_ratelimit_headers?: any): void;
/**
* Warns the user that the `onLimitReached` option is deprecated and
* will be removed in the next major release.
*
* @param onLimitReached {any | undefined} - The maximum number of hits per client.
*
* @returns {void}
*/
onLimitReached(onLimitReached?: any): void;
/**
* Warns the user when an invalid/unsupported version of the draft spec is passed.
*
* @param version {any | undefined} - The version passed by the user.
*
* @returns {void}
*/
headersDraftVersion(version?: any): void;
/**
* Warns the user when the selected headers option requires a reset time but
* the store does not provide one.
*
* @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
*
* @returns {void}
*/
headersResetTime(resetTime?: Date): void;
/**
* Checks the options.validate setting to ensure that only recognized
* validations are enabled or disabled.
*
* If any unrecognized values are found, an error is logged that
* includes the list of supported vaidations.
*/
validationsConfig(): void;
/**
* Checks to see if the instance was created inside of a request handler,
* which would prevent it from working correctly, with the default memory
* store (or any other store with localKeys.)
*/
creationStack(store: Store): void;
};
export type Validations = typeof validations;
declare const SUPPORTED_DRAFT_VERSIONS: string[];
/**
* Callback that fires when a client's hit counter is incremented.
*
* @param error {Error | undefined} - The error that occurred, if any.
* @param totalHits {number} - The number of hits for that client so far.
* @param resetTime {Date | undefined} - The time when the counter resets.
*/
export type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
/**
* Method (in the form of middleware) to generate/retrieve a value based on the
* incoming request.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
*
* @returns {T} - The value needed.
*/
export type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param next {NextFunction} - The Express `next` function, can be called to skip responding.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
/**
* Event callback that is triggered on a client's first request that exceeds the limit
* but not for subsequent requests. May be used for logging, etc. Should *not*
* send a response.
*
* @param request {Request} - The Express request object.
* @param response {Response} - The Express response object.
* @param optionsUsed {Options} - The options used to set up the middleware.
*/
export type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
/**
* Data returned from the `Store` when a client's hit counter is incremented.
*
* @property totalHits {number} - The number of hits for that client so far.
* @property resetTime {Date | undefined} - The time when the counter resets.
*/
export type ClientRateLimitInfo = {
totalHits: number;
resetTime: Date | undefined;
};
export type IncrementResponse = ClientRateLimitInfo;
/**
* A modified Express request handler with the rate limit functions.
*/
export type RateLimitRequestHandler = RequestHandler & {
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
getKey: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
};
/**
* An interface that all hit counter stores must implement.
*
* @deprecated 6.x - Implement the `Store` interface instead.
*/
export type LegacyStore = {
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
*/
incr: (key: string, callback: IncrementCallback) => void;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => void;
};
/**
* An interface that all hit counter stores must implement.
*/
export type Store = {
/**
* Method that initializes the store, and has access to the options passed to
* the middleware too.
*
* @param options {Options} - The options used to setup the middleware.
*/
init?: (options: Options) => void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*/
get?: (key: string) => Promise<ClientRateLimitInfo | undefined> | ClientRateLimitInfo | undefined;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {IncrementResponse | undefined} - The number of hits and reset time for that client.
*/
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
decrement: (key: string) => Promise<void> | void;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*/
resetKey: (key: string) => Promise<void> | void;
/**
* Method to reset everyone's hit counter.
*/
resetAll?: () => Promise<void> | void;
/**
* Method to shutdown the store, stop timers, and release all resources.
*/
shutdown?: () => Promise<void> | void;
/**
* Flag to indicate that keys incremented in one instance of this store can
* not affect other instances. Typically false if a database is used, true for
* MemoryStore.
*
* Used to help detect double-counting misconfigurations.
*/
localKeys?: boolean;
/**
* Optional value that the store prepends to keys
*
* Used by the double-count check to avoid false-positives when a key is counted twice, but with different prefixes
*/
prefix?: string;
};
export type DraftHeadersVersion = (typeof SUPPORTED_DRAFT_VERSIONS)[number];
/**
* Validate configuration object for enabling or disabling specific validations.
*
* The keys must also be keys in the validations object, except `enable`, `disable`,
* and `default`.
*/
export type EnabledValidations = {
[key in keyof Omit<Validations, "enabled" | "disable"> | "default"]?: boolean;
};
/**
* The configuration options for the rate limiter.
*/
export type Options = {
/**
* How long we should remember the requests.
*
* Defaults to `60000` ms (= 1 minute).
*/
windowMs: number;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* Defaults to `5`.
*/
limit: number | ValueDeterminingMiddleware<number>;
/**
* The response body to send back when a client is rate limited.
*
* Defaults to `'Too many requests, please try again later.'`
*/
message: any | ValueDeterminingMiddleware<any>;
/**
* The HTTP status code to send back when a client is rate limited.
*
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
*/
statusCode: number;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* Defaults to `true` (for backward compatibility).
*/
legacyHeaders: boolean;
/**
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
*
* Defaults to `false` (for backward compatibility, but its use is recommended).
*/
standardHeaders: boolean | DraftHeadersVersion;
/**
* The name used to identify the quota policy in the `RateLimit` headers as per
* the 8th draft of the IETF specification.
*
* Defaults to `{limit}-in-{window}`.
*/
identifier: string | ValueDeterminingMiddleware<string>;
/**
* The name of the property on the request object to store the rate limit info.
*
* Defaults to `rateLimit`.
*/
requestPropertyName: string;
/**
* If `true`, the library will (by default) skip all requests that have a 4XX
* or 5XX status.
*
* Defaults to `false`.
*/
skipFailedRequests: boolean;
/**
* If `true`, the library will (by default) skip all requests that have a
* status code less than 400.
*
* Defaults to `false`.
*/
skipSuccessfulRequests: boolean;
/**
* Method to generate custom identifiers for clients.
*
* By default, the client's IP address is used.
*/
keyGenerator: ValueDeterminingMiddleware<string>;
/**
* Express request handler that sends back a response when a client is
* rate-limited.
*
* By default, sends back the `statusCode` and `message` set via the options.
*/
handler: RateLimitExceededEventHandler;
/**
* Method (in the form of middleware) to determine whether or not this request
* counts towards a client's quota.
*
* By default, skips no requests.
*/
skip: ValueDeterminingMiddleware<boolean>;
/**
* Method to determine whether or not the request counts as 'succesful'. Used
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
*
* By default, requests with a response status code less than 400 are considered
* successful.
*/
requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
/**
* The `Store` to use to store the hit count for each client.
*
* By default, the built-in `MemoryStore` will be used.
*/
store: Store | LegacyStore;
/**
* The list of validation checks that should run.
*/
validate: boolean | EnabledValidations;
/**
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
* of requests.
*
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
*/
headers?: boolean;
/**
* The maximum number of connections to allow during the `window` before
* rate limiting the client.
*
* Can be the limit itself as a number or express middleware that parses
* the request and then figures out the limit.
*
* @deprecated 7.x - This option was renamed to `limit`. However, it will not
* be removed from the library in the foreseeable future.
*/
max?: number | ValueDeterminingMiddleware<number>;
/**
* If the Store generates an error, allow the request to pass.
*/
passOnStoreError: boolean;
};
/**
* The extended request object that includes information about the client's
* rate limit.
*/
export type AugmentedRequest = Request & {
[key: string]: RateLimitInfo;
};
/**
* The rate limit related information for each client included in the
* Express request object.
*/
export type RateLimitInfo = {
limit: number;
used: number;
remaining: number;
resetTime: Date | undefined;
};
/**
*
* Create an instance of IP rate-limiting middleware for Express.
*
* @param passedOptions {Options} - Options to configure the rate limiter.
*
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
*
* @public
*/
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
/**
* The record that stores information about a client - namely, how many times
* they have hit the endpoint, and when their hit count resets.
*
* Similar to `ClientRateLimitInfo`, except `resetTime` is a compulsory field.
*/
export type Client = {
totalHits: number;
resetTime: Date;
};
/**
* A `Store` that stores the hit count for each client in memory.
*
* @public
*/
export declare class MemoryStore implements Store {
/**
* The duration of time before which all hit counts are reset (in milliseconds).
*/
windowMs: number;
/**
* These two maps store usage (requests) and reset time by key (for example, IP
* addresses or API keys).
*
* They are split into two to avoid having to iterate through the entire set to
* determine which ones need reset. Instead, `Client`s are moved from `previous`
* to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients
* left in `previous`, i.e., those that have not made any recent requests, are
* known to be expired and can be deleted in bulk.
*/
previous: Map<string, Client>;
current: Map<string, Client>;
/**
* A reference to the active timer.
*/
interval?: NodeJS.Timeout;
/**
* Confirmation that the keys incremented in once instance of MemoryStore
* cannot affect other instances.
*/
localKeys: boolean;
/**
* Method that initializes the store.
*
* @param options {Options} - The options used to setup the middleware.
*/
init(options: Options): void;
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
*
* @public
*/
get(key: string): Promise<ClientRateLimitInfo | undefined>;
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*
* @public
*/
increment(key: string): Promise<ClientRateLimitInfo>;
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
decrement(key: string): Promise<void>;
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
resetKey(key: string): Promise<void>;
/**
* Method to reset everyone's hit counter.
*
* @public
*/
resetAll(): Promise<void>;
/**
* Method to stop the timer (if currently running) and prevent any memory
* leaks.
*
* @public
*/
shutdown(): void;
/**
* Recycles a client by setting its hit count to zero, and reset time to
* `windowMs` milliseconds from now.
*
* NOT to be confused with `#resetKey()`, which removes a client from both the
* `current` and `previous` maps.
*
* @param client {Client} - The client to recycle.
* @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
*
* @return {Client} - The modified client that was passed in, to allow for chaining.
*/
private resetClient;
/**
* Retrieves or creates a client, given a key. Also ensures that the client being
* returned is in the `current` map.
*
* @param key {string} - The key under which the client is (or is to be) stored.
*
* @returns {Client} - The requested client.
*/
private getClient;
/**
* Move current clients to previous, create a new map for current.
*
* This function is called every `windowMs`.
*/
private clearExpired;
}
export {
rateLimit as default,
};
export {};

View File

@ -1,809 +0,0 @@
// source/headers.ts
import { Buffer } from "buffer";
import { createHash } from "crypto";
var SUPPORTED_DRAFT_VERSIONS = ["draft-6", "draft-7", "draft-8"];
var getResetSeconds = (resetTime, windowMs) => {
let resetSeconds = void 0;
if (resetTime) {
const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
resetSeconds = Math.max(0, deltaSeconds);
} else if (windowMs) {
resetSeconds = Math.ceil(windowMs / 1e3);
}
return resetSeconds;
};
var getPartitionKey = (key) => {
const hash = createHash("sha256");
hash.update(key);
const partitionKey = hash.digest("hex").slice(0, 12);
return Buffer.from(partitionKey).toString("base64");
};
var setLegacyHeaders = (response, info) => {
if (response.headersSent)
return;
response.setHeader("X-RateLimit-Limit", info.limit.toString());
response.setHeader("X-RateLimit-Remaining", info.remaining.toString());
if (info.resetTime instanceof Date) {
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
response.setHeader(
"X-RateLimit-Reset",
Math.ceil(info.resetTime.getTime() / 1e3).toString()
);
}
};
var setDraft6Headers = (response, info, windowMs) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime);
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
response.setHeader("RateLimit-Limit", info.limit.toString());
response.setHeader("RateLimit-Remaining", info.remaining.toString());
if (resetSeconds)
response.setHeader("RateLimit-Reset", resetSeconds.toString());
};
var setDraft7Headers = (response, info, windowMs) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
response.setHeader(
"RateLimit",
`limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`
);
};
var setDraft8Headers = (response, info, windowMs, name, key) => {
if (response.headersSent)
return;
const windowSeconds = Math.ceil(windowMs / 1e3);
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
const partitionKey = getPartitionKey(key);
const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;
const header = `r=${info.remaining}; t=${resetSeconds}`;
response.append("RateLimit-Policy", `"${name}"; ${policy}`);
response.append("RateLimit", `"${name}"; ${header}`);
};
var setRetryAfterHeader = (response, info, windowMs) => {
if (response.headersSent)
return;
const resetSeconds = getResetSeconds(info.resetTime, windowMs);
response.setHeader("Retry-After", resetSeconds.toString());
};
// source/validations.ts
import { isIP } from "net";
var ValidationError = class extends Error {
/**
* The code must be a string, in snake case and all capital, that starts with
* the substring `ERR_ERL_`.
*
* The message must be a string, starting with an uppercase character,
* describing the issue in detail.
*/
constructor(code, message) {
const url = `https://express-rate-limit.github.io/${code}/`;
super(`${message} See ${url} for more information.`);
this.name = this.constructor.name;
this.code = code;
this.help = url;
}
};
var ChangeWarning = class extends ValidationError {
};
var usedStores = /* @__PURE__ */ new Set();
var singleCountKeys = /* @__PURE__ */ new WeakMap();
var validations = {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
enabled: {
default: true
},
// Should be EnabledValidations type, but that's a circular reference
disable() {
for (const k of Object.keys(this.enabled))
this.enabled[k] = false;
},
/**
* Checks whether the IP address is valid, and that it does not have a port
* number in it.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
*
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
*
* @returns {void}
*/
ip(ip) {
if (ip === void 0) {
throw new ValidationError(
"ERR_ERL_UNDEFINED_IP_ADDRESS",
`An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`
);
}
if (!isIP(ip)) {
throw new ValidationError(
"ERR_ERL_INVALID_IP_ADDRESS",
`An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`
);
}
},
/**
* Makes sure the trust proxy setting is not set to `true`.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
trustProxy(request) {
if (request.app.get("trust proxy") === true) {
throw new ValidationError(
"ERR_ERL_PERMISSIVE_TRUST_PROXY",
`The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`
);
}
},
/**
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
* header is present.
*
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
*
* @param request {Request} - The Express request object.
*
* @returns {void}
*/
xForwardedForHeader(request) {
if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
throw new ValidationError(
"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR",
`The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`
);
}
},
/**
* Ensures totalHits value from store is a positive integer.
*
* @param hits {any} - The `totalHits` returned by the store.
*/
positiveHits(hits) {
if (typeof hits !== "number" || hits < 1 || hits !== Math.round(hits)) {
throw new ValidationError(
"ERR_ERL_INVALID_HITS",
`The totalHits value returned from the store must be a positive integer, got ${hits}`
);
}
},
/**
* Ensures a single store instance is not used with multiple express-rate-limit instances
*/
unsharedStore(store) {
if (usedStores.has(store)) {
const maybeUniquePrefix = store?.localKeys ? "" : " (with a unique prefix)";
throw new ValidationError(
"ERR_ERL_STORE_REUSE",
`A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`
);
}
usedStores.add(store);
},
/**
* Ensures a given key is incremented only once per request.
*
* @param request {Request} - The Express request object.
* @param store {Store} - The store class.
* @param key {string} - The key used to store the client's hit count.
*
* @returns {void}
*/
singleCount(request, store, key) {
let storeKeys = singleCountKeys.get(request);
if (!storeKeys) {
storeKeys = /* @__PURE__ */ new Map();
singleCountKeys.set(request, storeKeys);
}
const storeKey = store.localKeys ? store : store.constructor.name;
let keys = storeKeys.get(storeKey);
if (!keys) {
keys = [];
storeKeys.set(storeKey, keys);
}
const prefixedKey = `${store.prefix ?? ""}${key}`;
if (keys.includes(prefixedKey)) {
throw new ValidationError(
"ERR_ERL_DOUBLE_COUNT",
`The hit count for ${key} was incremented more than once for a single request.`
);
}
keys.push(prefixedKey);
},
/**
* Warns the user that the behaviour for `max: 0` / `limit: 0` is
* changing in the next major release.
*
* @param limit {number} - The maximum number of hits per client.
*
* @returns {void}
*/
limit(limit) {
if (limit === 0) {
throw new ChangeWarning(
"WRN_ERL_MAX_ZERO",
`Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7`
);
}
},
/**
* Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
* and will be removed in the next major release.
*
* @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
*
* @returns {void}
*/
draftPolliHeaders(draft_polli_ratelimit_headers) {
if (draft_polli_ratelimit_headers) {
throw new ChangeWarning(
"WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS",
`The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`
);
}
},
/**
* Warns the user that the `onLimitReached` option is deprecated and
* will be removed in the next major release.
*
* @param onLimitReached {any | undefined} - The maximum number of hits per client.
*
* @returns {void}
*/
onLimitReached(onLimitReached) {
if (onLimitReached) {
throw new ChangeWarning(
"WRN_ERL_DEPRECATED_ON_LIMIT_REACHED",
`The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.`
);
}
},
/**
* Warns the user when an invalid/unsupported version of the draft spec is passed.
*
* @param version {any | undefined} - The version passed by the user.
*
* @returns {void}
*/
headersDraftVersion(version) {
if (typeof version !== "string" || !SUPPORTED_DRAFT_VERSIONS.includes(version)) {
const versionString = SUPPORTED_DRAFT_VERSIONS.join(", ");
throw new ValidationError(
"ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION",
`standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`
);
}
},
/**
* Warns the user when the selected headers option requires a reset time but
* the store does not provide one.
*
* @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
*
* @returns {void}
*/
headersResetTime(resetTime) {
if (!resetTime) {
throw new ValidationError(
"ERR_ERL_HEADERS_NO_RESET",
`standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`
);
}
},
/**
* Checks the options.validate setting to ensure that only recognized
* validations are enabled or disabled.
*
* If any unrecognized values are found, an error is logged that
* includes the list of supported vaidations.
*/
validationsConfig() {
const supportedValidations = Object.keys(this).filter(
(k) => !["enabled", "disable"].includes(k)
);
supportedValidations.push("default");
for (const key of Object.keys(this.enabled)) {
if (!supportedValidations.includes(key)) {
throw new ValidationError(
"ERR_ERL_UNKNOWN_VALIDATION",
`options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(
", "
)}.`
);
}
}
},
/**
* Checks to see if the instance was created inside of a request handler,
* which would prevent it from working correctly, with the default memory
* store (or any other store with localKeys.)
*/
creationStack(store) {
const { stack } = new Error(
"express-rate-limit validation check (set options.validate.creationStack=false to disable)"
);
if (stack?.includes("Layer.handle [as handle_request]")) {
if (!store.localKeys) {
throw new ValidationError(
"ERR_ERL_CREATED_IN_REQUEST_HANDLER",
"express-rate-limit instance should *usually* be created at app initialization, not when responding to a request."
);
}
throw new ValidationError(
"ERR_ERL_CREATED_IN_REQUEST_HANDLER",
`express-rate-limit instance should be created at app initialization, not when responding to a request.`
);
}
}
};
var getValidations = (_enabled) => {
let enabled;
if (typeof _enabled === "boolean") {
enabled = {
default: _enabled
};
} else {
enabled = {
default: true,
..._enabled
};
}
const wrappedValidations = {
enabled
};
for (const [name, validation] of Object.entries(validations)) {
if (typeof validation === "function")
wrappedValidations[name] = (...args) => {
if (!(enabled[name] ?? enabled.default)) {
return;
}
try {
;
validation.apply(
wrappedValidations,
args
);
} catch (error) {
if (error instanceof ChangeWarning)
console.warn(error);
else
console.error(error);
}
};
}
return wrappedValidations;
};
// source/memory-store.ts
var MemoryStore = class {
constructor() {
/**
* These two maps store usage (requests) and reset time by key (for example, IP
* addresses or API keys).
*
* They are split into two to avoid having to iterate through the entire set to
* determine which ones need reset. Instead, `Client`s are moved from `previous`
* to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients
* left in `previous`, i.e., those that have not made any recent requests, are
* known to be expired and can be deleted in bulk.
*/
this.previous = /* @__PURE__ */ new Map();
this.current = /* @__PURE__ */ new Map();
/**
* Confirmation that the keys incremented in once instance of MemoryStore
* cannot affect other instances.
*/
this.localKeys = true;
}
/**
* Method that initializes the store.
*
* @param options {Options} - The options used to setup the middleware.
*/
init(options) {
this.windowMs = options.windowMs;
if (this.interval)
clearInterval(this.interval);
this.interval = setInterval(() => {
this.clearExpired();
}, this.windowMs);
if (this.interval.unref)
this.interval.unref();
}
/**
* Method to fetch a client's hit count and reset time.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
*
* @public
*/
async get(key) {
return this.current.get(key) ?? this.previous.get(key);
}
/**
* Method to increment a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
*
* @public
*/
async increment(key) {
const client = this.getClient(key);
const now = Date.now();
if (client.resetTime.getTime() <= now) {
this.resetClient(client, now);
}
client.totalHits++;
return client;
}
/**
* Method to decrement a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
async decrement(key) {
const client = this.getClient(key);
if (client.totalHits > 0)
client.totalHits--;
}
/**
* Method to reset a client's hit counter.
*
* @param key {string} - The identifier for a client.
*
* @public
*/
async resetKey(key) {
this.current.delete(key);
this.previous.delete(key);
}
/**
* Method to reset everyone's hit counter.
*
* @public
*/
async resetAll() {
this.current.clear();
this.previous.clear();
}
/**
* Method to stop the timer (if currently running) and prevent any memory
* leaks.
*
* @public
*/
shutdown() {
clearInterval(this.interval);
void this.resetAll();
}
/**
* Recycles a client by setting its hit count to zero, and reset time to
* `windowMs` milliseconds from now.
*
* NOT to be confused with `#resetKey()`, which removes a client from both the
* `current` and `previous` maps.
*
* @param client {Client} - The client to recycle.
* @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
*
* @return {Client} - The modified client that was passed in, to allow for chaining.
*/
resetClient(client, now = Date.now()) {
client.totalHits = 0;
client.resetTime.setTime(now + this.windowMs);
return client;
}
/**
* Retrieves or creates a client, given a key. Also ensures that the client being
* returned is in the `current` map.
*
* @param key {string} - The key under which the client is (or is to be) stored.
*
* @returns {Client} - The requested client.
*/
getClient(key) {
if (this.current.has(key))
return this.current.get(key);
let client;
if (this.previous.has(key)) {
client = this.previous.get(key);
this.previous.delete(key);
} else {
client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };
this.resetClient(client);
}
this.current.set(key, client);
return client;
}
/**
* Move current clients to previous, create a new map for current.
*
* This function is called every `windowMs`.
*/
clearExpired() {
this.previous = this.current;
this.current = /* @__PURE__ */ new Map();
}
};
// source/lib.ts
var isLegacyStore = (store) => (
// Check that `incr` exists but `increment` does not - store authors might want
// to keep both around for backwards compatibility.
typeof store.incr === "function" && typeof store.increment !== "function"
);
var promisifyStore = (passedStore) => {
if (!isLegacyStore(passedStore)) {
return passedStore;
}
const legacyStore = passedStore;
class PromisifiedStore {
async increment(key) {
return new Promise((resolve, reject) => {
legacyStore.incr(
key,
(error, totalHits, resetTime) => {
if (error)
reject(error);
resolve({ totalHits, resetTime });
}
);
});
}
async decrement(key) {
return legacyStore.decrement(key);
}
async resetKey(key) {
return legacyStore.resetKey(key);
}
/* istanbul ignore next */
async resetAll() {
if (typeof legacyStore.resetAll === "function")
return legacyStore.resetAll();
}
}
return new PromisifiedStore();
};
var getOptionsFromConfig = (config) => {
const { validations: validations2, ...directlyPassableEntries } = config;
return {
...directlyPassableEntries,
validate: validations2.enabled
};
};
var omitUndefinedOptions = (passedOptions) => {
const omittedOptions = {};
for (const k of Object.keys(passedOptions)) {
const key = k;
if (passedOptions[key] !== void 0) {
omittedOptions[key] = passedOptions[key];
}
}
return omittedOptions;
};
var parseOptions = (passedOptions) => {
const notUndefinedOptions = omitUndefinedOptions(passedOptions);
const validations2 = getValidations(notUndefinedOptions?.validate ?? true);
validations2.validationsConfig();
validations2.draftPolliHeaders(
// @ts-expect-error see the note above.
notUndefinedOptions.draft_polli_ratelimit_headers
);
validations2.onLimitReached(notUndefinedOptions.onLimitReached);
let standardHeaders = notUndefinedOptions.standardHeaders ?? false;
if (standardHeaders === true)
standardHeaders = "draft-6";
const config = {
windowMs: 60 * 1e3,
limit: passedOptions.max ?? 5,
// `max` is deprecated, but support it anyways.
message: "Too many requests, please try again later.",
statusCode: 429,
legacyHeaders: passedOptions.headers ?? true,
identifier(request, _response) {
let duration = "";
const property = config.requestPropertyName;
const { limit } = request[property];
const seconds = config.windowMs / 1e3;
const minutes = config.windowMs / (1e3 * 60);
const hours = config.windowMs / (1e3 * 60 * 60);
const days = config.windowMs / (1e3 * 60 * 60 * 24);
if (seconds < 60)
duration = `${seconds}sec`;
else if (minutes < 60)
duration = `${minutes}min`;
else if (hours < 24)
duration = `${hours}hr${hours > 1 ? "s" : ""}`;
else
duration = `${days}day${days > 1 ? "s" : ""}`;
return `${limit}-in-${duration}`;
},
requestPropertyName: "rateLimit",
skipFailedRequests: false,
skipSuccessfulRequests: false,
requestWasSuccessful: (_request, response) => response.statusCode < 400,
skip: (_request, _response) => false,
keyGenerator(request, _response) {
validations2.ip(request.ip);
validations2.trustProxy(request);
validations2.xForwardedForHeader(request);
return request.ip;
},
async handler(request, response, _next, _optionsUsed) {
response.status(config.statusCode);
const message = typeof config.message === "function" ? await config.message(
request,
response
) : config.message;
if (!response.writableEnded) {
response.send(message);
}
},
passOnStoreError: false,
// Allow the default options to be overriden by the passed options.
...notUndefinedOptions,
// `standardHeaders` is resolved into a draft version above, use that.
standardHeaders,
// Note that this field is declared after the user's options are spread in,
// so that this field doesn't get overriden with an un-promisified store!
store: promisifyStore(notUndefinedOptions.store ?? new MemoryStore()),
// Print an error to the console if a few known misconfigurations are detected.
validations: validations2
};
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== "function" || config.store.init !== void 0 && typeof config.store.init !== "function") {
throw new TypeError(
"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
);
}
return config;
};
var handleAsyncErrors = (fn) => async (request, response, next) => {
try {
await Promise.resolve(fn(request, response, next)).catch(next);
} catch (error) {
next(error);
}
};
var rateLimit = (passedOptions) => {
const config = parseOptions(passedOptions ?? {});
const options = getOptionsFromConfig(config);
config.validations.creationStack(config.store);
config.validations.unsharedStore(config.store);
if (typeof config.store.init === "function")
config.store.init(options);
const middleware = handleAsyncErrors(
async (request, response, next) => {
const skip = await config.skip(request, response);
if (skip) {
next();
return;
}
const augmentedRequest = request;
const key = await config.keyGenerator(request, response);
let totalHits = 0;
let resetTime;
try {
const incrementResult = await config.store.increment(key);
totalHits = incrementResult.totalHits;
resetTime = incrementResult.resetTime;
} catch (error) {
if (config.passOnStoreError) {
console.error(
"express-rate-limit: error from store, allowing request without rate-limiting.",
error
);
next();
return;
}
throw error;
}
config.validations.positiveHits(totalHits);
config.validations.singleCount(request, config.store, key);
const retrieveLimit = typeof config.limit === "function" ? config.limit(request, response) : config.limit;
const limit = await retrieveLimit;
config.validations.limit(limit);
const info = {
limit,
used: totalHits,
remaining: Math.max(limit - totalHits, 0),
resetTime
};
Object.defineProperty(info, "current", {
configurable: false,
enumerable: false,
value: totalHits
});
augmentedRequest[config.requestPropertyName] = info;
if (config.legacyHeaders && !response.headersSent) {
setLegacyHeaders(response, info);
}
if (config.standardHeaders && !response.headersSent) {
switch (config.standardHeaders) {
case "draft-6": {
setDraft6Headers(response, info, config.windowMs);
break;
}
case "draft-7": {
config.validations.headersResetTime(info.resetTime);
setDraft7Headers(response, info, config.windowMs);
break;
}
case "draft-8": {
const retrieveName = typeof config.identifier === "function" ? config.identifier(request, response) : config.identifier;
const name = await retrieveName;
config.validations.headersResetTime(info.resetTime);
setDraft8Headers(response, info, config.windowMs, name, key);
break;
}
default: {
config.validations.headersDraftVersion(config.standardHeaders);
break;
}
}
}
if (config.skipFailedRequests || config.skipSuccessfulRequests) {
let decremented = false;
const decrementKey = async () => {
if (!decremented) {
await config.store.decrement(key);
decremented = true;
}
};
if (config.skipFailedRequests) {
response.on("finish", async () => {
if (!await config.requestWasSuccessful(request, response))
await decrementKey();
});
response.on("close", async () => {
if (!response.writableEnded)
await decrementKey();
});
response.on("error", async () => {
await decrementKey();
});
}
if (config.skipSuccessfulRequests) {
response.on("finish", async () => {
if (await config.requestWasSuccessful(request, response))
await decrementKey();
});
}
}
config.validations.disable();
if (totalHits > limit) {
if (config.legacyHeaders || config.standardHeaders) {
setRetryAfterHeader(response, info, config.windowMs);
}
config.handler(request, response, next, options);
return;
}
next();
}
);
const getThrowFn = () => {
throw new Error("The current store does not support the get/getKey method");
};
middleware.resetKey = config.store.resetKey.bind(config.store);
middleware.getKey = typeof config.store.get === "function" ? config.store.get.bind(config.store) : getThrowFn;
return middleware;
};
var lib_default = rateLimit;
export {
MemoryStore,
lib_default as default,
lib_default as rateLimit
};

View File

@ -1,133 +0,0 @@
{
"name": "express-rate-limit",
"version": "7.5.0",
"description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
"author": {
"name": "Nathan Friedly",
"url": "http://nfriedly.com/"
},
"license": "MIT",
"homepage": "https://github.com/express-rate-limit/express-rate-limit",
"repository": {
"type": "git",
"url": "git+https://github.com/express-rate-limit/express-rate-limit.git"
},
"funding": "https://github.com/sponsors/express-rate-limit",
"keywords": [
"express-rate-limit",
"express",
"rate",
"limit",
"ratelimit",
"rate-limit",
"middleware",
"ip",
"auth",
"authorization",
"security",
"brute",
"force",
"bruteforce",
"brute-force",
"attack"
],
"type": "module",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/",
"tsconfig.json"
],
"engines": {
"node": ">= 16"
},
"scripts": {
"clean": "del-cli dist/ coverage/ *.log *.tmp *.bak *.tgz",
"build:cjs": "esbuild --platform=node --bundle --target=es2022 --format=cjs --outfile=dist/index.cjs --footer:js=\"module.exports = rateLimit; module.exports.default = rateLimit; module.exports.rateLimit = rateLimit; module.exports.MemoryStore = MemoryStore;\" source/index.ts",
"build:esm": "esbuild --platform=node --bundle --target=es2022 --format=esm --outfile=dist/index.mjs source/index.ts",
"build:types": "dts-bundle-generator --out-file=dist/index.d.ts source/index.ts && cp dist/index.d.ts dist/index.d.cts && cp dist/index.d.ts dist/index.d.mts",
"compile": "run-s clean build:*",
"docs": "cd docs && mintlify dev",
"lint:code": "xo",
"lint:rest": "prettier --check .",
"lint": "run-s lint:*",
"format:code": "xo --fix",
"format:rest": "prettier --write .",
"format": "run-s format:*",
"test:lib": "jest",
"test:ext": "cd test/external/ && bash run-all-tests",
"test": "run-s lint test:lib",
"pre-commit": "lint-staged",
"prepare": "run-s compile && husky install config/husky"
},
"peerDependencies": {
"express": "^4.11 || 5 || ^5.0.0-beta.1"
},
"devDependencies": {
"@express-rate-limit/prettier": "1.1.1",
"@express-rate-limit/tsconfig": "1.0.2",
"@jest/globals": "29.7.0",
"@types/express": "4.17.20",
"@types/jest": "29.5.6",
"@types/node": "20.8.7",
"@types/supertest": "2.0.15",
"del-cli": "5.1.0",
"dts-bundle-generator": "8.0.1",
"esbuild": "0.19.5",
"express": "4.21.1",
"husky": "8.0.3",
"jest": "29.7.0",
"lint-staged": "15.0.2",
"mintlify": "4.0.63",
"npm-run-all": "4.1.5",
"ratelimit-header-parser": "0.1.0",
"supertest": "6.3.3",
"ts-jest": "29.1.1",
"ts-node": "10.9.1",
"typescript": "5.2.2",
"xo": "0.56.0"
},
"xo": {
"prettier": true,
"rules": {
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-dynamic-delete": 0,
"@typescript-eslint/no-confusing-void-expression": 0,
"@typescript-eslint/consistent-indexed-object-style": [
"error",
"index-signature"
],
"n/no-unsupported-features/es-syntax": 0
},
"overrides": [
{
"files": "test/library/*.ts",
"rules": {
"@typescript-eslint/no-unsafe-argument": 0,
"@typescript-eslint/no-unsafe-assignment": 0
}
}
],
"ignore": [
"test/external"
]
},
"prettier": "@express-rate-limit/prettier",
"lint-staged": {
"{source,test}/**/*.ts": "xo --fix",
"**/*.{json,yaml,md}": "prettier --write "
}
}

View File

@ -1,8 +0,0 @@
{
"include": ["source/"],
"exclude": ["node_modules/"],
"extends": "@express-rate-limit/tsconfig",
"compilerOptions": {
"target": "ES2020"
}
}

308
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,21 +22,23 @@
"dev": "nodemon app.js"
},
"dependencies": {
"@eslint/js": "^9.24.0",
"body-parser": "^2.2.0",
"csso": "^5.0.5",
"eslint": "^9.24.0",
"express": "^4.21.2",
"express-session": "^1.18.1",
"serve-favicon": "^2.5.0",
"tslib": "^2.8.1",
"undici": "^7.6.0"
},
"devDependencies": {
"@eslint/js": "^9.24.0",
"csso": "^5.0.5",
"eslint": "^9.24.0",
"glob": "^11.0.1",
"globals": "^16.0.0",
"html-minifier": "^4.0.0",
"pkg": "^5.8.1",
"prettier": "^3.5.3",
"serve-favicon": "^2.5.0",
"terser": "^5.39.0",
"tslib": "^2.8.1",
"typescript-eslint": "^8.30.1",
"undici": "^7.6.0"
"typescript-eslint": "^8.30.1"
}
}

28
src/js/index.d.ts vendored
View File

@ -156,7 +156,6 @@ declare class USER {
friendFeed: (gamertag: string, platform: platforms) => Promise<unknown>;
eventFeed: () => Promise<unknown>;
loggedInIdentities: () => Promise<unknown>;
userInfo: () => Promise<any>;
codPoints: (gamertag: string, platform: platforms) => Promise<unknown>;
connectedAccounts: (
gamertag: string,
@ -168,6 +167,7 @@ declare class USER {
platform: platforms,
action: friendActions
) => Promise<unknown>;
userInfo: () => Promise<unknown>;
}
declare class DB {
accolades: () => Promise<unknown>;
@ -190,22 +190,22 @@ declare const Me: USER;
declare const CDN: DB;
declare const Misc: ALT;
export {
CDN,
ColdWar,
disableDebugMode,
enableDebugMode,
friendActions,
login,
Me,
Misc,
telescopeLogin,
platforms,
friendActions,
Warzone,
ModernWarfare,
ModernWarfare2,
ModernWarfare3,
platforms,
Store,
telescopeLogin,
Vanguard,
Warzone,
Warzone2,
WarzoneMobile,
Warzone2,
ColdWar,
Vanguard,
Store,
Me,
CDN,
Misc,
enableDebugMode,
disableDebugMode,
};

View File

@ -1,32 +1,31 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.WarzoneMobile =
exports.Warzone2 =
exports.Warzone =
exports.Vanguard =
exports.telescopeLogin =
exports.disableDebugMode =
exports.enableDebugMode =
exports.Misc =
exports.Me =
exports.Store =
exports.platforms =
exports.Vanguard =
exports.ColdWar =
exports.Warzone2 =
exports.WarzoneMobile =
exports.ModernWarfare3 =
exports.ModernWarfare2 =
exports.ModernWarfare =
exports.Misc =
exports.Me =
exports.login =
exports.Warzone =
exports.friendActions =
exports.enableDebugMode =
exports.disableDebugMode =
exports.ColdWar =
exports.CDN =
exports.platforms =
exports.telescopeLogin =
exports.login =
void 0;
const tslib_1 = require('tslib');
const undici_1 = require('undici');
const game_modes_json_1 = tslib_1.__importDefault(
require('../data/game-modes.json')
);
const weapon_ids_json_1 = tslib_1.__importDefault(
require('../data/weapon-ids.json')
);
const game_modes_json_1 = tslib_1.__importDefault(
require('../data/game-modes.json')
);
const userAgent =
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36';
let baseCookie = 'new_SiteId=cod;ACT_SSO_LOCALE=en_US;country=US;';
@ -72,7 +71,8 @@ var platforms;
platforms['XBOX'] = 'xbl';
platforms['ios'] = 'ios';
platforms['NULL'] = '_';
})(platforms || (exports.platforms = platforms = {}));
})(platforms || (platforms = {}));
exports.platforms = platforms;
var games;
(function (games) {
games['ModernWarfare'] = 'mw';
@ -107,7 +107,8 @@ var friendActions;
friendActions['Remove'] = 'remove';
friendActions['Block'] = 'block';
friendActions['Unblock'] = 'unblock';
})(friendActions || (exports.friendActions = friendActions = {}));
})(friendActions || (friendActions = {}));
exports.friendActions = friendActions;
var generics;
(function (generics) {
generics['STEAM_UNSUPPORTED'] =
@ -170,7 +171,7 @@ const sendRequestCDN = (url) =>
tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
if (!loggedIn) throw new Error('Not Logged In.');
let requestUrl = `${baseUrl}${url}`;
let requestUrl = `${baseUrlTrunc}${url}`;
if (debugMode) console.log(`[DEBUG]`, `Request Uri: ${requestUrl}`);
if (debugMode) console.time('Round Trip');
const { body, statusCode } = yield (0, undici_1.request)(requestUrl, {
@ -233,8 +234,10 @@ const sendRequestUserInfo = (url) =>
throw new Error(
`Received status code: '${statusCode}'. Route may be down or not exist.`
);
// Get the response as text first
let responseText = yield body.text();
// Check if this is a JSONP response (contains function wrapper)
if (responseText.startsWith('userInfo(') && responseText.endsWith(');')) {
// Extract the JSON data from between the parentheses
@ -248,6 +251,7 @@ const sendRequestUserInfo = (url) =>
throw exception;
}
});
const sendPostRequest = (url, data) =>
tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
@ -332,7 +336,11 @@ const handleLookupType = (platform) => {
const checkForValidPlatform = (platform, gamertag) => {
if (!Object.values(platforms).includes(platform))
throw new Error(
`Platform '${platform}' is not valid.\nTry one of the following:\n${JSON.stringify(Object.values(platforms), null, 2)}`
`Platform '${platform}' is not valid.\nTry one of the following:\n${JSON.stringify(
Object.values(platforms),
null,
2
)}`
);
if (gamertag && isNaN(Number(gamertag)) && platform === platforms.Uno)
throw new Error(generics.UNO_NO_NUMERICAL_ID);
@ -365,7 +373,7 @@ class Endpoints {
this.breakdownWithDate = (startTime, endTime) =>
`/crm/cod/v2/title/${this.game}/platform/${this.platform}/${this.lookupType}/${this.gamertag}/matches/${this.mode}/start/${startTime}/end/${endTime}`;
this.matchInfo = (matchId) =>
`/crm/cod/v2/title/${this.game}/platform/${this.platform}/fullMatch/wz/${matchId}/en`;
`/crm/cod/v2/title/${this.game}/platform/${this.platform}/fullMatch/${this.mode}/${matchId}/en`;
this.matchHeatMap = (matchId) =>
`/ce/v1/title/${this.game}/platform/${this.platform}/match/${matchId}/matchMapEvents`;
this.seasonLoot = () =>
@ -393,6 +401,7 @@ class Endpoints {
`/crm/cod/v2/accounts/platform/${this.platform}/${this.lookupType}/${this.gamertag}`;
this.settings = () =>
`/preferences/v1/platform/${this.platform}/${this.lookupType}/${this.gamertag}/list`;
this.friendsList = () => `/codfriends/v1/compendium`;
this.friendAction = (action) =>
`/codfriends/v1/${action}/${this.platform}/${this.lookupType}/${this.gamertag}`;
this.search = () =>
@ -425,9 +434,9 @@ class TelescopeEndpoints {
}
class WZ {
constructor() {
this.fullData = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.fullData = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -442,9 +451,10 @@ class WZ {
);
return yield sendRequest(endpoint.fullData());
});
this.combatHistory = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistory = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -459,9 +469,10 @@ class WZ {
);
return yield sendRequest(endpoint.combatHistory());
});
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -478,9 +489,10 @@ class WZ {
endpoint.combatHistoryWithDate(startTime, endTime)
);
});
this.breakdown = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdown = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -495,9 +507,10 @@ class WZ {
);
return yield sendRequest(endpoint.breakdown());
});
this.breakdownWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdownWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -514,9 +527,10 @@ class WZ {
endpoint.breakdownWithDate(startTime, endTime)
);
});
this.matchInfo = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchInfo = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -531,6 +545,7 @@ class WZ {
);
return yield sendRequest(endpoint.matchInfo(matchId));
});
};
this.cleanGameMode = (mode) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
//@ts-ignore
@ -542,9 +557,9 @@ class WZ {
}
class MW {
constructor() {
this.fullData = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.fullData = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -559,9 +574,10 @@ class MW {
);
return yield sendRequest(endpoint.fullData());
});
this.combatHistory = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistory = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -576,9 +592,10 @@ class MW {
);
return yield sendRequest(endpoint.combatHistory());
});
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -595,9 +612,10 @@ class MW {
endpoint.combatHistoryWithDate(startTime, endTime)
);
});
this.breakdown = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdown = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -612,9 +630,10 @@ class MW {
);
return yield sendRequest(endpoint.breakdown());
});
this.breakdownWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdownWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -631,9 +650,10 @@ class MW {
endpoint.breakdownWithDate(startTime, endTime)
);
});
this.matchInfo = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchInfo = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -648,9 +668,10 @@ class MW {
);
return yield sendRequest(endpoint.matchInfo(matchId));
});
this.matchHeatMap = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchHeatMap = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -665,9 +686,10 @@ class MW {
);
return yield sendRequest(endpoint.matchHeatMap(matchId));
});
this.seasonloot = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.seasonloot = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -682,9 +704,10 @@ class MW {
);
return yield sendRequest(endpoint.seasonLoot());
});
this.bpProg = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bpProg = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -699,9 +722,10 @@ class MW {
);
return yield sendRequest(endpoint.bpProg());
});
this.bundleInfo = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bundleInfo = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -716,9 +740,10 @@ class MW {
);
return yield sendRequest(endpoint.bundleInfo());
});
this.mapList = (platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.mapList = (platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -733,9 +758,10 @@ class MW {
);
return yield sendRequest(endpoint.mapList());
});
this.communityMapDataForMapMode = (mapId, gamemode, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.communityMapDataForMapMode = (mapId, gamemode, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -752,6 +778,7 @@ class MW {
endpoint.communityMapDataForMapMode(mapId, gamemode)
);
});
};
}
}
class MW2 {
@ -892,9 +919,9 @@ class WZM {
}
class CW {
constructor() {
this.fullData = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.fullData = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -909,9 +936,10 @@ class CW {
);
return yield sendRequest(endpoint.fullData());
});
this.combatHistory = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistory = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -926,9 +954,10 @@ class CW {
);
return yield sendRequest(endpoint.combatHistory());
});
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -945,9 +974,10 @@ class CW {
endpoint.combatHistoryWithDate(startTime, endTime)
);
});
this.breakdown = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdown = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -962,9 +992,10 @@ class CW {
);
return yield sendRequest(endpoint.breakdown());
});
this.breakdownWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdownWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -981,9 +1012,10 @@ class CW {
endpoint.breakdownWithDate(startTime, endTime)
);
});
this.seasonloot = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.seasonloot = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -998,9 +1030,10 @@ class CW {
);
return yield sendRequest(endpoint.seasonLoot());
});
this.bpProg = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bpProg = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1015,9 +1048,10 @@ class CW {
);
return yield sendRequest(endpoint.bpProg());
});
this.bundleInfo = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bundleInfo = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1032,9 +1066,10 @@ class CW {
);
return yield sendRequest(endpoint.bundleInfo());
});
this.mapList = (platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.mapList = (platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1049,9 +1084,10 @@ class CW {
);
return yield sendRequest(endpoint.mapList());
});
this.matchInfo = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchInfo = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1066,9 +1102,10 @@ class CW {
);
return yield sendRequest(endpoint.matchInfo(matchId));
});
this.matchHeatMap = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchHeatMap = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1083,13 +1120,14 @@ class CW {
);
return yield sendRequest(endpoint.matchHeatMap(matchId));
});
};
}
}
class VG {
constructor() {
this.fullData = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.fullData = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1104,9 +1142,10 @@ class VG {
);
return yield sendRequest(endpoint.fullData());
});
this.combatHistory = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistory = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1121,9 +1160,10 @@ class VG {
);
return yield sendRequest(endpoint.combatHistory());
});
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.combatHistoryWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1140,9 +1180,10 @@ class VG {
endpoint.combatHistoryWithDate(startTime, endTime)
);
});
this.breakdown = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdown = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1157,9 +1198,10 @@ class VG {
);
return yield sendRequest(endpoint.breakdown());
});
this.breakdownWithDate = (gamertag, startTime, endTime, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.breakdownWithDate = (gamertag, startTime, endTime, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1176,9 +1218,10 @@ class VG {
endpoint.breakdownWithDate(startTime, endTime)
);
});
this.seasonloot = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.seasonloot = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1193,9 +1236,10 @@ class VG {
);
return yield sendRequest(endpoint.seasonLoot());
});
this.bpProg = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bpProg = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1210,9 +1254,10 @@ class VG {
);
return yield sendRequest(endpoint.bpProg());
});
this.bundleInfo = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.bundleInfo = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1227,9 +1272,10 @@ class VG {
);
return yield sendRequest(endpoint.bundleInfo());
});
this.mapList = (platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.mapList = (platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1244,9 +1290,10 @@ class VG {
);
return yield sendRequest(endpoint.mapList());
});
this.matchInfo = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchInfo = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1261,9 +1308,10 @@ class VG {
);
return yield sendRequest(endpoint.matchInfo(matchId));
});
this.matchHeatMap = (matchId, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.matchHeatMap = (matchId, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1278,6 +1326,7 @@ class VG {
);
return yield sendRequest(endpoint.matchHeatMap(matchId));
});
};
}
}
class SHOP {
@ -1304,9 +1353,9 @@ class SHOP {
);
return yield sendRequest(endpoint.bundleInformation(title, bundleId));
});
this.battlePassLoot = (title, season, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.battlePassLoot = (title, season, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1321,13 +1370,14 @@ class SHOP {
);
return yield sendRequest(endpoint.battlePassLoot(season));
});
};
}
}
class USER {
constructor() {
this.friendFeed = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.friendFeed = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1342,6 +1392,7 @@ class USER {
);
return yield sendRequest(endpoint.friendFeed());
});
};
this.eventFeed = () =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
const endpoint = new Endpoints(
@ -1375,9 +1426,9 @@ class USER {
);
return yield sendRequestUserInfo(endpoint.userInfo());
});
this.codPoints = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.codPoints = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1392,9 +1443,10 @@ class USER {
);
return yield sendRequest(endpoint.codPoints());
});
this.connectedAccounts = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.connectedAccounts = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1409,9 +1461,10 @@ class USER {
);
return yield sendRequest(endpoint.connectedAccounts());
});
this.settings = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
};
this.settings = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1426,9 +1479,21 @@ class USER {
);
return yield sendRequest(endpoint.settings());
});
this.friendAction = (gamertag, platform, action) =>
};
this.friendsList = () =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
const endpoint = new Endpoints(
games.NULL,
'',
platforms.NULL,
modes.NULL,
''
);
return yield sendRequest(endpoint.friendsList());
});
this.friendAction = (gamertag, platform, action) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1443,8 +1508,10 @@ class USER {
);
return yield sendPostRequest(endpoint.friendAction(action), '{}');
});
};
}
}
class DB {
constructor() {
this.accolades = () =>
@ -1471,11 +1538,12 @@ class DB {
});
}
}
class ALT {
constructor() {
this.search = (gamertag, platform) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
var gamertag, platform, lookupType;
this.search = (gamertag, platform) => {
var gamertag, platform, lookupType;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
({
gamertag,
_platform: platform,
@ -1490,6 +1558,7 @@ class ALT {
);
return yield sendRequest(endpoint.search());
});
};
this.cleanWeapon = (weapon) =>
tslib_1.__awaiter(this, void 0, void 0, function* () {
//@ts-ignore
@ -1523,4 +1592,4 @@ const CDN = new DB();
exports.CDN = CDN;
const Misc = new ALT();
exports.Misc = Misc;
//# sourceMappingURL=index.js.map
// # sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,4 @@
interface IncomingHttpHeaders {
[header: string]: string | string[] | undefined;
}
import { IncomingHttpHeaders } from 'http';
import { request } from 'undici';
import wzMappings from '../data/game-modes.json';
import weaponMappings from '../data/weapon-ids.json';
@ -12,26 +9,14 @@ let baseCookie: string = 'new_SiteId=cod;ACT_SSO_LOCALE=en_US;country=US;';
let baseSsoToken: string = '';
let debugMode = false;
interface CustomHeaders extends Record<string, string | string[] | undefined> {
'X-XSRF-TOKEN'?: string;
'X-CSRF-TOKEN'?: string;
'Atvi-Auth'?: string;
ACT_SSO_COOKIE?: string;
atkn?: string;
cookie?: string;
'content-type'?: string;
'user-agent'?: string;
accept?: string;
authorization?: string;
'accept-language'?: string;
'cache-control'?: string;
pragma?: string;
'sec-ch-ua'?: string;
'sec-ch-ua-mobile'?: string;
'sec-ch-ua-platform'?: string;
'sec-fetch-dest'?: string;
'sec-fetch-mode'?: string;
'sec-fetch-site'?: string;
interface CustomHeaders extends IncomingHttpHeaders {
'X-XSRF-TOKEN'?: string | undefined;
'X-CSRF-TOKEN'?: string | undefined;
'Atvi-Auth'?: string | undefined;
ACT_SSO_COOKIE?: string | undefined;
atkn?: string | undefined;
cookie?: string | undefined;
'content-type'?: string | undefined;
}
let baseHeaders: CustomHeaders = {

View File

@ -7,8 +7,8 @@
"module": "CommonJS",
"target": "es2015",
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"outDir": "./src/js/dist",
"lib": ["esnext"],
"outDir": "dist",
"sourceMap": true,
"declaration": true,
"skipLibCheck": true,