nest-ratelimit-pro 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +359 -0
  3. package/dist/constants.d.ts +13 -0
  4. package/dist/constants.js +17 -0
  5. package/dist/constants.js.map +1 -0
  6. package/dist/decorators/rate-limit.decorator.d.ts +3 -0
  7. package/dist/decorators/rate-limit.decorator.js +14 -0
  8. package/dist/decorators/rate-limit.decorator.js.map +1 -0
  9. package/dist/exceptions/rate-limit.exception.d.ts +5 -0
  10. package/dist/exceptions/rate-limit.exception.js +17 -0
  11. package/dist/exceptions/rate-limit.exception.js.map +1 -0
  12. package/dist/guards/rate-limit.guard.d.ts +12 -0
  13. package/dist/guards/rate-limit.guard.js +75 -0
  14. package/dist/guards/rate-limit.guard.js.map +1 -0
  15. package/dist/index.d.ts +12 -0
  16. package/dist/index.js +29 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/interfaces/rate-limit-options.interface.d.ts +45 -0
  19. package/dist/interfaces/rate-limit-options.interface.js +19 -0
  20. package/dist/interfaces/rate-limit-options.interface.js.map +1 -0
  21. package/dist/interfaces/rate-limit.interface.d.ts +20 -0
  22. package/dist/interfaces/rate-limit.interface.js +3 -0
  23. package/dist/interfaces/rate-limit.interface.js.map +1 -0
  24. package/dist/interfaces/storage.interface.d.ts +12 -0
  25. package/dist/interfaces/storage.interface.js +3 -0
  26. package/dist/interfaces/storage.interface.js.map +1 -0
  27. package/dist/rate-limit.module.d.ts +8 -0
  28. package/dist/rate-limit.module.js +76 -0
  29. package/dist/rate-limit.module.js.map +1 -0
  30. package/dist/services/rate-limit.service.d.ts +18 -0
  31. package/dist/services/rate-limit.service.js +164 -0
  32. package/dist/services/rate-limit.service.js.map +1 -0
  33. package/dist/storage/memory.storage.d.ts +19 -0
  34. package/dist/storage/memory.storage.js +124 -0
  35. package/dist/storage/memory.storage.js.map +1 -0
  36. package/dist/utils/key.utils.d.ts +5 -0
  37. package/dist/utils/key.utils.js +47 -0
  38. package/dist/utils/key.utils.js.map +1 -0
  39. package/dist/utils/time-utils.d.ts +4 -0
  40. package/dist/utils/time-utils.js +30 -0
  41. package/dist/utils/time-utils.js.map +1 -0
  42. package/package.json +91 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/rate-limit-options.interface.ts"],"names":[],"mappings":";;;AAMA,IAAY,kBAoBX;AApBD,WAAY,kBAAkB;IAI5B,mDAA6B,CAAA;IAK7B,mDAA6B,CAAA;IAK7B,uDAAiC,CAAA;IAKjC,uEAAiD,CAAA;AACnD,CAAC,EApBW,kBAAkB,kCAAlB,kBAAkB,QAoB7B;AAKD,IAAY,oBAyBX;AAzBD,WAAY,oBAAoB;IAI9B,iCAAS,CAAA;IAKT,2CAAmB,CAAA;IAKnB,2CAAmB,CAAA;IAKnB,yCAAiB,CAAA;IAKjB,6CAAqB,CAAA;AACvB,CAAC,EAzBW,oBAAoB,oCAApB,oBAAoB,QAyB/B"}
@@ -0,0 +1,20 @@
1
+ export interface RateLimitResult {
2
+ allowed: boolean;
3
+ limit: number;
4
+ remaining: number;
5
+ resetAt: number;
6
+ retryAfter?: number;
7
+ cost?: number;
8
+ }
9
+ export interface RateLimitInfo {
10
+ key: string;
11
+ consumed: number;
12
+ limit: number;
13
+ windowStart: number;
14
+ windowDuration: number;
15
+ }
16
+ export interface RateLimitCheckOptions {
17
+ keySuffix?: string;
18
+ cost?: number;
19
+ skip?: boolean;
20
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=rate-limit.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.interface.js","sourceRoot":"","sources":["../../src/interfaces/rate-limit.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { RateLimitInfo } from './rate-limit.interface';
2
+ export interface RateLimitStorage {
3
+ increment(key: string, amount: number, ttl: number): Promise<number>;
4
+ get(key: string): Promise<number>;
5
+ getInfo(key: string): Promise<RateLimitInfo | null>;
6
+ reset(key: string): Promise<void>;
7
+ set(key: string, value: any, ttl: number): Promise<void>;
8
+ delete(key: string): Promise<void>;
9
+ exists(key: string): Promise<boolean>;
10
+ ttl(key: string): Promise<number>;
11
+ cleanup?(): Promise<void>;
12
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=storage.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.interface.js","sourceRoot":"","sources":["../../src/interfaces/storage.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { RateLimitModuleOptions, RateLimitModuleAsyncOptions } from './interfaces/rate-limit-options.interface';
3
+ export declare class RateLimitModule {
4
+ static forRoot(options: RateLimitModuleOptions): DynamicModule;
5
+ static forRootAsync(options: RateLimitModuleAsyncOptions): DynamicModule;
6
+ private static createProviders;
7
+ private static createAsyncProviders;
8
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var RateLimitModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.RateLimitModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const rate_limit_service_1 = require("./services/rate-limit.service");
13
+ const rate_limit_guard_1 = require("./guards/rate-limit.guard");
14
+ const memory_storage_1 = require("./storage/memory.storage");
15
+ const constants_1 = require("./constants");
16
+ let RateLimitModule = RateLimitModule_1 = class RateLimitModule {
17
+ static forRoot(options) {
18
+ const providers = this.createProviders(options);
19
+ return {
20
+ module: RateLimitModule_1,
21
+ providers,
22
+ exports: [rate_limit_service_1.RateLimitService, rate_limit_guard_1.RateLimitGuard],
23
+ global: true,
24
+ };
25
+ }
26
+ static forRootAsync(options) {
27
+ const providers = this.createAsyncProviders(options);
28
+ return {
29
+ module: RateLimitModule_1,
30
+ imports: options.imports || [],
31
+ providers,
32
+ exports: [rate_limit_service_1.RateLimitService, rate_limit_guard_1.RateLimitGuard],
33
+ global: true,
34
+ };
35
+ }
36
+ static createProviders(options) {
37
+ return [
38
+ {
39
+ provide: constants_1.RATE_LIMIT_OPTIONS,
40
+ useValue: options,
41
+ },
42
+ {
43
+ provide: constants_1.RATE_LIMIT_STORAGE,
44
+ useClass: options.storage || memory_storage_1.MemoryRateLimitStorage,
45
+ },
46
+ rate_limit_service_1.RateLimitService,
47
+ rate_limit_guard_1.RateLimitGuard,
48
+ ];
49
+ }
50
+ static createAsyncProviders(options) {
51
+ const optionsProvider = {
52
+ provide: constants_1.RATE_LIMIT_OPTIONS,
53
+ useFactory: options.useFactory,
54
+ inject: options.inject || [],
55
+ };
56
+ return [
57
+ optionsProvider,
58
+ {
59
+ provide: constants_1.RATE_LIMIT_STORAGE,
60
+ useFactory: (opts) => {
61
+ const StorageClass = opts.storage || memory_storage_1.MemoryRateLimitStorage;
62
+ return new StorageClass();
63
+ },
64
+ inject: [constants_1.RATE_LIMIT_OPTIONS],
65
+ },
66
+ rate_limit_service_1.RateLimitService,
67
+ rate_limit_guard_1.RateLimitGuard,
68
+ ];
69
+ }
70
+ };
71
+ exports.RateLimitModule = RateLimitModule;
72
+ exports.RateLimitModule = RateLimitModule = RateLimitModule_1 = __decorate([
73
+ (0, common_1.Global)(),
74
+ (0, common_1.Module)({})
75
+ ], RateLimitModule);
76
+ //# sourceMappingURL=rate-limit.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.module.js","sourceRoot":"","sources":["../src/rate-limit.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAyE;AAKzE,sEAAiE;AACjE,gEAA2D;AAC3D,6DAAkE;AAClE,2CAAqE;AAI9D,IAAM,eAAe,uBAArB,MAAM,eAAe;IAI1B,MAAM,CAAC,OAAO,CAAC,OAA+B;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAEhD,OAAO;YACL,MAAM,EAAE,iBAAe;YACvB,SAAS;YACT,OAAO,EAAE,CAAC,qCAAgB,EAAE,iCAAc,CAAC;YAC3C,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,YAAY,CAAC,OAAoC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAErD,OAAO;YACL,MAAM,EAAE,iBAAe;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,SAAS;YACT,OAAO,EAAE,CAAC,qCAAgB,EAAE,iCAAc,CAAC;YAC3C,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;IAKO,MAAM,CAAC,eAAe,CAAC,OAA+B;QAC5D,OAAO;YACL;gBACE,OAAO,EAAE,8BAAkB;gBAC3B,QAAQ,EAAE,OAAO;aAClB;YACD;gBACE,OAAO,EAAE,8BAAkB;gBAC3B,QAAQ,EAAE,OAAO,CAAC,OAAO,IAAI,uCAAsB;aACpD;YACD,qCAAgB;YAChB,iCAAc;SACf,CAAC;IACJ,CAAC;IAKO,MAAM,CAAC,oBAAoB,CAAC,OAAoC;QACtE,MAAM,eAAe,GAAa;YAChC,OAAO,EAAE,8BAAkB;YAC3B,UAAU,EAAE,OAAO,CAAC,UAAW;YAC/B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;SAC7B,CAAC;QAEF,OAAO;YACL,eAAe;YACf;gBACE,OAAO,EAAE,8BAAkB;gBAC3B,UAAU,EAAE,CAAC,IAA4B,EAAE,EAAE;oBAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,IAAI,uCAAsB,CAAC;oBAC5D,OAAO,IAAI,YAAY,EAAE,CAAC;gBAC5B,CAAC;gBACD,MAAM,EAAE,CAAC,8BAAkB,CAAC;aAC7B;YACD,qCAAgB;YAChB,iCAAc;SACf,CAAC;IACJ,CAAC;CACF,CAAA;AAxEY,0CAAe;0BAAf,eAAe;IAF3B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,eAAe,CAwE3B"}
@@ -0,0 +1,18 @@
1
+ import { Request } from 'express';
2
+ import { RateLimitStorage } from '../interfaces/storage.interface';
3
+ import { RateLimitModuleOptions } from '../interfaces/rate-limit-options.interface';
4
+ import { RateLimitResult, RateLimitCheckOptions } from '../interfaces/rate-limit.interface';
5
+ export declare class RateLimitService {
6
+ private readonly options;
7
+ private readonly storage;
8
+ private readonly windowDurationMs;
9
+ private readonly windowDurationSec;
10
+ constructor(options: RateLimitModuleOptions, storage: RateLimitStorage);
11
+ check(request: Request, checkOptions?: RateLimitCheckOptions): Promise<RateLimitResult>;
12
+ private checkFixedWindow;
13
+ private checkSlidingWindow;
14
+ private checkTokenBucket;
15
+ private generateKey;
16
+ private createAllowedResult;
17
+ reset(identifier: string): Promise<void>;
18
+ }
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.RateLimitService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const rate_limit_options_interface_1 = require("../interfaces/rate-limit-options.interface");
18
+ const constants_1 = require("../constants");
19
+ const time_utils_1 = require("../utils/time-utils");
20
+ const key_utils_1 = require("../utils/key.utils");
21
+ let RateLimitService = class RateLimitService {
22
+ constructor(options, storage) {
23
+ this.options = options;
24
+ this.storage = storage;
25
+ this.windowDurationMs = (0, time_utils_1.parseDuration)(options.duration);
26
+ this.windowDurationSec = (0, time_utils_1.msToSeconds)(this.windowDurationMs);
27
+ }
28
+ async check(request, checkOptions) {
29
+ if (this.options.enabled === false) {
30
+ return this.createAllowedResult(this.options.limit);
31
+ }
32
+ if (checkOptions?.skip) {
33
+ return this.createAllowedResult(this.options.limit);
34
+ }
35
+ if (this.options.skipIf && (await this.options.skipIf(request))) {
36
+ return this.createAllowedResult(this.options.limit);
37
+ }
38
+ const key = await this.generateKey(request, checkOptions?.keySuffix);
39
+ const cost = checkOptions?.cost || 1;
40
+ switch (this.options.algorithm) {
41
+ case rate_limit_options_interface_1.RateLimitAlgorithm.SLIDING_WINDOW:
42
+ return this.checkSlidingWindow(key, cost);
43
+ case rate_limit_options_interface_1.RateLimitAlgorithm.TOKEN_BUCKET:
44
+ return this.checkTokenBucket(key, cost);
45
+ default:
46
+ return this.checkFixedWindow(key, cost);
47
+ }
48
+ }
49
+ async checkFixedWindow(key, cost) {
50
+ const count = await this.storage.increment(key, cost, this.windowDurationSec);
51
+ const allowed = count <= this.options.limit;
52
+ const remaining = Math.max(0, this.options.limit - count);
53
+ const resetAt = (0, time_utils_1.calculateResetTime)(this.windowDurationMs);
54
+ return {
55
+ allowed,
56
+ limit: this.options.limit,
57
+ remaining,
58
+ resetAt,
59
+ retryAfter: allowed ? undefined : this.windowDurationSec,
60
+ cost,
61
+ };
62
+ }
63
+ async checkSlidingWindow(key, cost) {
64
+ const now = Date.now();
65
+ const windowStart = now - this.windowDurationMs;
66
+ const currentKey = `${key}:${Math.floor(now / this.windowDurationMs)}`;
67
+ const previousKey = `${key}:${Math.floor(windowStart / this.windowDurationMs)}`;
68
+ const currentCount = await this.storage.get(currentKey);
69
+ const previousCount = await this.storage.get(previousKey);
70
+ const previousWeight = (this.windowDurationMs - (now % this.windowDurationMs)) / this.windowDurationMs;
71
+ const weightedCount = previousCount * previousWeight + currentCount;
72
+ if (weightedCount + cost <= this.options.limit) {
73
+ await this.storage.increment(currentKey, cost, this.windowDurationSec);
74
+ return {
75
+ allowed: true,
76
+ limit: this.options.limit,
77
+ remaining: Math.max(0, this.options.limit - weightedCount - cost),
78
+ resetAt: (0, time_utils_1.calculateResetTime)(this.windowDurationMs),
79
+ cost,
80
+ };
81
+ }
82
+ return {
83
+ allowed: false,
84
+ limit: this.options.limit,
85
+ remaining: 0,
86
+ resetAt: (0, time_utils_1.calculateResetTime)(this.windowDurationMs),
87
+ retryAfter: this.windowDurationSec,
88
+ cost,
89
+ };
90
+ }
91
+ async checkTokenBucket(key, cost) {
92
+ const tokenKey = `${key}:tokens`;
93
+ const lastUpdateKey = `${key}:lastUpdate`;
94
+ const now = Date.now();
95
+ const tokens = (await this.storage.get(tokenKey)) || this.options.limit;
96
+ const lastUpdate = (await this.storage.get(lastUpdateKey)) || now;
97
+ const timePassed = now - lastUpdate;
98
+ const tokensToAdd = (timePassed / this.windowDurationMs) * this.options.limit;
99
+ const currentTokens = Math.min(this.options.limit, tokens + tokensToAdd);
100
+ if (currentTokens >= cost) {
101
+ const newTokens = currentTokens - cost;
102
+ await this.storage.set(tokenKey, newTokens, this.windowDurationSec);
103
+ await this.storage.set(lastUpdateKey, now, this.windowDurationSec);
104
+ return {
105
+ allowed: true,
106
+ limit: this.options.limit,
107
+ remaining: Math.floor(newTokens),
108
+ resetAt: (0, time_utils_1.calculateResetTime)(this.windowDurationMs),
109
+ cost,
110
+ };
111
+ }
112
+ return {
113
+ allowed: false,
114
+ limit: this.options.limit,
115
+ remaining: 0,
116
+ resetAt: (0, time_utils_1.calculateResetTime)(this.windowDurationMs),
117
+ retryAfter: Math.ceil((cost - currentTokens) / this.options.limit * this.windowDurationSec),
118
+ cost,
119
+ };
120
+ }
121
+ async generateKey(request, suffix) {
122
+ const prefix = this.options.keyPrefix || constants_1.DEFAULT_KEY_PREFIX;
123
+ let identifier;
124
+ if (this.options.keyExtractor) {
125
+ identifier = await this.options.keyExtractor(request);
126
+ }
127
+ else {
128
+ switch (this.options.keyStrategy) {
129
+ case rate_limit_options_interface_1.RateLimitKeyStrategy.USER_ID:
130
+ identifier = (0, key_utils_1.extractUserId)(request);
131
+ break;
132
+ case rate_limit_options_interface_1.RateLimitKeyStrategy.API_KEY:
133
+ identifier = (0, key_utils_1.extractApiKey)(request, this.options.apiKeyHeader);
134
+ break;
135
+ case rate_limit_options_interface_1.RateLimitKeyStrategy.IP:
136
+ default:
137
+ identifier = (0, key_utils_1.extractIpAddress)(request);
138
+ break;
139
+ }
140
+ }
141
+ return (0, key_utils_1.buildRateLimitKey)(prefix, identifier, suffix);
142
+ }
143
+ createAllowedResult(limit) {
144
+ return {
145
+ allowed: true,
146
+ limit,
147
+ remaining: limit,
148
+ resetAt: (0, time_utils_1.getCurrentTimestamp)() + this.windowDurationSec,
149
+ };
150
+ }
151
+ async reset(identifier) {
152
+ const prefix = this.options.keyPrefix || constants_1.DEFAULT_KEY_PREFIX;
153
+ const key = (0, key_utils_1.buildRateLimitKey)(prefix, identifier);
154
+ await this.storage.reset(key);
155
+ }
156
+ };
157
+ exports.RateLimitService = RateLimitService;
158
+ exports.RateLimitService = RateLimitService = __decorate([
159
+ (0, common_1.Injectable)(),
160
+ __param(0, (0, common_1.Inject)(constants_1.RATE_LIMIT_OPTIONS)),
161
+ __param(1, (0, common_1.Inject)(constants_1.RATE_LIMIT_STORAGE)),
162
+ __metadata("design:paramtypes", [Object, Object])
163
+ ], RateLimitService);
164
+ //# sourceMappingURL=rate-limit.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.service.js","sourceRoot":"","sources":["../../src/services/rate-limit.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { RateLimitStorage } from '../interfaces/storage.interface';
2
+ import { RateLimitInfo } from '../interfaces/rate-limit.interface';
3
+ export declare class MemoryRateLimitStorage implements RateLimitStorage {
4
+ private storage;
5
+ private cleanupInterval;
6
+ constructor();
7
+ increment(key: string, amount: number | undefined, ttl: number): Promise<number>;
8
+ get(key: string): Promise<number>;
9
+ getInfo(key: string): Promise<RateLimitInfo | null>;
10
+ reset(key: string): Promise<void>;
11
+ set(key: string, value: any, ttl: number): Promise<void>;
12
+ delete(key: string): Promise<void>;
13
+ exists(key: string): Promise<boolean>;
14
+ ttl(key: string): Promise<number>;
15
+ cleanup(): Promise<void>;
16
+ clear(): void;
17
+ size(): number;
18
+ onModuleDestroy(): void;
19
+ }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MemoryRateLimitStorage = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ let MemoryRateLimitStorage = class MemoryRateLimitStorage {
15
+ constructor() {
16
+ this.storage = new Map();
17
+ this.cleanupInterval = setInterval(() => {
18
+ this.cleanup();
19
+ }, 60000);
20
+ }
21
+ async increment(key, amount = 1, ttl) {
22
+ const now = Date.now();
23
+ const expiresAt = now + ttl * 1000;
24
+ const entry = this.storage.get(key);
25
+ if (!entry || entry.expiresAt < now) {
26
+ this.storage.set(key, {
27
+ value: amount,
28
+ expiresAt,
29
+ });
30
+ return amount;
31
+ }
32
+ entry.value += amount;
33
+ entry.expiresAt = expiresAt;
34
+ return entry.value;
35
+ }
36
+ async get(key) {
37
+ const entry = this.storage.get(key);
38
+ if (!entry) {
39
+ return 0;
40
+ }
41
+ if (entry.expiresAt < Date.now()) {
42
+ this.storage.delete(key);
43
+ return 0;
44
+ }
45
+ return entry.value;
46
+ }
47
+ async getInfo(key) {
48
+ const entry = this.storage.get(key);
49
+ if (!entry || entry.expiresAt < Date.now()) {
50
+ return null;
51
+ }
52
+ return {
53
+ key,
54
+ consumed: entry.value,
55
+ limit: 0,
56
+ windowStart: Date.now(),
57
+ windowDuration: entry.expiresAt - Date.now(),
58
+ };
59
+ }
60
+ async reset(key) {
61
+ this.storage.delete(key);
62
+ }
63
+ async set(key, value, ttl) {
64
+ this.storage.set(key, {
65
+ value,
66
+ expiresAt: Date.now() + ttl * 1000,
67
+ });
68
+ }
69
+ async delete(key) {
70
+ this.storage.delete(key);
71
+ }
72
+ async exists(key) {
73
+ const entry = this.storage.get(key);
74
+ if (!entry) {
75
+ return false;
76
+ }
77
+ if (entry.expiresAt < Date.now()) {
78
+ this.storage.delete(key);
79
+ return false;
80
+ }
81
+ return true;
82
+ }
83
+ async ttl(key) {
84
+ const entry = this.storage.get(key);
85
+ if (!entry) {
86
+ return -2;
87
+ }
88
+ const remaining = Math.floor((entry.expiresAt - Date.now()) / 1000);
89
+ if (remaining <= 0) {
90
+ this.storage.delete(key);
91
+ return -2;
92
+ }
93
+ return remaining;
94
+ }
95
+ async cleanup() {
96
+ const now = Date.now();
97
+ const expiredKeys = [];
98
+ for (const [key, entry] of this.storage.entries()) {
99
+ if (entry.expiresAt < now) {
100
+ expiredKeys.push(key);
101
+ }
102
+ }
103
+ for (const key of expiredKeys) {
104
+ this.storage.delete(key);
105
+ }
106
+ }
107
+ clear() {
108
+ this.storage.clear();
109
+ }
110
+ size() {
111
+ return this.storage.size;
112
+ }
113
+ onModuleDestroy() {
114
+ if (this.cleanupInterval) {
115
+ clearInterval(this.cleanupInterval);
116
+ }
117
+ }
118
+ };
119
+ exports.MemoryRateLimitStorage = MemoryRateLimitStorage;
120
+ exports.MemoryRateLimitStorage = MemoryRateLimitStorage = __decorate([
121
+ (0, common_1.Injectable)(),
122
+ __metadata("design:paramtypes", [])
123
+ ], MemoryRateLimitStorage);
124
+ //# sourceMappingURL=memory.storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.storage.js","sourceRoot":"","sources":["../../src/storage/memory.storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Request } from 'express';
2
+ export declare function extractIpAddress(request: Request): string;
3
+ export declare function extractUserId(request: any): string;
4
+ export declare function extractApiKey(request: Request, headerName?: string): string;
5
+ export declare function buildRateLimitKey(prefix: string, identifier: string, suffix?: string): string;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractIpAddress = extractIpAddress;
4
+ exports.extractUserId = extractUserId;
5
+ exports.extractApiKey = extractApiKey;
6
+ exports.buildRateLimitKey = buildRateLimitKey;
7
+ function extractIpAddress(request) {
8
+ const forwardedFor = request.headers['x-forwarded-for'];
9
+ if (forwardedFor) {
10
+ const ips = typeof forwardedFor === 'string'
11
+ ? forwardedFor.split(',')
12
+ : forwardedFor;
13
+ return ips[0].trim();
14
+ }
15
+ const realIp = request.headers['x-real-ip'];
16
+ if (realIp) {
17
+ return typeof realIp === 'string' ? realIp : realIp[0];
18
+ }
19
+ return request.ip || request.socket?.remoteAddress || 'unknown';
20
+ }
21
+ function extractUserId(request) {
22
+ if (request.user?.id) {
23
+ return String(request.user.id);
24
+ }
25
+ if (request.user?.sub) {
26
+ return String(request.user.sub);
27
+ }
28
+ if (request.userId) {
29
+ return String(request.userId);
30
+ }
31
+ return 'anonymous';
32
+ }
33
+ function extractApiKey(request, headerName = 'X-API-Key') {
34
+ const apiKey = request.headers[headerName.toLowerCase()];
35
+ if (apiKey) {
36
+ return typeof apiKey === 'string' ? apiKey : apiKey[0];
37
+ }
38
+ return 'unknown';
39
+ }
40
+ function buildRateLimitKey(prefix, identifier, suffix) {
41
+ const parts = [prefix, identifier];
42
+ if (suffix) {
43
+ parts.push(suffix);
44
+ }
45
+ return parts.join(':');
46
+ }
47
+ //# sourceMappingURL=key.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key.utils.js","sourceRoot":"","sources":["../../src/utils/key.utils.ts"],"names":[],"mappings":";;AAOA,4CAmBC;AAOD,sCAeC;AAQD,sCAQC;AASD,8CAQC;AA1ED,SAAgB,gBAAgB,CAAC,OAAgB;IAE/C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,OAAO,YAAY,KAAK,QAAQ;YAC1C,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC;YACzB,CAAC,CAAC,YAAY,CAAC;QACjB,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAGD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IAGD,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,aAAa,IAAI,SAAS,CAAC;AAClE,CAAC;AAOD,SAAgB,aAAa,CAAC,OAAY;IAExC,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;QACrB,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAQD,SAAgB,aAAa,CAAC,OAAgB,EAAE,aAAqB,WAAW;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAEzD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AASD,SAAgB,iBAAiB,CAAC,MAAc,EAAE,UAAkB,EAAE,MAAe;IACnF,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEnC,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parseDuration(duration: string | number): number;
2
+ export declare function msToSeconds(milliseconds: number): number;
3
+ export declare function getCurrentTimestamp(): number;
4
+ export declare function calculateResetTime(windowDuration: number): number;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseDuration = parseDuration;
7
+ exports.msToSeconds = msToSeconds;
8
+ exports.getCurrentTimestamp = getCurrentTimestamp;
9
+ exports.calculateResetTime = calculateResetTime;
10
+ const ms_1 = __importDefault(require("ms"));
11
+ function parseDuration(duration) {
12
+ if (typeof duration === 'number') {
13
+ return duration;
14
+ }
15
+ const milliseconds = (0, ms_1.default)(duration);
16
+ if (milliseconds === undefined) {
17
+ throw new Error(`Invalid duration format: ${duration}`);
18
+ }
19
+ return milliseconds;
20
+ }
21
+ function msToSeconds(milliseconds) {
22
+ return Math.floor(milliseconds / 1000);
23
+ }
24
+ function getCurrentTimestamp() {
25
+ return Math.floor(Date.now() / 1000);
26
+ }
27
+ function calculateResetTime(windowDuration) {
28
+ return getCurrentTimestamp() + msToSeconds(windowDuration);
29
+ }
30
+ //# sourceMappingURL=time-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-utils.js","sourceRoot":"","sources":["../../src/utils/time-utils.ts"],"names":[],"mappings":";;;;;AAOA,sCAYC;AAOD,kCAEC;AAMD,kDAEC;AAOD,gDAEC;AA7CD,4CAAoB;AAOpB,SAAgB,aAAa,CAAC,QAAyB;IACrD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,YAAY,GAAG,IAAA,YAAE,EAAC,QAAQ,CAAC,CAAC;IAElC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAOD,SAAgB,WAAW,CAAC,YAAoB;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;AACzC,CAAC;AAMD,SAAgB,mBAAmB;IACjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC;AAOD,SAAgB,kBAAkB,CAAC,cAAsB;IACvD,OAAO,mBAAmB,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;AAC7D,CAAC"}