@geekmidas/rate-limit 10.0.0-alpha.6 → 10.0.0-alpha.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/index.ts
3
3
  /**
4
4
  * Error thrown when rate limit is exceeded
@@ -30,15 +30,13 @@ async function checkRateLimit(config, ctx) {
30
30
  resetTime: Date.now() + config.windowMs,
31
31
  retryAfter: config.windowMs
32
32
  };
33
- const keyGenerator = config.keyGenerator || defaultKeyGenerator;
34
- const key = await keyGenerator(ctx);
33
+ const key = await (config.keyGenerator || defaultKeyGenerator)(ctx);
35
34
  const now = Date.now();
36
35
  let data = await config.cache.get(key);
37
36
  if (!data || data.resetTime <= now) {
38
- const resetTime = now + config.windowMs;
39
37
  data = {
40
38
  count: 1,
41
- resetTime
39
+ resetTime: now + config.windowMs
42
40
  };
43
41
  const ttlSeconds = Math.ceil(config.windowMs / 1e3);
44
42
  await config.cache.set(key, data, ttlSeconds);
@@ -79,10 +77,10 @@ function getRateLimitHeaders(info, config) {
79
77
  if (info.remaining === 0) headers["Retry-After"] = Math.ceil(info.retryAfter / 1e3).toString();
80
78
  return headers;
81
79
  }
82
-
83
80
  //#endregion
84
81
  exports.TooManyRequestsError = TooManyRequestsError;
85
82
  exports.checkRateLimit = checkRateLimit;
86
83
  exports.defaultKeyGenerator = defaultKeyGenerator;
87
84
  exports.getRateLimitHeaders = getRateLimitHeaders;
85
+
88
86
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["message?: string","retryAfter?: number","defaultKeyGenerator: RateLimitKeyGenerator","config: RateLimitConfig","ctx: RateLimitContext<TServices, TLogger, TSession>","info: RateLimitInfo","headers: RateLimitHeaders"],"sources":["../src/index.ts"],"sourcesContent":["import type { Cache } from '@geekmidas/cache';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class TooManyRequestsError extends Error {\n\tpublic readonly statusCode = 429;\n\tpublic readonly retryAfter?: number;\n\n\tconstructor(message?: string, retryAfter?: number) {\n\t\tsuper(message || 'Too many requests, please try again later.');\n\t\tthis.name = 'TooManyRequestsError';\n\t\tthis.retryAfter = retryAfter;\n\t}\n}\n\n/**\n * Rate limit configuration for an endpoint\n */\nexport interface RateLimitConfig {\n\t/**\n\t * Maximum number of requests allowed in the window\n\t */\n\tlimit: number;\n\n\t/**\n\t * Time window in milliseconds\n\t */\n\twindowMs: number;\n\n\t/**\n\t * Cache instance to store rate limit data\n\t */\n\tcache: Cache;\n\n\t/**\n\t * Key generator function to identify clients\n\t * Defaults to using IP address\n\t */\n\tkeyGenerator?: RateLimitKeyGenerator;\n\n\t/**\n\t * Skip rate limiting for certain requests\n\t */\n\tskip?: RateLimitSkipFn;\n\n\t/**\n\t * Optional message to return when rate limit is exceeded\n\t */\n\tmessage?: string;\n\n\t/**\n\t * Optional custom handler when rate limit is exceeded\n\t */\n\thandler?: RateLimitExceededHandler;\n\n\t/**\n\t * Whether to include rate limit headers in response\n\t * @default true\n\t */\n\tstandardHeaders?: boolean;\n\n\t/**\n\t * Whether to include legacy rate limit headers\n\t * @default false\n\t */\n\tlegacyHeaders?: boolean;\n}\n\n/**\n * Context for rate limiting decisions\n */\nexport interface RateLimitContext<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> {\n\theader: (key: string) => string | undefined;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tsession: TSession;\n\tpath: string;\n\tmethod: string;\n}\n\n/**\n * Function to generate a unique key for rate limiting\n */\nexport type RateLimitKeyGenerator<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => string | Promise<string>;\n\n/**\n * Function to determine if rate limiting should be skipped\n */\nexport type RateLimitSkipFn<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => boolean | Promise<boolean>;\n\n/**\n * Handler for when rate limit is exceeded\n */\nexport type RateLimitExceededHandler<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n\tinfo: RateLimitInfo,\n) => void | Promise<void>;\n\n/**\n * Information about current rate limit status\n */\nexport interface RateLimitInfo {\n\t/**\n\t * Current request count in the window\n\t */\n\tcount: number;\n\n\t/**\n\t * Maximum allowed requests\n\t */\n\tlimit: number;\n\n\t/**\n\t * Remaining requests allowed\n\t */\n\tremaining: number;\n\n\t/**\n\t * Time when the window resets (Unix timestamp)\n\t */\n\tresetTime: number;\n\n\t/**\n\t * Time until reset in milliseconds\n\t */\n\tretryAfter: number;\n}\n\n/**\n * Headers to be set on responses\n */\nexport interface RateLimitHeaders {\n\t'X-RateLimit-Limit'?: string;\n\t'X-RateLimit-Remaining'?: string;\n\t'X-RateLimit-Reset'?: string;\n\t'Retry-After'?: string;\n\t'X-RateLimit-Retry-After'?: string;\n\t'X-RateLimit-Reset-After'?: string;\n}\n\n/**\n * Data stored in cache for rate limiting\n */\nexport interface RateLimitData {\n\tcount: number;\n\tresetTime: number;\n}\n\n/**\n * Default key generator using IP address\n */\nexport const defaultKeyGenerator: RateLimitKeyGenerator = (ctx) => {\n\t// Try various headers for IP address\n\tconst ip =\n\t\tctx.header('x-forwarded-for')?.split(',')[0]?.trim() ||\n\t\tctx.header('x-real-ip') ||\n\t\tctx.header('x-client-ip') ||\n\t\tctx.header('cf-connecting-ip') ||\n\t\t'unknown';\n\n\treturn `rate-limit:${ctx.method}:${ctx.path}:${ip}`;\n};\n\n/**\n * Check rate limit and throw error if exceeded\n */\nexport async function checkRateLimit<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n>(\n\tconfig: RateLimitConfig,\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n): Promise<RateLimitInfo> {\n\t// Check if we should skip rate limiting\n\tif (config.skip && (await config.skip(ctx))) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tlimit: config.limit,\n\t\t\tremaining: config.limit,\n\t\t\tresetTime: Date.now() + config.windowMs,\n\t\t\tretryAfter: config.windowMs,\n\t\t};\n\t}\n\n\t// Generate key for this request\n\tconst keyGenerator = config.keyGenerator || defaultKeyGenerator;\n\tconst key = await keyGenerator(ctx);\n\n\t// Get current data from cache\n\tconst now = Date.now();\n\tlet data = await config.cache.get<RateLimitData>(key);\n\n\t// If no data or window expired, create new entry\n\tif (!data || data.resetTime <= now) {\n\t\tconst resetTime = now + config.windowMs;\n\t\tdata = { count: 1, resetTime };\n\n\t\t// Store with TTL matching the window\n\t\tconst ttlSeconds = Math.ceil(config.windowMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t} else {\n\t\t// Increment count\n\t\tdata.count++;\n\n\t\t// Calculate remaining TTL\n\t\tconst remainingMs = data.resetTime - now;\n\t\tconst ttlSeconds = Math.ceil(remainingMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t}\n\n\t// Calculate rate limit info\n\tconst info: RateLimitInfo = {\n\t\tcount: data.count,\n\t\tlimit: config.limit,\n\t\tremaining: Math.max(0, config.limit - data.count),\n\t\tresetTime: data.resetTime,\n\t\tretryAfter: data.resetTime - now,\n\t};\n\n\t// Check if limit exceeded\n\tif (data.count > config.limit) {\n\t\t// Call custom handler if provided\n\t\tif (config.handler) {\n\t\t\tawait config.handler(ctx, info);\n\t\t}\n\n\t\t// Throw rate limit error\n\t\tconst retryAfterSeconds = Math.ceil(info.retryAfter / 1000);\n\t\tthrow new TooManyRequestsError(\n\t\t\tconfig.message || 'Too many requests, please try again later.',\n\t\t\tretryAfterSeconds,\n\t\t);\n\t}\n\n\treturn info;\n}\n\n/**\n * Generate rate limit headers\n */\nexport function getRateLimitHeaders(\n\tinfo: RateLimitInfo,\n\tconfig: RateLimitConfig,\n): RateLimitHeaders {\n\tconst headers: RateLimitHeaders = {};\n\n\tif (config.standardHeaders !== false) {\n\t\theaders['X-RateLimit-Limit'] = info.limit.toString();\n\t\theaders['X-RateLimit-Remaining'] = info.remaining.toString();\n\t\theaders['X-RateLimit-Reset'] = new Date(info.resetTime).toISOString();\n\t}\n\n\tif (config.legacyHeaders) {\n\t\theaders['X-RateLimit-Retry-After'] = info.retryAfter.toString();\n\t\theaders['X-RateLimit-Reset-After'] = Math.ceil(\n\t\t\tinfo.retryAfter / 1000,\n\t\t).toString();\n\t}\n\n\t// Always set Retry-After when limit is exceeded\n\tif (info.remaining === 0) {\n\t\theaders['Retry-After'] = Math.ceil(info.retryAfter / 1000).toString();\n\t}\n\n\treturn headers;\n}\n"],"mappings":";;;;;AAOA,IAAa,uBAAb,cAA0C,MAAM;CAC/C,AAAgB,aAAa;CAC7B,AAAgB;CAEhB,YAAYA,SAAkBC,YAAqB;AAClD,QAAM,WAAW,6CAA6C;AAC9D,OAAK,OAAO;AACZ,OAAK,aAAa;CAClB;AACD;;;;AA8JD,MAAaC,sBAA6C,CAAC,QAAQ;CAElE,MAAM,KACL,IAAI,OAAO,kBAAkB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM,IACpD,IAAI,OAAO,YAAY,IACvB,IAAI,OAAO,cAAc,IACzB,IAAI,OAAO,mBAAmB,IAC9B;AAED,SAAQ,aAAa,IAAI,OAAO,GAAG,IAAI,KAAK,GAAG,GAAG;AAClD;;;;AAKD,eAAsB,eAKrBC,QACAC,KACyB;AAEzB,KAAI,OAAO,QAAS,MAAM,OAAO,KAAK,IAAI,CACzC,QAAO;EACN,OAAO;EACP,OAAO,OAAO;EACd,WAAW,OAAO;EAClB,WAAW,KAAK,KAAK,GAAG,OAAO;EAC/B,YAAY,OAAO;CACnB;CAIF,MAAM,eAAe,OAAO,gBAAgB;CAC5C,MAAM,MAAM,MAAM,aAAa,IAAI;CAGnC,MAAM,MAAM,KAAK,KAAK;CACtB,IAAI,OAAO,MAAM,OAAO,MAAM,IAAmB,IAAI;AAGrD,MAAK,QAAQ,KAAK,aAAa,KAAK;EACnC,MAAM,YAAY,MAAM,OAAO;AAC/B,SAAO;GAAE,OAAO;GAAG;EAAW;EAG9B,MAAM,aAAa,KAAK,KAAK,OAAO,WAAW,IAAK;AACpD,QAAM,OAAO,MAAM,IAAI,KAAK,MAAM,WAAW;CAC7C,OAAM;AAEN,OAAK;EAGL,MAAM,cAAc,KAAK,YAAY;EACrC,MAAM,aAAa,KAAK,KAAK,cAAc,IAAK;AAChD,QAAM,OAAO,MAAM,IAAI,KAAK,MAAM,WAAW;CAC7C;CAGD,MAAMC,OAAsB;EAC3B,OAAO,KAAK;EACZ,OAAO,OAAO;EACd,WAAW,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,MAAM;EACjD,WAAW,KAAK;EAChB,YAAY,KAAK,YAAY;CAC7B;AAGD,KAAI,KAAK,QAAQ,OAAO,OAAO;AAE9B,MAAI,OAAO,QACV,OAAM,OAAO,QAAQ,KAAK,KAAK;EAIhC,MAAM,oBAAoB,KAAK,KAAK,KAAK,aAAa,IAAK;AAC3D,QAAM,IAAI,qBACT,OAAO,WAAW,8CAClB;CAED;AAED,QAAO;AACP;;;;AAKD,SAAgB,oBACfA,MACAF,QACmB;CACnB,MAAMG,UAA4B,CAAE;AAEpC,KAAI,OAAO,oBAAoB,OAAO;AACrC,UAAQ,uBAAuB,KAAK,MAAM,UAAU;AACpD,UAAQ,2BAA2B,KAAK,UAAU,UAAU;AAC5D,UAAQ,uBAAuB,IAAI,KAAK,KAAK,WAAW,aAAa;CACrE;AAED,KAAI,OAAO,eAAe;AACzB,UAAQ,6BAA6B,KAAK,WAAW,UAAU;AAC/D,UAAQ,6BAA6B,KAAK,KACzC,KAAK,aAAa,IAClB,CAAC,UAAU;CACZ;AAGD,KAAI,KAAK,cAAc,EACtB,SAAQ,iBAAiB,KAAK,KAAK,KAAK,aAAa,IAAK,CAAC,UAAU;AAGtE,QAAO;AACP"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Cache } from '@geekmidas/cache';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class TooManyRequestsError extends Error {\n\tpublic readonly statusCode = 429;\n\tpublic readonly retryAfter?: number;\n\n\tconstructor(message?: string, retryAfter?: number) {\n\t\tsuper(message || 'Too many requests, please try again later.');\n\t\tthis.name = 'TooManyRequestsError';\n\t\tthis.retryAfter = retryAfter;\n\t}\n}\n\n/**\n * Rate limit configuration for an endpoint\n */\nexport interface RateLimitConfig {\n\t/**\n\t * Maximum number of requests allowed in the window\n\t */\n\tlimit: number;\n\n\t/**\n\t * Time window in milliseconds\n\t */\n\twindowMs: number;\n\n\t/**\n\t * Cache instance to store rate limit data\n\t */\n\tcache: Cache;\n\n\t/**\n\t * Key generator function to identify clients\n\t * Defaults to using IP address\n\t */\n\tkeyGenerator?: RateLimitKeyGenerator;\n\n\t/**\n\t * Skip rate limiting for certain requests\n\t */\n\tskip?: RateLimitSkipFn;\n\n\t/**\n\t * Optional message to return when rate limit is exceeded\n\t */\n\tmessage?: string;\n\n\t/**\n\t * Optional custom handler when rate limit is exceeded\n\t */\n\thandler?: RateLimitExceededHandler;\n\n\t/**\n\t * Whether to include rate limit headers in response\n\t * @default true\n\t */\n\tstandardHeaders?: boolean;\n\n\t/**\n\t * Whether to include legacy rate limit headers\n\t * @default false\n\t */\n\tlegacyHeaders?: boolean;\n}\n\n/**\n * Context for rate limiting decisions\n */\nexport interface RateLimitContext<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> {\n\theader: (key: string) => string | undefined;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tsession: TSession;\n\tpath: string;\n\tmethod: string;\n}\n\n/**\n * Function to generate a unique key for rate limiting\n */\nexport type RateLimitKeyGenerator<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => string | Promise<string>;\n\n/**\n * Function to determine if rate limiting should be skipped\n */\nexport type RateLimitSkipFn<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => boolean | Promise<boolean>;\n\n/**\n * Handler for when rate limit is exceeded\n */\nexport type RateLimitExceededHandler<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n\tinfo: RateLimitInfo,\n) => void | Promise<void>;\n\n/**\n * Information about current rate limit status\n */\nexport interface RateLimitInfo {\n\t/**\n\t * Current request count in the window\n\t */\n\tcount: number;\n\n\t/**\n\t * Maximum allowed requests\n\t */\n\tlimit: number;\n\n\t/**\n\t * Remaining requests allowed\n\t */\n\tremaining: number;\n\n\t/**\n\t * Time when the window resets (Unix timestamp)\n\t */\n\tresetTime: number;\n\n\t/**\n\t * Time until reset in milliseconds\n\t */\n\tretryAfter: number;\n}\n\n/**\n * Headers to be set on responses\n */\nexport interface RateLimitHeaders {\n\t'X-RateLimit-Limit'?: string;\n\t'X-RateLimit-Remaining'?: string;\n\t'X-RateLimit-Reset'?: string;\n\t'Retry-After'?: string;\n\t'X-RateLimit-Retry-After'?: string;\n\t'X-RateLimit-Reset-After'?: string;\n}\n\n/**\n * Data stored in cache for rate limiting\n */\nexport interface RateLimitData {\n\tcount: number;\n\tresetTime: number;\n}\n\n/**\n * Default key generator using IP address\n */\nexport const defaultKeyGenerator: RateLimitKeyGenerator = (ctx) => {\n\t// Try various headers for IP address\n\tconst ip =\n\t\tctx.header('x-forwarded-for')?.split(',')[0]?.trim() ||\n\t\tctx.header('x-real-ip') ||\n\t\tctx.header('x-client-ip') ||\n\t\tctx.header('cf-connecting-ip') ||\n\t\t'unknown';\n\n\treturn `rate-limit:${ctx.method}:${ctx.path}:${ip}`;\n};\n\n/**\n * Check rate limit and throw error if exceeded\n */\nexport async function checkRateLimit<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n>(\n\tconfig: RateLimitConfig,\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n): Promise<RateLimitInfo> {\n\t// Check if we should skip rate limiting\n\tif (config.skip && (await config.skip(ctx))) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tlimit: config.limit,\n\t\t\tremaining: config.limit,\n\t\t\tresetTime: Date.now() + config.windowMs,\n\t\t\tretryAfter: config.windowMs,\n\t\t};\n\t}\n\n\t// Generate key for this request\n\tconst keyGenerator = config.keyGenerator || defaultKeyGenerator;\n\tconst key = await keyGenerator(ctx);\n\n\t// Get current data from cache\n\tconst now = Date.now();\n\tlet data = await config.cache.get<RateLimitData>(key);\n\n\t// If no data or window expired, create new entry\n\tif (!data || data.resetTime <= now) {\n\t\tconst resetTime = now + config.windowMs;\n\t\tdata = { count: 1, resetTime };\n\n\t\t// Store with TTL matching the window\n\t\tconst ttlSeconds = Math.ceil(config.windowMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t} else {\n\t\t// Increment count\n\t\tdata.count++;\n\n\t\t// Calculate remaining TTL\n\t\tconst remainingMs = data.resetTime - now;\n\t\tconst ttlSeconds = Math.ceil(remainingMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t}\n\n\t// Calculate rate limit info\n\tconst info: RateLimitInfo = {\n\t\tcount: data.count,\n\t\tlimit: config.limit,\n\t\tremaining: Math.max(0, config.limit - data.count),\n\t\tresetTime: data.resetTime,\n\t\tretryAfter: data.resetTime - now,\n\t};\n\n\t// Check if limit exceeded\n\tif (data.count > config.limit) {\n\t\t// Call custom handler if provided\n\t\tif (config.handler) {\n\t\t\tawait config.handler(ctx, info);\n\t\t}\n\n\t\t// Throw rate limit error\n\t\tconst retryAfterSeconds = Math.ceil(info.retryAfter / 1000);\n\t\tthrow new TooManyRequestsError(\n\t\t\tconfig.message || 'Too many requests, please try again later.',\n\t\t\tretryAfterSeconds,\n\t\t);\n\t}\n\n\treturn info;\n}\n\n/**\n * Generate rate limit headers\n */\nexport function getRateLimitHeaders(\n\tinfo: RateLimitInfo,\n\tconfig: RateLimitConfig,\n): RateLimitHeaders {\n\tconst headers: RateLimitHeaders = {};\n\n\tif (config.standardHeaders !== false) {\n\t\theaders['X-RateLimit-Limit'] = info.limit.toString();\n\t\theaders['X-RateLimit-Remaining'] = info.remaining.toString();\n\t\theaders['X-RateLimit-Reset'] = new Date(info.resetTime).toISOString();\n\t}\n\n\tif (config.legacyHeaders) {\n\t\theaders['X-RateLimit-Retry-After'] = info.retryAfter.toString();\n\t\theaders['X-RateLimit-Reset-After'] = Math.ceil(\n\t\t\tinfo.retryAfter / 1000,\n\t\t).toString();\n\t}\n\n\t// Always set Retry-After when limit is exceeded\n\tif (info.remaining === 0) {\n\t\theaders['Retry-After'] = Math.ceil(info.retryAfter / 1000).toString();\n\t}\n\n\treturn headers;\n}\n"],"mappings":";;;;;AAOA,IAAa,uBAAb,cAA0C,MAAM;CAC/C,aAA6B;CAC7B;CAEA,YAAY,SAAkB,YAAqB;EAClD,MAAM,WAAW,4CAA4C;EAC7D,KAAK,OAAO;EACZ,KAAK,aAAa;CACnB;AACD;;;;AA8JA,MAAa,uBAA8C,QAAQ;CAElE,MAAM,KACL,IAAI,OAAO,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,KACnD,IAAI,OAAO,WAAW,KACtB,IAAI,OAAO,aAAa,KACxB,IAAI,OAAO,kBAAkB,KAC7B;CAED,OAAO,cAAc,IAAI,OAAO,GAAG,IAAI,KAAK,GAAG;AAChD;;;;AAKA,eAAsB,eAKrB,QACA,KACyB;CAEzB,IAAI,OAAO,QAAS,MAAM,OAAO,KAAK,GAAG,GACxC,OAAO;EACN,OAAO;EACP,OAAO,OAAO;EACd,WAAW,OAAO;EAClB,WAAW,KAAK,IAAI,IAAI,OAAO;EAC/B,YAAY,OAAO;CACpB;CAKD,MAAM,MAAM,OADS,OAAO,gBAAgB,oBAAA,CACb,GAAG;CAGlC,MAAM,MAAM,KAAK,IAAI;CACrB,IAAI,OAAO,MAAM,OAAO,MAAM,IAAmB,GAAG;CAGpD,IAAI,CAAC,QAAQ,KAAK,aAAa,KAAK;EAEnC,OAAO;GAAE,OAAO;GAAG,WADD,MAAM,OAAO;EACF;EAG7B,MAAM,aAAa,KAAK,KAAK,OAAO,WAAW,GAAI;EACnD,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,UAAU;CAC7C,OAAO;EAEN,KAAK;EAGL,MAAM,cAAc,KAAK,YAAY;EACrC,MAAM,aAAa,KAAK,KAAK,cAAc,GAAI;EAC/C,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,UAAU;CAC7C;CAGA,MAAM,OAAsB;EAC3B,OAAO,KAAK;EACZ,OAAO,OAAO;EACd,WAAW,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,KAAK;EAChD,WAAW,KAAK;EAChB,YAAY,KAAK,YAAY;CAC9B;CAGA,IAAI,KAAK,QAAQ,OAAO,OAAO;EAE9B,IAAI,OAAO,SACV,MAAM,OAAO,QAAQ,KAAK,IAAI;EAI/B,MAAM,oBAAoB,KAAK,KAAK,KAAK,aAAa,GAAI;EAC1D,MAAM,IAAI,qBACT,OAAO,WAAW,8CAClB,iBACD;CACD;CAEA,OAAO;AACR;;;;AAKA,SAAgB,oBACf,MACA,QACmB;CACnB,MAAM,UAA4B,CAAC;CAEnC,IAAI,OAAO,oBAAoB,OAAO;EACrC,QAAQ,uBAAuB,KAAK,MAAM,SAAS;EACnD,QAAQ,2BAA2B,KAAK,UAAU,SAAS;EAC3D,QAAQ,uBAAuB,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,YAAY;CACrE;CAEA,IAAI,OAAO,eAAe;EACzB,QAAQ,6BAA6B,KAAK,WAAW,SAAS;EAC9D,QAAQ,6BAA6B,KAAK,KACzC,KAAK,aAAa,GACnB,CAAC,CAAC,SAAS;CACZ;CAGA,IAAI,KAAK,cAAc,GACtB,QAAQ,iBAAiB,KAAK,KAAK,KAAK,aAAa,GAAI,CAAC,CAAC,SAAS;CAGrE,OAAO;AACR"}
package/dist/index.d.cts CHANGED
@@ -1,13 +1,11 @@
1
1
  import { Cache } from "@geekmidas/cache";
2
2
  import { Logger } from "@geekmidas/logger";
3
3
  import { Service, ServiceRecord } from "@geekmidas/services";
4
-
5
4
  //#region src/index.d.ts
6
-
7
5
  /**
8
6
  * Error thrown when rate limit is exceeded
9
7
  */
10
- declare class TooManyRequestsError extends Error {
8
+ export declare class TooManyRequestsError extends Error {
11
9
  readonly statusCode = 429;
12
10
  readonly retryAfter?: number;
13
11
  constructor(message?: string, retryAfter?: number);
@@ -15,7 +13,7 @@ declare class TooManyRequestsError extends Error {
15
13
  /**
16
14
  * Rate limit configuration for an endpoint
17
15
  */
18
- interface RateLimitConfig {
16
+ export interface RateLimitConfig {
19
17
  /**
20
18
  * Maximum number of requests allowed in the window
21
19
  */
@@ -59,7 +57,7 @@ interface RateLimitConfig {
59
57
  /**
60
58
  * Context for rate limiting decisions
61
59
  */
62
- interface RateLimitContext<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> {
60
+ export interface RateLimitContext<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> {
63
61
  header: (key: string) => string | undefined;
64
62
  services: ServiceRecord<TServices>;
65
63
  logger: TLogger;
@@ -70,19 +68,19 @@ interface RateLimitContext<TServices extends Service[] = [], TLogger extends Log
70
68
  /**
71
69
  * Function to generate a unique key for rate limiting
72
70
  */
73
- type RateLimitKeyGenerator<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => string | Promise<string>;
71
+ export type RateLimitKeyGenerator<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => string | Promise<string>;
74
72
  /**
75
73
  * Function to determine if rate limiting should be skipped
76
74
  */
77
- type RateLimitSkipFn<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => boolean | Promise<boolean>;
75
+ export type RateLimitSkipFn<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => boolean | Promise<boolean>;
78
76
  /**
79
77
  * Handler for when rate limit is exceeded
80
78
  */
81
- type RateLimitExceededHandler<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>, info: RateLimitInfo) => void | Promise<void>;
79
+ export type RateLimitExceededHandler<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>, info: RateLimitInfo) => void | Promise<void>;
82
80
  /**
83
81
  * Information about current rate limit status
84
82
  */
85
- interface RateLimitInfo {
83
+ export interface RateLimitInfo {
86
84
  /**
87
85
  * Current request count in the window
88
86
  */
@@ -107,7 +105,7 @@ interface RateLimitInfo {
107
105
  /**
108
106
  * Headers to be set on responses
109
107
  */
110
- interface RateLimitHeaders {
108
+ export interface RateLimitHeaders {
111
109
  'X-RateLimit-Limit'?: string;
112
110
  'X-RateLimit-Remaining'?: string;
113
111
  'X-RateLimit-Reset'?: string;
@@ -118,23 +116,21 @@ interface RateLimitHeaders {
118
116
  /**
119
117
  * Data stored in cache for rate limiting
120
118
  */
121
- interface RateLimitData {
119
+ export interface RateLimitData {
122
120
  count: number;
123
121
  resetTime: number;
124
122
  }
125
123
  /**
126
124
  * Default key generator using IP address
127
125
  */
128
- declare const defaultKeyGenerator: RateLimitKeyGenerator;
126
+ export declare const defaultKeyGenerator: RateLimitKeyGenerator;
129
127
  /**
130
128
  * Check rate limit and throw error if exceeded
131
129
  */
132
- declare function checkRateLimit<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown>(config: RateLimitConfig, ctx: RateLimitContext<TServices, TLogger, TSession>): Promise<RateLimitInfo>;
130
+ export declare function checkRateLimit<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown>(config: RateLimitConfig, ctx: RateLimitContext<TServices, TLogger, TSession>): Promise<RateLimitInfo>;
133
131
  /**
134
132
  * Generate rate limit headers
135
133
  */
136
- declare function getRateLimitHeaders(info: RateLimitInfo, config: RateLimitConfig): RateLimitHeaders;
137
- //# sourceMappingURL=index.d.ts.map
134
+ export declare function getRateLimitHeaders(info: RateLimitInfo, config: RateLimitConfig): RateLimitHeaders;
138
135
  //#endregion
139
- export { RateLimitConfig, RateLimitContext, RateLimitData, RateLimitExceededHandler, RateLimitHeaders, RateLimitInfo, RateLimitKeyGenerator, RateLimitSkipFn, TooManyRequestsError, checkRateLimit, defaultKeyGenerator, getRateLimitHeaders };
140
136
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAOA;AAciB,cAdJ,oBAAA,SAA6B,KAAK,CAcf;EAAA,SAAA,UAAA,GAAA,GAAA;EAAA,SAcxB,UAAA,CAAA,EAAA,MAAA;EAAK,WAMG,CAAA,OAAA,CAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA;;;AAemB;AAkBnC;AAAiC,UArDhB,eAAA,CAqDgB;EAAA;;;EAED,KAIP,EAAA,MAAA;EAAS;;;EAEhB,QAAA,EAAA,MAAA;EAQN;;;EACc,KACT,EAzDT,KAyDS;EAAM;;;;EAG4B,YAA7C,CAAA,EAtDU,qBAsDV;EAAgB;AACD;AAKrB;EAA2B,IAAA,CAAA,EAvDnB,eAuDmB;EAAA;;;EAEK,OAGT,CAAA,EAAA,MAAA;EAAS;;;EAAV,OACP,CAAA,EAnDJ,wBAmDI;EAAO;AAKtB;;;EAC0B,eACT,CAAA,EAAA,OAAA;EAAM;;;;EAG4B,aAA7C,CAAA,EAAA,OAAA;;;AAEa;AAKnB;AA8BiB,UAhFA,gBAgFgB,CAAA,kBA/Ed,OA+Ec,EAAA,GAAA,EAAA,EAAA,gBA9EhB,MA8EgB,GA9EP,MA8EO,EAAA,WAAA,OAAA,CAAA,CAAA;EAYhB,MAAA,EAAA,CAAA,GAAA,EAAA,MAAa,EAAA,GAAA,MAAA,GAAA,SAAA;EAQjB,QAAA,EA9FF,aAwGV,CAxGwB,SA8FS,CAAA;EAeZ,MAAA,EA5Gb,OA4Ga;EAAc,OAAA,EA3G1B,QA2G0B;EAAA,IACjB,EAAA,MAAA;EAAO,MACT,EAAA,MAAA;;;;;AAI0B,KAzG/B,qBAyG+B,CAAA,kBAxGxB,OAwGwB,EAAA,GAAA,EAAA,EAAA,gBAvG1B,MAuG0B,GAvGjB,MAuGiB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EApGrC,gBAoGqC,CApGpB,SAoGoB,EApGT,OAoGS,EApGA,QAoGA,CAAA,EAAA,GAAA,MAAA,GAnG7B,OAmG6B,CAAA,MAAA,CAAA;;;;AACjC,KA/FE,eA+FF,CAAA,kBA9FS,OA8FT,EAAA,GAAA,EAAA,EAAA,gBA7FO,MA6FP,GA7FgB,MA6FhB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EA1FJ,gBA0FI,CA1Fa,SA0Fb,EA1FwB,OA0FxB,EA1FiC,QA0FjC,CAAA,EAAA,GAAA,OAAA,GAzFK,OAyFL,CAAA,OAAA,CAAA;AAoEV;;;AAES,KA1JG,wBA0JH,CAAA,kBAzJU,OAyJV,EAAA,GAAA,EAAA,EAAA,gBAxJQ,MAwJR,GAxJiB,MAwJjB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EArJH,gBAqJG,CArJc,SAqJd,EArJyB,OAqJzB,EArJkC,QAqJlC,CAAA,EAAA,IAAA,EApJF,aAoJE,EAAA,GAAA,IAAA,GAnJG,OAmJH,CAAA,IAAA,CAAA;;AACU;;UA/IF,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;UA8BA,gBAAA;;;;;;;;;;;UAYA,aAAA;;;;;;;cAQJ,qBAAqB;;;;iBAeZ,iCACH,gCACF,SAAS,oCAGjB,sBACH,iBAAiB,WAAW,SAAS,YACxC,QAAQ;;;;iBAoEK,mBAAA,OACT,uBACE,kBACN"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;qBAOa,6BAA6B;WACzB;WACA;EAEhB,YAAY,kBAAkB;;;;;iBAUd;;;;EAIhB;;;;EAKA;;;;EAKA,OAAO;;;;;EAMP,eAAe;;;;EAKf,OAAO;;;;EAKP;;;;EAKA,UAAU;;;;;EAMV;;;;;EAMA;;;;;iBAMgB,iBAChB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB;EAEA,SAAS;EACT,UAAU,cAAc;EACxB,QAAQ;EACR,SAAS;EACT;EACA;;;;;YAMW,sBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,uBAC7B;;;;YAKF,gBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,wBAC5B;;;;YAKH,yBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,WAC1C,MAAM,yBACK;;;;iBAKK;;;;EAIhB;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;;iBAMgB;EAChB;EACA;EACA;EACA;EACA;EACA;;;;;iBAMgB;EAChB;EACA;;;;;qBAMY,qBAAqB;;;;wBAeZ,eACrB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,oBAEA,QAAQ,iBACR,KAAK,iBAAiB,WAAW,SAAS,YACxC,QAAQ;;;;wBAoEK,oBACf,MAAM,eACN,QAAQ,kBACN"}
package/dist/index.d.mts CHANGED
@@ -1,13 +1,11 @@
1
1
  import { Cache } from "@geekmidas/cache";
2
2
  import { Logger } from "@geekmidas/logger";
3
3
  import { Service, ServiceRecord } from "@geekmidas/services";
4
-
5
4
  //#region src/index.d.ts
6
-
7
5
  /**
8
6
  * Error thrown when rate limit is exceeded
9
7
  */
10
- declare class TooManyRequestsError extends Error {
8
+ export declare class TooManyRequestsError extends Error {
11
9
  readonly statusCode = 429;
12
10
  readonly retryAfter?: number;
13
11
  constructor(message?: string, retryAfter?: number);
@@ -15,7 +13,7 @@ declare class TooManyRequestsError extends Error {
15
13
  /**
16
14
  * Rate limit configuration for an endpoint
17
15
  */
18
- interface RateLimitConfig {
16
+ export interface RateLimitConfig {
19
17
  /**
20
18
  * Maximum number of requests allowed in the window
21
19
  */
@@ -59,7 +57,7 @@ interface RateLimitConfig {
59
57
  /**
60
58
  * Context for rate limiting decisions
61
59
  */
62
- interface RateLimitContext<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> {
60
+ export interface RateLimitContext<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> {
63
61
  header: (key: string) => string | undefined;
64
62
  services: ServiceRecord<TServices>;
65
63
  logger: TLogger;
@@ -70,19 +68,19 @@ interface RateLimitContext<TServices extends Service[] = [], TLogger extends Log
70
68
  /**
71
69
  * Function to generate a unique key for rate limiting
72
70
  */
73
- type RateLimitKeyGenerator<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => string | Promise<string>;
71
+ export type RateLimitKeyGenerator<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => string | Promise<string>;
74
72
  /**
75
73
  * Function to determine if rate limiting should be skipped
76
74
  */
77
- type RateLimitSkipFn<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => boolean | Promise<boolean>;
75
+ export type RateLimitSkipFn<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>) => boolean | Promise<boolean>;
78
76
  /**
79
77
  * Handler for when rate limit is exceeded
80
78
  */
81
- type RateLimitExceededHandler<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>, info: RateLimitInfo) => void | Promise<void>;
79
+ export type RateLimitExceededHandler<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown> = (ctx: RateLimitContext<TServices, TLogger, TSession>, info: RateLimitInfo) => void | Promise<void>;
82
80
  /**
83
81
  * Information about current rate limit status
84
82
  */
85
- interface RateLimitInfo {
83
+ export interface RateLimitInfo {
86
84
  /**
87
85
  * Current request count in the window
88
86
  */
@@ -107,7 +105,7 @@ interface RateLimitInfo {
107
105
  /**
108
106
  * Headers to be set on responses
109
107
  */
110
- interface RateLimitHeaders {
108
+ export interface RateLimitHeaders {
111
109
  'X-RateLimit-Limit'?: string;
112
110
  'X-RateLimit-Remaining'?: string;
113
111
  'X-RateLimit-Reset'?: string;
@@ -118,23 +116,21 @@ interface RateLimitHeaders {
118
116
  /**
119
117
  * Data stored in cache for rate limiting
120
118
  */
121
- interface RateLimitData {
119
+ export interface RateLimitData {
122
120
  count: number;
123
121
  resetTime: number;
124
122
  }
125
123
  /**
126
124
  * Default key generator using IP address
127
125
  */
128
- declare const defaultKeyGenerator: RateLimitKeyGenerator;
126
+ export declare const defaultKeyGenerator: RateLimitKeyGenerator;
129
127
  /**
130
128
  * Check rate limit and throw error if exceeded
131
129
  */
132
- declare function checkRateLimit<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown>(config: RateLimitConfig, ctx: RateLimitContext<TServices, TLogger, TSession>): Promise<RateLimitInfo>;
130
+ export declare function checkRateLimit<TServices extends Service[] = [], TLogger extends Logger = Logger, TSession = unknown>(config: RateLimitConfig, ctx: RateLimitContext<TServices, TLogger, TSession>): Promise<RateLimitInfo>;
133
131
  /**
134
132
  * Generate rate limit headers
135
133
  */
136
- declare function getRateLimitHeaders(info: RateLimitInfo, config: RateLimitConfig): RateLimitHeaders;
137
- //# sourceMappingURL=index.d.ts.map
134
+ export declare function getRateLimitHeaders(info: RateLimitInfo, config: RateLimitConfig): RateLimitHeaders;
138
135
  //#endregion
139
- export { RateLimitConfig, RateLimitContext, RateLimitData, RateLimitExceededHandler, RateLimitHeaders, RateLimitInfo, RateLimitKeyGenerator, RateLimitSkipFn, TooManyRequestsError, checkRateLimit, defaultKeyGenerator, getRateLimitHeaders };
140
136
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAOA;AAciB,cAdJ,oBAAA,SAA6B,KAAK,CAcf;EAAA,SAAA,UAAA,GAAA,GAAA;EAAA,SAcxB,UAAA,CAAA,EAAA,MAAA;EAAK,WAMG,CAAA,OAAA,CAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA;;;AAemB;AAkBnC;AAAiC,UArDhB,eAAA,CAqDgB;EAAA;;;EAED,KAIP,EAAA,MAAA;EAAS;;;EAEhB,QAAA,EAAA,MAAA;EAQN;;;EACc,KACT,EAzDT,KAyDS;EAAM;;;;EAG4B,YAA7C,CAAA,EAtDU,qBAsDV;EAAgB;AACD;AAKrB;EAA2B,IAAA,CAAA,EAvDnB,eAuDmB;EAAA;;;EAEK,OAGT,CAAA,EAAA,MAAA;EAAS;;;EAAV,OACP,CAAA,EAnDJ,wBAmDI;EAAO;AAKtB;;;EAC0B,eACT,CAAA,EAAA,OAAA;EAAM;;;;EAG4B,aAA7C,CAAA,EAAA,OAAA;;;AAEa;AAKnB;AA8BiB,UAhFA,gBAgFgB,CAAA,kBA/Ed,OA+Ec,EAAA,GAAA,EAAA,EAAA,gBA9EhB,MA8EgB,GA9EP,MA8EO,EAAA,WAAA,OAAA,CAAA,CAAA;EAYhB,MAAA,EAAA,CAAA,GAAA,EAAA,MAAa,EAAA,GAAA,MAAA,GAAA,SAAA;EAQjB,QAAA,EA9FF,aAwGV,CAxGwB,SA8FS,CAAA;EAeZ,MAAA,EA5Gb,OA4Ga;EAAc,OAAA,EA3G1B,QA2G0B;EAAA,IACjB,EAAA,MAAA;EAAO,MACT,EAAA,MAAA;;;;;AAI0B,KAzG/B,qBAyG+B,CAAA,kBAxGxB,OAwGwB,EAAA,GAAA,EAAA,EAAA,gBAvG1B,MAuG0B,GAvGjB,MAuGiB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EApGrC,gBAoGqC,CApGpB,SAoGoB,EApGT,OAoGS,EApGA,QAoGA,CAAA,EAAA,GAAA,MAAA,GAnG7B,OAmG6B,CAAA,MAAA,CAAA;;;;AACjC,KA/FE,eA+FF,CAAA,kBA9FS,OA8FT,EAAA,GAAA,EAAA,EAAA,gBA7FO,MA6FP,GA7FgB,MA6FhB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EA1FJ,gBA0FI,CA1Fa,SA0Fb,EA1FwB,OA0FxB,EA1FiC,QA0FjC,CAAA,EAAA,GAAA,OAAA,GAzFK,OAyFL,CAAA,OAAA,CAAA;AAoEV;;;AAES,KA1JG,wBA0JH,CAAA,kBAzJU,OAyJV,EAAA,GAAA,EAAA,EAAA,gBAxJQ,MAwJR,GAxJiB,MAwJjB,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,GAAA,EArJH,gBAqJG,CArJc,SAqJd,EArJyB,OAqJzB,EArJkC,QAqJlC,CAAA,EAAA,IAAA,EApJF,aAoJE,EAAA,GAAA,IAAA,GAnJG,OAmJH,CAAA,IAAA,CAAA;;AACU;;UA/IF,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;UA8BA,gBAAA;;;;;;;;;;;UAYA,aAAA;;;;;;;cAQJ,qBAAqB;;;;iBAeZ,iCACH,gCACF,SAAS,oCAGjB,sBACH,iBAAiB,WAAW,SAAS,YACxC,QAAQ;;;;iBAoEK,mBAAA,OACT,uBACE,kBACN"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;qBAOa,6BAA6B;WACzB;WACA;EAEhB,YAAY,kBAAkB;;;;;iBAUd;;;;EAIhB;;;;EAKA;;;;EAKA,OAAO;;;;;EAMP,eAAe;;;;EAKf,OAAO;;;;EAKP;;;;EAKA,UAAU;;;;;EAMV;;;;;EAMA;;;;;iBAMgB,iBAChB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB;EAEA,SAAS;EACT,UAAU,cAAc;EACxB,QAAQ;EACR,SAAS;EACT;EACA;;;;;YAMW,sBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,uBAC7B;;;;YAKF,gBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,wBAC5B;;;;YAKH,yBACX,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBAEA,KAAK,iBAAiB,WAAW,SAAS,WAC1C,MAAM,yBACK;;;;iBAKK;;;;EAIhB;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;;iBAMgB;EAChB;EACA;EACA;EACA;EACA;EACA;;;;;iBAMgB;EAChB;EACA;;;;;qBAMY,qBAAqB;;;;wBAeZ,eACrB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,oBAEA,QAAQ,iBACR,KAAK,iBAAiB,WAAW,SAAS,YACxC,QAAQ;;;;wBAoEK,oBACf,MAAM,eACN,QAAQ,kBACN"}
package/dist/index.mjs CHANGED
@@ -29,15 +29,13 @@ async function checkRateLimit(config, ctx) {
29
29
  resetTime: Date.now() + config.windowMs,
30
30
  retryAfter: config.windowMs
31
31
  };
32
- const keyGenerator = config.keyGenerator || defaultKeyGenerator;
33
- const key = await keyGenerator(ctx);
32
+ const key = await (config.keyGenerator || defaultKeyGenerator)(ctx);
34
33
  const now = Date.now();
35
34
  let data = await config.cache.get(key);
36
35
  if (!data || data.resetTime <= now) {
37
- const resetTime = now + config.windowMs;
38
36
  data = {
39
37
  count: 1,
40
- resetTime
38
+ resetTime: now + config.windowMs
41
39
  };
42
40
  const ttlSeconds = Math.ceil(config.windowMs / 1e3);
43
41
  await config.cache.set(key, data, ttlSeconds);
@@ -78,7 +76,7 @@ function getRateLimitHeaders(info, config) {
78
76
  if (info.remaining === 0) headers["Retry-After"] = Math.ceil(info.retryAfter / 1e3).toString();
79
77
  return headers;
80
78
  }
81
-
82
79
  //#endregion
83
80
  export { TooManyRequestsError, checkRateLimit, defaultKeyGenerator, getRateLimitHeaders };
81
+
84
82
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["message?: string","retryAfter?: number","defaultKeyGenerator: RateLimitKeyGenerator","config: RateLimitConfig","ctx: RateLimitContext<TServices, TLogger, TSession>","info: RateLimitInfo","headers: RateLimitHeaders"],"sources":["../src/index.ts"],"sourcesContent":["import type { Cache } from '@geekmidas/cache';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class TooManyRequestsError extends Error {\n\tpublic readonly statusCode = 429;\n\tpublic readonly retryAfter?: number;\n\n\tconstructor(message?: string, retryAfter?: number) {\n\t\tsuper(message || 'Too many requests, please try again later.');\n\t\tthis.name = 'TooManyRequestsError';\n\t\tthis.retryAfter = retryAfter;\n\t}\n}\n\n/**\n * Rate limit configuration for an endpoint\n */\nexport interface RateLimitConfig {\n\t/**\n\t * Maximum number of requests allowed in the window\n\t */\n\tlimit: number;\n\n\t/**\n\t * Time window in milliseconds\n\t */\n\twindowMs: number;\n\n\t/**\n\t * Cache instance to store rate limit data\n\t */\n\tcache: Cache;\n\n\t/**\n\t * Key generator function to identify clients\n\t * Defaults to using IP address\n\t */\n\tkeyGenerator?: RateLimitKeyGenerator;\n\n\t/**\n\t * Skip rate limiting for certain requests\n\t */\n\tskip?: RateLimitSkipFn;\n\n\t/**\n\t * Optional message to return when rate limit is exceeded\n\t */\n\tmessage?: string;\n\n\t/**\n\t * Optional custom handler when rate limit is exceeded\n\t */\n\thandler?: RateLimitExceededHandler;\n\n\t/**\n\t * Whether to include rate limit headers in response\n\t * @default true\n\t */\n\tstandardHeaders?: boolean;\n\n\t/**\n\t * Whether to include legacy rate limit headers\n\t * @default false\n\t */\n\tlegacyHeaders?: boolean;\n}\n\n/**\n * Context for rate limiting decisions\n */\nexport interface RateLimitContext<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> {\n\theader: (key: string) => string | undefined;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tsession: TSession;\n\tpath: string;\n\tmethod: string;\n}\n\n/**\n * Function to generate a unique key for rate limiting\n */\nexport type RateLimitKeyGenerator<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => string | Promise<string>;\n\n/**\n * Function to determine if rate limiting should be skipped\n */\nexport type RateLimitSkipFn<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => boolean | Promise<boolean>;\n\n/**\n * Handler for when rate limit is exceeded\n */\nexport type RateLimitExceededHandler<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n\tinfo: RateLimitInfo,\n) => void | Promise<void>;\n\n/**\n * Information about current rate limit status\n */\nexport interface RateLimitInfo {\n\t/**\n\t * Current request count in the window\n\t */\n\tcount: number;\n\n\t/**\n\t * Maximum allowed requests\n\t */\n\tlimit: number;\n\n\t/**\n\t * Remaining requests allowed\n\t */\n\tremaining: number;\n\n\t/**\n\t * Time when the window resets (Unix timestamp)\n\t */\n\tresetTime: number;\n\n\t/**\n\t * Time until reset in milliseconds\n\t */\n\tretryAfter: number;\n}\n\n/**\n * Headers to be set on responses\n */\nexport interface RateLimitHeaders {\n\t'X-RateLimit-Limit'?: string;\n\t'X-RateLimit-Remaining'?: string;\n\t'X-RateLimit-Reset'?: string;\n\t'Retry-After'?: string;\n\t'X-RateLimit-Retry-After'?: string;\n\t'X-RateLimit-Reset-After'?: string;\n}\n\n/**\n * Data stored in cache for rate limiting\n */\nexport interface RateLimitData {\n\tcount: number;\n\tresetTime: number;\n}\n\n/**\n * Default key generator using IP address\n */\nexport const defaultKeyGenerator: RateLimitKeyGenerator = (ctx) => {\n\t// Try various headers for IP address\n\tconst ip =\n\t\tctx.header('x-forwarded-for')?.split(',')[0]?.trim() ||\n\t\tctx.header('x-real-ip') ||\n\t\tctx.header('x-client-ip') ||\n\t\tctx.header('cf-connecting-ip') ||\n\t\t'unknown';\n\n\treturn `rate-limit:${ctx.method}:${ctx.path}:${ip}`;\n};\n\n/**\n * Check rate limit and throw error if exceeded\n */\nexport async function checkRateLimit<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n>(\n\tconfig: RateLimitConfig,\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n): Promise<RateLimitInfo> {\n\t// Check if we should skip rate limiting\n\tif (config.skip && (await config.skip(ctx))) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tlimit: config.limit,\n\t\t\tremaining: config.limit,\n\t\t\tresetTime: Date.now() + config.windowMs,\n\t\t\tretryAfter: config.windowMs,\n\t\t};\n\t}\n\n\t// Generate key for this request\n\tconst keyGenerator = config.keyGenerator || defaultKeyGenerator;\n\tconst key = await keyGenerator(ctx);\n\n\t// Get current data from cache\n\tconst now = Date.now();\n\tlet data = await config.cache.get<RateLimitData>(key);\n\n\t// If no data or window expired, create new entry\n\tif (!data || data.resetTime <= now) {\n\t\tconst resetTime = now + config.windowMs;\n\t\tdata = { count: 1, resetTime };\n\n\t\t// Store with TTL matching the window\n\t\tconst ttlSeconds = Math.ceil(config.windowMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t} else {\n\t\t// Increment count\n\t\tdata.count++;\n\n\t\t// Calculate remaining TTL\n\t\tconst remainingMs = data.resetTime - now;\n\t\tconst ttlSeconds = Math.ceil(remainingMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t}\n\n\t// Calculate rate limit info\n\tconst info: RateLimitInfo = {\n\t\tcount: data.count,\n\t\tlimit: config.limit,\n\t\tremaining: Math.max(0, config.limit - data.count),\n\t\tresetTime: data.resetTime,\n\t\tretryAfter: data.resetTime - now,\n\t};\n\n\t// Check if limit exceeded\n\tif (data.count > config.limit) {\n\t\t// Call custom handler if provided\n\t\tif (config.handler) {\n\t\t\tawait config.handler(ctx, info);\n\t\t}\n\n\t\t// Throw rate limit error\n\t\tconst retryAfterSeconds = Math.ceil(info.retryAfter / 1000);\n\t\tthrow new TooManyRequestsError(\n\t\t\tconfig.message || 'Too many requests, please try again later.',\n\t\t\tretryAfterSeconds,\n\t\t);\n\t}\n\n\treturn info;\n}\n\n/**\n * Generate rate limit headers\n */\nexport function getRateLimitHeaders(\n\tinfo: RateLimitInfo,\n\tconfig: RateLimitConfig,\n): RateLimitHeaders {\n\tconst headers: RateLimitHeaders = {};\n\n\tif (config.standardHeaders !== false) {\n\t\theaders['X-RateLimit-Limit'] = info.limit.toString();\n\t\theaders['X-RateLimit-Remaining'] = info.remaining.toString();\n\t\theaders['X-RateLimit-Reset'] = new Date(info.resetTime).toISOString();\n\t}\n\n\tif (config.legacyHeaders) {\n\t\theaders['X-RateLimit-Retry-After'] = info.retryAfter.toString();\n\t\theaders['X-RateLimit-Reset-After'] = Math.ceil(\n\t\t\tinfo.retryAfter / 1000,\n\t\t).toString();\n\t}\n\n\t// Always set Retry-After when limit is exceeded\n\tif (info.remaining === 0) {\n\t\theaders['Retry-After'] = Math.ceil(info.retryAfter / 1000).toString();\n\t}\n\n\treturn headers;\n}\n"],"mappings":";;;;AAOA,IAAa,uBAAb,cAA0C,MAAM;CAC/C,AAAgB,aAAa;CAC7B,AAAgB;CAEhB,YAAYA,SAAkBC,YAAqB;AAClD,QAAM,WAAW,6CAA6C;AAC9D,OAAK,OAAO;AACZ,OAAK,aAAa;CAClB;AACD;;;;AA8JD,MAAaC,sBAA6C,CAAC,QAAQ;CAElE,MAAM,KACL,IAAI,OAAO,kBAAkB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM,IACpD,IAAI,OAAO,YAAY,IACvB,IAAI,OAAO,cAAc,IACzB,IAAI,OAAO,mBAAmB,IAC9B;AAED,SAAQ,aAAa,IAAI,OAAO,GAAG,IAAI,KAAK,GAAG,GAAG;AAClD;;;;AAKD,eAAsB,eAKrBC,QACAC,KACyB;AAEzB,KAAI,OAAO,QAAS,MAAM,OAAO,KAAK,IAAI,CACzC,QAAO;EACN,OAAO;EACP,OAAO,OAAO;EACd,WAAW,OAAO;EAClB,WAAW,KAAK,KAAK,GAAG,OAAO;EAC/B,YAAY,OAAO;CACnB;CAIF,MAAM,eAAe,OAAO,gBAAgB;CAC5C,MAAM,MAAM,MAAM,aAAa,IAAI;CAGnC,MAAM,MAAM,KAAK,KAAK;CACtB,IAAI,OAAO,MAAM,OAAO,MAAM,IAAmB,IAAI;AAGrD,MAAK,QAAQ,KAAK,aAAa,KAAK;EACnC,MAAM,YAAY,MAAM,OAAO;AAC/B,SAAO;GAAE,OAAO;GAAG;EAAW;EAG9B,MAAM,aAAa,KAAK,KAAK,OAAO,WAAW,IAAK;AACpD,QAAM,OAAO,MAAM,IAAI,KAAK,MAAM,WAAW;CAC7C,OAAM;AAEN,OAAK;EAGL,MAAM,cAAc,KAAK,YAAY;EACrC,MAAM,aAAa,KAAK,KAAK,cAAc,IAAK;AAChD,QAAM,OAAO,MAAM,IAAI,KAAK,MAAM,WAAW;CAC7C;CAGD,MAAMC,OAAsB;EAC3B,OAAO,KAAK;EACZ,OAAO,OAAO;EACd,WAAW,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,MAAM;EACjD,WAAW,KAAK;EAChB,YAAY,KAAK,YAAY;CAC7B;AAGD,KAAI,KAAK,QAAQ,OAAO,OAAO;AAE9B,MAAI,OAAO,QACV,OAAM,OAAO,QAAQ,KAAK,KAAK;EAIhC,MAAM,oBAAoB,KAAK,KAAK,KAAK,aAAa,IAAK;AAC3D,QAAM,IAAI,qBACT,OAAO,WAAW,8CAClB;CAED;AAED,QAAO;AACP;;;;AAKD,SAAgB,oBACfA,MACAF,QACmB;CACnB,MAAMG,UAA4B,CAAE;AAEpC,KAAI,OAAO,oBAAoB,OAAO;AACrC,UAAQ,uBAAuB,KAAK,MAAM,UAAU;AACpD,UAAQ,2BAA2B,KAAK,UAAU,UAAU;AAC5D,UAAQ,uBAAuB,IAAI,KAAK,KAAK,WAAW,aAAa;CACrE;AAED,KAAI,OAAO,eAAe;AACzB,UAAQ,6BAA6B,KAAK,WAAW,UAAU;AAC/D,UAAQ,6BAA6B,KAAK,KACzC,KAAK,aAAa,IAClB,CAAC,UAAU;CACZ;AAGD,KAAI,KAAK,cAAc,EACtB,SAAQ,iBAAiB,KAAK,KAAK,KAAK,aAAa,IAAK,CAAC,UAAU;AAGtE,QAAO;AACP"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Cache } from '@geekmidas/cache';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class TooManyRequestsError extends Error {\n\tpublic readonly statusCode = 429;\n\tpublic readonly retryAfter?: number;\n\n\tconstructor(message?: string, retryAfter?: number) {\n\t\tsuper(message || 'Too many requests, please try again later.');\n\t\tthis.name = 'TooManyRequestsError';\n\t\tthis.retryAfter = retryAfter;\n\t}\n}\n\n/**\n * Rate limit configuration for an endpoint\n */\nexport interface RateLimitConfig {\n\t/**\n\t * Maximum number of requests allowed in the window\n\t */\n\tlimit: number;\n\n\t/**\n\t * Time window in milliseconds\n\t */\n\twindowMs: number;\n\n\t/**\n\t * Cache instance to store rate limit data\n\t */\n\tcache: Cache;\n\n\t/**\n\t * Key generator function to identify clients\n\t * Defaults to using IP address\n\t */\n\tkeyGenerator?: RateLimitKeyGenerator;\n\n\t/**\n\t * Skip rate limiting for certain requests\n\t */\n\tskip?: RateLimitSkipFn;\n\n\t/**\n\t * Optional message to return when rate limit is exceeded\n\t */\n\tmessage?: string;\n\n\t/**\n\t * Optional custom handler when rate limit is exceeded\n\t */\n\thandler?: RateLimitExceededHandler;\n\n\t/**\n\t * Whether to include rate limit headers in response\n\t * @default true\n\t */\n\tstandardHeaders?: boolean;\n\n\t/**\n\t * Whether to include legacy rate limit headers\n\t * @default false\n\t */\n\tlegacyHeaders?: boolean;\n}\n\n/**\n * Context for rate limiting decisions\n */\nexport interface RateLimitContext<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> {\n\theader: (key: string) => string | undefined;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tsession: TSession;\n\tpath: string;\n\tmethod: string;\n}\n\n/**\n * Function to generate a unique key for rate limiting\n */\nexport type RateLimitKeyGenerator<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => string | Promise<string>;\n\n/**\n * Function to determine if rate limiting should be skipped\n */\nexport type RateLimitSkipFn<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n) => boolean | Promise<boolean>;\n\n/**\n * Handler for when rate limit is exceeded\n */\nexport type RateLimitExceededHandler<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = (\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n\tinfo: RateLimitInfo,\n) => void | Promise<void>;\n\n/**\n * Information about current rate limit status\n */\nexport interface RateLimitInfo {\n\t/**\n\t * Current request count in the window\n\t */\n\tcount: number;\n\n\t/**\n\t * Maximum allowed requests\n\t */\n\tlimit: number;\n\n\t/**\n\t * Remaining requests allowed\n\t */\n\tremaining: number;\n\n\t/**\n\t * Time when the window resets (Unix timestamp)\n\t */\n\tresetTime: number;\n\n\t/**\n\t * Time until reset in milliseconds\n\t */\n\tretryAfter: number;\n}\n\n/**\n * Headers to be set on responses\n */\nexport interface RateLimitHeaders {\n\t'X-RateLimit-Limit'?: string;\n\t'X-RateLimit-Remaining'?: string;\n\t'X-RateLimit-Reset'?: string;\n\t'Retry-After'?: string;\n\t'X-RateLimit-Retry-After'?: string;\n\t'X-RateLimit-Reset-After'?: string;\n}\n\n/**\n * Data stored in cache for rate limiting\n */\nexport interface RateLimitData {\n\tcount: number;\n\tresetTime: number;\n}\n\n/**\n * Default key generator using IP address\n */\nexport const defaultKeyGenerator: RateLimitKeyGenerator = (ctx) => {\n\t// Try various headers for IP address\n\tconst ip =\n\t\tctx.header('x-forwarded-for')?.split(',')[0]?.trim() ||\n\t\tctx.header('x-real-ip') ||\n\t\tctx.header('x-client-ip') ||\n\t\tctx.header('cf-connecting-ip') ||\n\t\t'unknown';\n\n\treturn `rate-limit:${ctx.method}:${ctx.path}:${ip}`;\n};\n\n/**\n * Check rate limit and throw error if exceeded\n */\nexport async function checkRateLimit<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n>(\n\tconfig: RateLimitConfig,\n\tctx: RateLimitContext<TServices, TLogger, TSession>,\n): Promise<RateLimitInfo> {\n\t// Check if we should skip rate limiting\n\tif (config.skip && (await config.skip(ctx))) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tlimit: config.limit,\n\t\t\tremaining: config.limit,\n\t\t\tresetTime: Date.now() + config.windowMs,\n\t\t\tretryAfter: config.windowMs,\n\t\t};\n\t}\n\n\t// Generate key for this request\n\tconst keyGenerator = config.keyGenerator || defaultKeyGenerator;\n\tconst key = await keyGenerator(ctx);\n\n\t// Get current data from cache\n\tconst now = Date.now();\n\tlet data = await config.cache.get<RateLimitData>(key);\n\n\t// If no data or window expired, create new entry\n\tif (!data || data.resetTime <= now) {\n\t\tconst resetTime = now + config.windowMs;\n\t\tdata = { count: 1, resetTime };\n\n\t\t// Store with TTL matching the window\n\t\tconst ttlSeconds = Math.ceil(config.windowMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t} else {\n\t\t// Increment count\n\t\tdata.count++;\n\n\t\t// Calculate remaining TTL\n\t\tconst remainingMs = data.resetTime - now;\n\t\tconst ttlSeconds = Math.ceil(remainingMs / 1000);\n\t\tawait config.cache.set(key, data, ttlSeconds);\n\t}\n\n\t// Calculate rate limit info\n\tconst info: RateLimitInfo = {\n\t\tcount: data.count,\n\t\tlimit: config.limit,\n\t\tremaining: Math.max(0, config.limit - data.count),\n\t\tresetTime: data.resetTime,\n\t\tretryAfter: data.resetTime - now,\n\t};\n\n\t// Check if limit exceeded\n\tif (data.count > config.limit) {\n\t\t// Call custom handler if provided\n\t\tif (config.handler) {\n\t\t\tawait config.handler(ctx, info);\n\t\t}\n\n\t\t// Throw rate limit error\n\t\tconst retryAfterSeconds = Math.ceil(info.retryAfter / 1000);\n\t\tthrow new TooManyRequestsError(\n\t\t\tconfig.message || 'Too many requests, please try again later.',\n\t\t\tretryAfterSeconds,\n\t\t);\n\t}\n\n\treturn info;\n}\n\n/**\n * Generate rate limit headers\n */\nexport function getRateLimitHeaders(\n\tinfo: RateLimitInfo,\n\tconfig: RateLimitConfig,\n): RateLimitHeaders {\n\tconst headers: RateLimitHeaders = {};\n\n\tif (config.standardHeaders !== false) {\n\t\theaders['X-RateLimit-Limit'] = info.limit.toString();\n\t\theaders['X-RateLimit-Remaining'] = info.remaining.toString();\n\t\theaders['X-RateLimit-Reset'] = new Date(info.resetTime).toISOString();\n\t}\n\n\tif (config.legacyHeaders) {\n\t\theaders['X-RateLimit-Retry-After'] = info.retryAfter.toString();\n\t\theaders['X-RateLimit-Reset-After'] = Math.ceil(\n\t\t\tinfo.retryAfter / 1000,\n\t\t).toString();\n\t}\n\n\t// Always set Retry-After when limit is exceeded\n\tif (info.remaining === 0) {\n\t\theaders['Retry-After'] = Math.ceil(info.retryAfter / 1000).toString();\n\t}\n\n\treturn headers;\n}\n"],"mappings":";;;;AAOA,IAAa,uBAAb,cAA0C,MAAM;CAC/C,aAA6B;CAC7B;CAEA,YAAY,SAAkB,YAAqB;EAClD,MAAM,WAAW,4CAA4C;EAC7D,KAAK,OAAO;EACZ,KAAK,aAAa;CACnB;AACD;;;;AA8JA,MAAa,uBAA8C,QAAQ;CAElE,MAAM,KACL,IAAI,OAAO,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,KACnD,IAAI,OAAO,WAAW,KACtB,IAAI,OAAO,aAAa,KACxB,IAAI,OAAO,kBAAkB,KAC7B;CAED,OAAO,cAAc,IAAI,OAAO,GAAG,IAAI,KAAK,GAAG;AAChD;;;;AAKA,eAAsB,eAKrB,QACA,KACyB;CAEzB,IAAI,OAAO,QAAS,MAAM,OAAO,KAAK,GAAG,GACxC,OAAO;EACN,OAAO;EACP,OAAO,OAAO;EACd,WAAW,OAAO;EAClB,WAAW,KAAK,IAAI,IAAI,OAAO;EAC/B,YAAY,OAAO;CACpB;CAKD,MAAM,MAAM,OADS,OAAO,gBAAgB,oBAAA,CACb,GAAG;CAGlC,MAAM,MAAM,KAAK,IAAI;CACrB,IAAI,OAAO,MAAM,OAAO,MAAM,IAAmB,GAAG;CAGpD,IAAI,CAAC,QAAQ,KAAK,aAAa,KAAK;EAEnC,OAAO;GAAE,OAAO;GAAG,WADD,MAAM,OAAO;EACF;EAG7B,MAAM,aAAa,KAAK,KAAK,OAAO,WAAW,GAAI;EACnD,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,UAAU;CAC7C,OAAO;EAEN,KAAK;EAGL,MAAM,cAAc,KAAK,YAAY;EACrC,MAAM,aAAa,KAAK,KAAK,cAAc,GAAI;EAC/C,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,UAAU;CAC7C;CAGA,MAAM,OAAsB;EAC3B,OAAO,KAAK;EACZ,OAAO,OAAO;EACd,WAAW,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,KAAK;EAChD,WAAW,KAAK;EAChB,YAAY,KAAK,YAAY;CAC9B;CAGA,IAAI,KAAK,QAAQ,OAAO,OAAO;EAE9B,IAAI,OAAO,SACV,MAAM,OAAO,QAAQ,KAAK,IAAI;EAI/B,MAAM,oBAAoB,KAAK,KAAK,KAAK,aAAa,GAAI;EAC1D,MAAM,IAAI,qBACT,OAAO,WAAW,8CAClB,iBACD;CACD;CAEA,OAAO;AACR;;;;AAKA,SAAgB,oBACf,MACA,QACmB;CACnB,MAAM,UAA4B,CAAC;CAEnC,IAAI,OAAO,oBAAoB,OAAO;EACrC,QAAQ,uBAAuB,KAAK,MAAM,SAAS;EACnD,QAAQ,2BAA2B,KAAK,UAAU,SAAS;EAC3D,QAAQ,uBAAuB,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,YAAY;CACrE;CAEA,IAAI,OAAO,eAAe;EACzB,QAAQ,6BAA6B,KAAK,WAAW,SAAS;EAC9D,QAAQ,6BAA6B,KAAK,KACzC,KAAK,aAAa,GACnB,CAAC,CAAC,SAAS;CACZ;CAGA,IAAI,KAAK,cAAc,GACtB,QAAQ,iBAAiB,KAAK,KAAK,KAAK,aAAa,GAAI,CAAC,CAAC,SAAS;CAGrE,OAAO;AACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/rate-limit",
3
- "version": "10.0.0-alpha.6",
3
+ "version": "10.0.0-alpha.60",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -28,9 +28,9 @@
28
28
  },
29
29
  "dependencies": {},
30
30
  "peerDependencies": {
31
- "@geekmidas/cache": "^10.0.0-alpha.6",
32
- "@geekmidas/logger": "^10.0.0-alpha.6",
33
- "@geekmidas/services": "^10.0.0-alpha.6"
31
+ "@geekmidas/cache": "^10.0.0-alpha.60",
32
+ "@geekmidas/logger": "^10.0.0-alpha.60",
33
+ "@geekmidas/services": "^10.0.0-alpha.60"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@geekmidas/cache": {
@@ -44,9 +44,9 @@
44
44
  }
45
45
  },
46
46
  "devDependencies": {
47
- "@geekmidas/cache": "^10.0.0-alpha.6",
48
- "@geekmidas/logger": "^10.0.0-alpha.6",
49
- "@geekmidas/services": "^10.0.0-alpha.6"
47
+ "@geekmidas/cache": "^10.0.0-alpha.60",
48
+ "@geekmidas/logger": "^10.0.0-alpha.60",
49
+ "@geekmidas/services": "^10.0.0-alpha.60"
50
50
  },
51
51
  "scripts": {
52
52
  "ts": "tsc --noEmit --skipLibCheck src/**/*.ts"