nestjs-shield 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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +361 -0
  3. package/dist/algorithms/fixed-window.d.ts +4 -0
  4. package/dist/algorithms/fixed-window.js +9 -0
  5. package/dist/algorithms/leaky-bucket.d.ts +4 -0
  6. package/dist/algorithms/leaky-bucket.js +10 -0
  7. package/dist/algorithms/sliding-window-counter.d.ts +4 -0
  8. package/dist/algorithms/sliding-window-counter.js +9 -0
  9. package/dist/algorithms/sliding-window-log.d.ts +4 -0
  10. package/dist/algorithms/sliding-window-log.js +9 -0
  11. package/dist/algorithms/token-bucket.d.ts +4 -0
  12. package/dist/algorithms/token-bucket.js +10 -0
  13. package/dist/apply-to.d.ts +8 -0
  14. package/dist/apply-to.js +42 -0
  15. package/dist/checks/auto-ban.check.d.ts +6 -0
  16. package/dist/checks/auto-ban.check.js +43 -0
  17. package/dist/checks/blacklist.check.d.ts +4 -0
  18. package/dist/checks/blacklist.check.js +20 -0
  19. package/dist/checks/burst.check.d.ts +5 -0
  20. package/dist/checks/burst.check.js +28 -0
  21. package/dist/checks/payload.check.d.ts +5 -0
  22. package/dist/checks/payload.check.js +46 -0
  23. package/dist/checks/rate-limit.check.d.ts +9 -0
  24. package/dist/checks/rate-limit.check.js +59 -0
  25. package/dist/checks/slow-down.check.d.ts +5 -0
  26. package/dist/checks/slow-down.check.js +19 -0
  27. package/dist/checks/user-agent.check.d.ts +4 -0
  28. package/dist/checks/user-agent.check.js +31 -0
  29. package/dist/checks/whitelist.check.d.ts +4 -0
  30. package/dist/checks/whitelist.check.js +15 -0
  31. package/dist/decorators/blacklist.decorator.d.ts +2 -0
  32. package/dist/decorators/blacklist.decorator.js +7 -0
  33. package/dist/decorators/burst-limit.decorator.d.ts +2 -0
  34. package/dist/decorators/burst-limit.decorator.js +7 -0
  35. package/dist/decorators/max-payload.decorator.d.ts +2 -0
  36. package/dist/decorators/max-payload.decorator.js +7 -0
  37. package/dist/decorators/rate-limit.decorator.d.ts +2 -0
  38. package/dist/decorators/rate-limit.decorator.js +7 -0
  39. package/dist/decorators/skip-shield.decorator.d.ts +2 -0
  40. package/dist/decorators/skip-shield.decorator.js +7 -0
  41. package/dist/decorators/slow-down.decorator.d.ts +2 -0
  42. package/dist/decorators/slow-down.decorator.js +7 -0
  43. package/dist/decorators/user-agent-policy.decorator.d.ts +2 -0
  44. package/dist/decorators/user-agent-policy.decorator.js +7 -0
  45. package/dist/decorators/whitelist.decorator.d.ts +2 -0
  46. package/dist/decorators/whitelist.decorator.js +7 -0
  47. package/dist/exceptions/shield.exceptions.d.ts +23 -0
  48. package/dist/exceptions/shield.exceptions.js +40 -0
  49. package/dist/index.d.ts +32 -0
  50. package/dist/index.js +58 -0
  51. package/dist/shield.constants.d.ts +22 -0
  52. package/dist/shield.constants.js +33 -0
  53. package/dist/shield.engine.d.ts +21 -0
  54. package/dist/shield.engine.js +215 -0
  55. package/dist/shield.guard.d.ts +10 -0
  56. package/dist/shield.guard.js +89 -0
  57. package/dist/shield.middleware.d.ts +5 -0
  58. package/dist/shield.middleware.js +47 -0
  59. package/dist/shield.module.d.ts +14 -0
  60. package/dist/shield.module.js +105 -0
  61. package/dist/shield.types.d.ts +141 -0
  62. package/dist/shield.types.js +2 -0
  63. package/dist/storage/memory.storage.d.ts +30 -0
  64. package/dist/storage/memory.storage.js +201 -0
  65. package/dist/storage/redis.storage.d.ts +44 -0
  66. package/dist/storage/redis.storage.js +258 -0
  67. package/dist/storage/shield-storage.interface.d.ts +30 -0
  68. package/dist/storage/shield-storage.interface.js +2 -0
  69. package/dist/utils/headers.util.d.ts +5 -0
  70. package/dist/utils/headers.util.js +23 -0
  71. package/dist/utils/ip.util.d.ts +6 -0
  72. package/dist/utils/ip.util.js +100 -0
  73. package/dist/utils/key.util.d.ts +5 -0
  74. package/dist/utils/key.util.js +24 -0
  75. package/dist/utils/ua.util.d.ts +4 -0
  76. package/dist/utils/ua.util.js +26 -0
  77. package/package.json +77 -0
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PayloadCheck = void 0;
4
+ class PayloadCheck {
5
+ static run(req, config) {
6
+ if (!config)
7
+ return { allowed: true };
8
+ if (config.maxHeaderBytes !== undefined) {
9
+ const size = PayloadCheck.estimateHeaderBytes(req.headers);
10
+ if (size > config.maxHeaderBytes) {
11
+ return {
12
+ allowed: false,
13
+ layer: 'payload',
14
+ status: 431,
15
+ reason: `Header size ${size} exceeds limit ${config.maxHeaderBytes}`,
16
+ };
17
+ }
18
+ }
19
+ if (config.maxBodyBytes !== undefined) {
20
+ const cl = req.headers['content-length'];
21
+ if (cl !== undefined) {
22
+ const declared = Number(Array.isArray(cl) ? cl[0] : cl);
23
+ if (Number.isFinite(declared) && declared > config.maxBodyBytes) {
24
+ return {
25
+ allowed: false,
26
+ layer: 'payload',
27
+ status: 413,
28
+ reason: `Payload size ${declared} exceeds limit ${config.maxBodyBytes}`,
29
+ };
30
+ }
31
+ }
32
+ }
33
+ return { allowed: true };
34
+ }
35
+ static estimateHeaderBytes(headers) {
36
+ let total = 0;
37
+ for (const [k, v] of Object.entries(headers)) {
38
+ if (v === undefined)
39
+ continue;
40
+ const value = Array.isArray(v) ? v.join(',') : String(v);
41
+ total += k.length + value.length + 4;
42
+ }
43
+ return total;
44
+ }
45
+ }
46
+ exports.PayloadCheck = PayloadCheck;
@@ -0,0 +1,9 @@
1
+ import type { ShieldStorage } from '../storage/shield-storage.interface';
2
+ import type { AnyRequest, CheckOutcome, RateLimitConfig } from '../shield.types';
3
+ export declare class RateLimitCheck {
4
+ static check(storage: ShieldStorage, req: AnyRequest, ip: string, config: RateLimitConfig): Promise<CheckOutcome & {
5
+ limit: number;
6
+ remaining: number;
7
+ resetMs: number;
8
+ }>;
9
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RateLimitCheck = void 0;
4
+ const fixed_window_1 = require("../algorithms/fixed-window");
5
+ const leaky_bucket_1 = require("../algorithms/leaky-bucket");
6
+ const sliding_window_counter_1 = require("../algorithms/sliding-window-counter");
7
+ const sliding_window_log_1 = require("../algorithms/sliding-window-log");
8
+ const token_bucket_1 = require("../algorithms/token-bucket");
9
+ const shield_constants_1 = require("../shield.constants");
10
+ const key_util_1 = require("../utils/key.util");
11
+ class RateLimitCheck {
12
+ static async check(storage, req, ip, config) {
13
+ if (config.skip && config.skip(req)) {
14
+ return {
15
+ allowed: true,
16
+ limit: config.limit,
17
+ remaining: config.limit,
18
+ resetMs: 0,
19
+ };
20
+ }
21
+ const tracker = key_util_1.KeyUtil.fromRequest(req, ip, config.keyBy);
22
+ const algo = config.algorithm ?? 'token-bucket';
23
+ const key = `${shield_constants_1.KEY_RATE_LIMIT}:${algo}:${tracker}`;
24
+ let result;
25
+ switch (algo) {
26
+ case 'token-bucket':
27
+ result = await token_bucket_1.TokenBucket.check(storage, key, config.limit, config.ttl);
28
+ break;
29
+ case 'sliding-window':
30
+ result = await sliding_window_counter_1.SlidingWindowCounter.check(storage, key, config.limit, config.ttl);
31
+ break;
32
+ case 'sliding-window-log':
33
+ result = await sliding_window_log_1.SlidingWindowLog.check(storage, key, config.limit, config.ttl);
34
+ break;
35
+ case 'fixed-window':
36
+ result = await fixed_window_1.FixedWindow.check(storage, key, config.limit, config.ttl);
37
+ break;
38
+ case 'leaky-bucket':
39
+ result = await leaky_bucket_1.LeakyBucket.check(storage, key, config.limit, config.ttl);
40
+ break;
41
+ default:
42
+ result = await token_bucket_1.TokenBucket.check(storage, key, config.limit, config.ttl);
43
+ }
44
+ const remaining = 'remaining' in result && result.remaining !== undefined
45
+ ? result.remaining
46
+ : Math.max(0, config.limit - (result.count ?? 0));
47
+ return {
48
+ allowed: result.allowed,
49
+ layer: 'rate-limit',
50
+ status: result.allowed ? undefined : 429,
51
+ reason: result.allowed ? undefined : 'Rate limit exceeded',
52
+ retryAfterMs: result.allowed ? undefined : result.resetMs,
53
+ limit: config.limit,
54
+ remaining,
55
+ resetMs: result.resetMs,
56
+ };
57
+ }
58
+ }
59
+ exports.RateLimitCheck = RateLimitCheck;
@@ -0,0 +1,5 @@
1
+ import type { ShieldStorage } from '../storage/shield-storage.interface';
2
+ import type { CheckOutcome, SlowDownConfig } from '../shield.types';
3
+ export declare class SlowDownCheck {
4
+ static check(storage: ShieldStorage, ip: string, ttlMs: number, config?: SlowDownConfig): Promise<CheckOutcome>;
5
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlowDownCheck = void 0;
4
+ const shield_constants_1 = require("../shield.constants");
5
+ class SlowDownCheck {
6
+ static async check(storage, ip, ttlMs, config) {
7
+ if (!config)
8
+ return { allowed: true };
9
+ const key = `${shield_constants_1.KEY_SLOW_DOWN}:${ip}`;
10
+ const { count } = await storage.increment(key, ttlMs);
11
+ if (count <= config.delayAfter)
12
+ return { allowed: true };
13
+ const overflow = count - config.delayAfter;
14
+ const computed = typeof config.delayMs === 'function' ? config.delayMs(overflow) : config.delayMs * overflow;
15
+ const delay = config.maxDelayMs ? Math.min(config.maxDelayMs, computed) : computed;
16
+ return { allowed: true, layer: 'slow-down', delayMs: Math.max(0, delay) };
17
+ }
18
+ }
19
+ exports.SlowDownCheck = SlowDownCheck;
@@ -0,0 +1,4 @@
1
+ import type { CheckOutcome, UserAgentConfig } from '../shield.types';
2
+ export declare class UserAgentCheck {
3
+ static run(ua: string, config?: UserAgentConfig): CheckOutcome;
4
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserAgentCheck = void 0;
4
+ const ua_util_1 = require("../utils/ua.util");
5
+ class UserAgentCheck {
6
+ static run(ua, config) {
7
+ if (!config)
8
+ return { allowed: true };
9
+ if (config.requirePresent && !ua) {
10
+ return {
11
+ allowed: false,
12
+ layer: 'user-agent',
13
+ status: 403,
14
+ reason: 'User-Agent header required',
15
+ };
16
+ }
17
+ if (config.allow && config.allow.length > 0 && ua_util_1.UaUtil.match(ua, config.allow)) {
18
+ return { allowed: true };
19
+ }
20
+ if (config.block && config.block.length > 0 && ua_util_1.UaUtil.match(ua, config.block)) {
21
+ return {
22
+ allowed: false,
23
+ layer: 'user-agent',
24
+ status: 403,
25
+ reason: 'User-Agent is blocked',
26
+ };
27
+ }
28
+ return { allowed: true };
29
+ }
30
+ }
31
+ exports.UserAgentCheck = UserAgentCheck;
@@ -0,0 +1,4 @@
1
+ import type { IpListConfig, CheckOutcome } from '../shield.types';
2
+ export declare class WhitelistCheck {
3
+ static run(ip: string, config?: IpListConfig): CheckOutcome;
4
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WhitelistCheck = void 0;
4
+ const ip_util_1 = require("../utils/ip.util");
5
+ class WhitelistCheck {
6
+ static run(ip, config) {
7
+ if (!config)
8
+ return { allowed: false };
9
+ const hit = ip_util_1.IpUtil.matches(ip, config.ips, config.cidrs);
10
+ if (hit)
11
+ return { allowed: true, layer: 'whitelist' };
12
+ return { allowed: false };
13
+ }
14
+ }
15
+ exports.WhitelistCheck = WhitelistCheck;
@@ -0,0 +1,2 @@
1
+ import type { IpListConfig } from '../shield.types';
2
+ export declare const Blacklist: (config: IpListConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Blacklist = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const Blacklist = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_BLACKLIST, config);
7
+ exports.Blacklist = Blacklist;
@@ -0,0 +1,2 @@
1
+ import type { BurstConfig } from '../shield.types';
2
+ export declare const BurstLimit: (config: BurstConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BurstLimit = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const BurstLimit = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_BURST, config);
7
+ exports.BurstLimit = BurstLimit;
@@ -0,0 +1,2 @@
1
+ import type { PayloadConfig } from '../shield.types';
2
+ export declare const MaxPayload: (config: PayloadConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MaxPayload = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const MaxPayload = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_MAX_PAYLOAD, config);
7
+ exports.MaxPayload = MaxPayload;
@@ -0,0 +1,2 @@
1
+ import type { RateLimitConfig } from '../shield.types';
2
+ export declare const RateLimit: (options: RateLimitConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RateLimit = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const RateLimit = (options) => (0, common_1.SetMetadata)(shield_constants_1.META_RATE_LIMIT, options);
7
+ exports.RateLimit = RateLimit;
@@ -0,0 +1,2 @@
1
+ import type { ShieldLayer } from '../shield.constants';
2
+ export declare const SkipShield: (...layers: ShieldLayer[]) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SkipShield = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const SkipShield = (...layers) => (0, common_1.SetMetadata)(shield_constants_1.META_SKIP, layers.length === 0 ? true : layers);
7
+ exports.SkipShield = SkipShield;
@@ -0,0 +1,2 @@
1
+ import type { SlowDownConfig } from '../shield.types';
2
+ export declare const SlowDown: (config: SlowDownConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlowDown = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const SlowDown = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_SLOW_DOWN, config);
7
+ exports.SlowDown = SlowDown;
@@ -0,0 +1,2 @@
1
+ import type { UserAgentConfig } from '../shield.types';
2
+ export declare const UserAgentPolicy: (config: UserAgentConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserAgentPolicy = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const UserAgentPolicy = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_UA, config);
7
+ exports.UserAgentPolicy = UserAgentPolicy;
@@ -0,0 +1,2 @@
1
+ import type { IpListConfig } from '../shield.types';
2
+ export declare const Whitelist: (config: IpListConfig) => import("@nestjs/common").CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Whitelist = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const shield_constants_1 = require("../shield.constants");
6
+ const Whitelist = (config) => (0, common_1.SetMetadata)(shield_constants_1.META_WHITELIST, config);
7
+ exports.Whitelist = Whitelist;
@@ -0,0 +1,23 @@
1
+ import { HttpException } from '@nestjs/common';
2
+ export interface ShieldExceptionPayload {
3
+ message: string;
4
+ code: string;
5
+ layer: string;
6
+ retryAfter?: number;
7
+ }
8
+ export declare class ShieldRateLimitException extends HttpException {
9
+ constructor(payload: Omit<ShieldExceptionPayload, 'code'> & {
10
+ code?: string;
11
+ });
12
+ }
13
+ export declare class ShieldBlockedException extends HttpException {
14
+ constructor(payload: Omit<ShieldExceptionPayload, 'code'> & {
15
+ code?: string;
16
+ status?: number;
17
+ });
18
+ }
19
+ export declare class ShieldPayloadException extends HttpException {
20
+ constructor(payload: Omit<ShieldExceptionPayload, 'code'> & {
21
+ code?: string;
22
+ });
23
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ShieldPayloadException = exports.ShieldBlockedException = exports.ShieldRateLimitException = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ class ShieldRateLimitException extends common_1.HttpException {
6
+ constructor(payload) {
7
+ super({
8
+ statusCode: common_1.HttpStatus.TOO_MANY_REQUESTS,
9
+ code: payload.code ?? 'SHIELD_RATE_LIMITED',
10
+ message: payload.message,
11
+ layer: payload.layer,
12
+ retryAfter: payload.retryAfter,
13
+ }, common_1.HttpStatus.TOO_MANY_REQUESTS);
14
+ }
15
+ }
16
+ exports.ShieldRateLimitException = ShieldRateLimitException;
17
+ class ShieldBlockedException extends common_1.HttpException {
18
+ constructor(payload) {
19
+ const status = payload.status ?? common_1.HttpStatus.FORBIDDEN;
20
+ super({
21
+ statusCode: status,
22
+ code: payload.code ?? 'SHIELD_BLOCKED',
23
+ message: payload.message,
24
+ layer: payload.layer,
25
+ retryAfter: payload.retryAfter,
26
+ }, status);
27
+ }
28
+ }
29
+ exports.ShieldBlockedException = ShieldBlockedException;
30
+ class ShieldPayloadException extends common_1.HttpException {
31
+ constructor(payload) {
32
+ super({
33
+ statusCode: common_1.HttpStatus.PAYLOAD_TOO_LARGE,
34
+ code: payload.code ?? 'SHIELD_PAYLOAD_TOO_LARGE',
35
+ message: payload.message,
36
+ layer: payload.layer,
37
+ }, common_1.HttpStatus.PAYLOAD_TOO_LARGE);
38
+ }
39
+ }
40
+ exports.ShieldPayloadException = ShieldPayloadException;
@@ -0,0 +1,32 @@
1
+ export { ShieldModule } from './shield.module';
2
+ export type { ShieldAsyncOptions } from './shield.module';
3
+ export { ShieldEngine } from './shield.engine';
4
+ export { ShieldGuard } from './shield.guard';
5
+ export { Shield } from './apply-to';
6
+ export type { NestAppLike } from './apply-to';
7
+ export { SHIELD_CONFIG, SHIELD_ENGINE, SHIELD_STORAGE, ALL_LAYERS, } from './shield.constants';
8
+ export type { ShieldLayer } from './shield.constants';
9
+ export type { ShieldConfig, RateLimitConfig, RateLimitAlgorithm, KeyByOption, IpListConfig, BlacklistConfig, AutoBanConfig, SlowDownConfig, UserAgentConfig, BurstConfig, PayloadConfig, ResponseConfig, StorageOption, RejectInfo, DecoratorOverrides, AnyRequest, AnyResponse, CheckOutcome, } from './shield.types';
10
+ export { RateLimit } from './decorators/rate-limit.decorator';
11
+ export { SkipShield } from './decorators/skip-shield.decorator';
12
+ export { Blacklist } from './decorators/blacklist.decorator';
13
+ export { Whitelist } from './decorators/whitelist.decorator';
14
+ export { SlowDown } from './decorators/slow-down.decorator';
15
+ export { MaxPayload } from './decorators/max-payload.decorator';
16
+ export { BurstLimit } from './decorators/burst-limit.decorator';
17
+ export { UserAgentPolicy } from './decorators/user-agent-policy.decorator';
18
+ export { MemoryStorage } from './storage/memory.storage';
19
+ export type { MemoryStorageOptions } from './storage/memory.storage';
20
+ export { RedisStorage } from './storage/redis.storage';
21
+ export type { RedisStorageOptions } from './storage/redis.storage';
22
+ export type { ShieldStorage, CounterResult, TokenBucketResult, WindowResult, } from './storage/shield-storage.interface';
23
+ export { TokenBucket } from './algorithms/token-bucket';
24
+ export { SlidingWindowCounter } from './algorithms/sliding-window-counter';
25
+ export { SlidingWindowLog } from './algorithms/sliding-window-log';
26
+ export { FixedWindow } from './algorithms/fixed-window';
27
+ export { LeakyBucket } from './algorithms/leaky-bucket';
28
+ export { ShieldRateLimitException, ShieldBlockedException, ShieldPayloadException, } from './exceptions/shield.exceptions';
29
+ export { IpUtil } from './utils/ip.util';
30
+ export { HeadersUtil } from './utils/headers.util';
31
+ export { UaUtil } from './utils/ua.util';
32
+ export { KeyUtil } from './utils/key.util';
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KeyUtil = exports.UaUtil = exports.HeadersUtil = exports.IpUtil = exports.ShieldPayloadException = exports.ShieldBlockedException = exports.ShieldRateLimitException = exports.LeakyBucket = exports.FixedWindow = exports.SlidingWindowLog = exports.SlidingWindowCounter = exports.TokenBucket = exports.RedisStorage = exports.MemoryStorage = exports.UserAgentPolicy = exports.BurstLimit = exports.MaxPayload = exports.SlowDown = exports.Whitelist = exports.Blacklist = exports.SkipShield = exports.RateLimit = exports.ALL_LAYERS = exports.SHIELD_STORAGE = exports.SHIELD_ENGINE = exports.SHIELD_CONFIG = exports.Shield = exports.ShieldGuard = exports.ShieldEngine = exports.ShieldModule = void 0;
4
+ var shield_module_1 = require("./shield.module");
5
+ Object.defineProperty(exports, "ShieldModule", { enumerable: true, get: function () { return shield_module_1.ShieldModule; } });
6
+ var shield_engine_1 = require("./shield.engine");
7
+ Object.defineProperty(exports, "ShieldEngine", { enumerable: true, get: function () { return shield_engine_1.ShieldEngine; } });
8
+ var shield_guard_1 = require("./shield.guard");
9
+ Object.defineProperty(exports, "ShieldGuard", { enumerable: true, get: function () { return shield_guard_1.ShieldGuard; } });
10
+ var apply_to_1 = require("./apply-to");
11
+ Object.defineProperty(exports, "Shield", { enumerable: true, get: function () { return apply_to_1.Shield; } });
12
+ var shield_constants_1 = require("./shield.constants");
13
+ Object.defineProperty(exports, "SHIELD_CONFIG", { enumerable: true, get: function () { return shield_constants_1.SHIELD_CONFIG; } });
14
+ Object.defineProperty(exports, "SHIELD_ENGINE", { enumerable: true, get: function () { return shield_constants_1.SHIELD_ENGINE; } });
15
+ Object.defineProperty(exports, "SHIELD_STORAGE", { enumerable: true, get: function () { return shield_constants_1.SHIELD_STORAGE; } });
16
+ Object.defineProperty(exports, "ALL_LAYERS", { enumerable: true, get: function () { return shield_constants_1.ALL_LAYERS; } });
17
+ var rate_limit_decorator_1 = require("./decorators/rate-limit.decorator");
18
+ Object.defineProperty(exports, "RateLimit", { enumerable: true, get: function () { return rate_limit_decorator_1.RateLimit; } });
19
+ var skip_shield_decorator_1 = require("./decorators/skip-shield.decorator");
20
+ Object.defineProperty(exports, "SkipShield", { enumerable: true, get: function () { return skip_shield_decorator_1.SkipShield; } });
21
+ var blacklist_decorator_1 = require("./decorators/blacklist.decorator");
22
+ Object.defineProperty(exports, "Blacklist", { enumerable: true, get: function () { return blacklist_decorator_1.Blacklist; } });
23
+ var whitelist_decorator_1 = require("./decorators/whitelist.decorator");
24
+ Object.defineProperty(exports, "Whitelist", { enumerable: true, get: function () { return whitelist_decorator_1.Whitelist; } });
25
+ var slow_down_decorator_1 = require("./decorators/slow-down.decorator");
26
+ Object.defineProperty(exports, "SlowDown", { enumerable: true, get: function () { return slow_down_decorator_1.SlowDown; } });
27
+ var max_payload_decorator_1 = require("./decorators/max-payload.decorator");
28
+ Object.defineProperty(exports, "MaxPayload", { enumerable: true, get: function () { return max_payload_decorator_1.MaxPayload; } });
29
+ var burst_limit_decorator_1 = require("./decorators/burst-limit.decorator");
30
+ Object.defineProperty(exports, "BurstLimit", { enumerable: true, get: function () { return burst_limit_decorator_1.BurstLimit; } });
31
+ var user_agent_policy_decorator_1 = require("./decorators/user-agent-policy.decorator");
32
+ Object.defineProperty(exports, "UserAgentPolicy", { enumerable: true, get: function () { return user_agent_policy_decorator_1.UserAgentPolicy; } });
33
+ var memory_storage_1 = require("./storage/memory.storage");
34
+ Object.defineProperty(exports, "MemoryStorage", { enumerable: true, get: function () { return memory_storage_1.MemoryStorage; } });
35
+ var redis_storage_1 = require("./storage/redis.storage");
36
+ Object.defineProperty(exports, "RedisStorage", { enumerable: true, get: function () { return redis_storage_1.RedisStorage; } });
37
+ var token_bucket_1 = require("./algorithms/token-bucket");
38
+ Object.defineProperty(exports, "TokenBucket", { enumerable: true, get: function () { return token_bucket_1.TokenBucket; } });
39
+ var sliding_window_counter_1 = require("./algorithms/sliding-window-counter");
40
+ Object.defineProperty(exports, "SlidingWindowCounter", { enumerable: true, get: function () { return sliding_window_counter_1.SlidingWindowCounter; } });
41
+ var sliding_window_log_1 = require("./algorithms/sliding-window-log");
42
+ Object.defineProperty(exports, "SlidingWindowLog", { enumerable: true, get: function () { return sliding_window_log_1.SlidingWindowLog; } });
43
+ var fixed_window_1 = require("./algorithms/fixed-window");
44
+ Object.defineProperty(exports, "FixedWindow", { enumerable: true, get: function () { return fixed_window_1.FixedWindow; } });
45
+ var leaky_bucket_1 = require("./algorithms/leaky-bucket");
46
+ Object.defineProperty(exports, "LeakyBucket", { enumerable: true, get: function () { return leaky_bucket_1.LeakyBucket; } });
47
+ var shield_exceptions_1 = require("./exceptions/shield.exceptions");
48
+ Object.defineProperty(exports, "ShieldRateLimitException", { enumerable: true, get: function () { return shield_exceptions_1.ShieldRateLimitException; } });
49
+ Object.defineProperty(exports, "ShieldBlockedException", { enumerable: true, get: function () { return shield_exceptions_1.ShieldBlockedException; } });
50
+ Object.defineProperty(exports, "ShieldPayloadException", { enumerable: true, get: function () { return shield_exceptions_1.ShieldPayloadException; } });
51
+ var ip_util_1 = require("./utils/ip.util");
52
+ Object.defineProperty(exports, "IpUtil", { enumerable: true, get: function () { return ip_util_1.IpUtil; } });
53
+ var headers_util_1 = require("./utils/headers.util");
54
+ Object.defineProperty(exports, "HeadersUtil", { enumerable: true, get: function () { return headers_util_1.HeadersUtil; } });
55
+ var ua_util_1 = require("./utils/ua.util");
56
+ Object.defineProperty(exports, "UaUtil", { enumerable: true, get: function () { return ua_util_1.UaUtil; } });
57
+ var key_util_1 = require("./utils/key.util");
58
+ Object.defineProperty(exports, "KeyUtil", { enumerable: true, get: function () { return key_util_1.KeyUtil; } });
@@ -0,0 +1,22 @@
1
+ export declare const SHIELD_CONFIG = "SHIELD_CONFIG";
2
+ export declare const SHIELD_STORAGE = "SHIELD_STORAGE";
3
+ export declare const SHIELD_ENGINE = "SHIELD_ENGINE";
4
+ export declare const META_RATE_LIMIT = "shield:rate-limit";
5
+ export declare const META_SKIP = "shield:skip";
6
+ export declare const META_BLACKLIST = "shield:blacklist";
7
+ export declare const META_WHITELIST = "shield:whitelist";
8
+ export declare const META_SLOW_DOWN = "shield:slow-down";
9
+ export declare const META_MAX_PAYLOAD = "shield:max-payload";
10
+ export declare const META_BURST = "shield:burst";
11
+ export declare const META_UA = "shield:user-agent";
12
+ export declare const KEY_PREFIX = "shield";
13
+ export declare const KEY_RATE_LIMIT = "shield:rl";
14
+ export declare const KEY_VIOLATIONS = "shield:violations";
15
+ export declare const KEY_BAN = "shield:ban";
16
+ export declare const KEY_BAN_COUNT = "shield:ban-count";
17
+ export declare const KEY_BURST = "shield:burst";
18
+ export declare const KEY_SLOW_DOWN = "shield:sd";
19
+ export declare const DEFAULT_MEMORY_MAX_KEYS = 100000;
20
+ export declare const DEFAULT_HEADERS_STANDARD: "draft-7";
21
+ export type ShieldLayer = 'whitelist' | 'blacklist' | 'auto-ban' | 'user-agent' | 'payload' | 'burst' | 'rate-limit' | 'slow-down';
22
+ export declare const ALL_LAYERS: ShieldLayer[];
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALL_LAYERS = exports.DEFAULT_HEADERS_STANDARD = exports.DEFAULT_MEMORY_MAX_KEYS = exports.KEY_SLOW_DOWN = exports.KEY_BURST = exports.KEY_BAN_COUNT = exports.KEY_BAN = exports.KEY_VIOLATIONS = exports.KEY_RATE_LIMIT = exports.KEY_PREFIX = exports.META_UA = exports.META_BURST = exports.META_MAX_PAYLOAD = exports.META_SLOW_DOWN = exports.META_WHITELIST = exports.META_BLACKLIST = exports.META_SKIP = exports.META_RATE_LIMIT = exports.SHIELD_ENGINE = exports.SHIELD_STORAGE = exports.SHIELD_CONFIG = void 0;
4
+ exports.SHIELD_CONFIG = 'SHIELD_CONFIG';
5
+ exports.SHIELD_STORAGE = 'SHIELD_STORAGE';
6
+ exports.SHIELD_ENGINE = 'SHIELD_ENGINE';
7
+ exports.META_RATE_LIMIT = 'shield:rate-limit';
8
+ exports.META_SKIP = 'shield:skip';
9
+ exports.META_BLACKLIST = 'shield:blacklist';
10
+ exports.META_WHITELIST = 'shield:whitelist';
11
+ exports.META_SLOW_DOWN = 'shield:slow-down';
12
+ exports.META_MAX_PAYLOAD = 'shield:max-payload';
13
+ exports.META_BURST = 'shield:burst';
14
+ exports.META_UA = 'shield:user-agent';
15
+ exports.KEY_PREFIX = 'shield';
16
+ exports.KEY_RATE_LIMIT = `${exports.KEY_PREFIX}:rl`;
17
+ exports.KEY_VIOLATIONS = `${exports.KEY_PREFIX}:violations`;
18
+ exports.KEY_BAN = `${exports.KEY_PREFIX}:ban`;
19
+ exports.KEY_BAN_COUNT = `${exports.KEY_PREFIX}:ban-count`;
20
+ exports.KEY_BURST = `${exports.KEY_PREFIX}:burst`;
21
+ exports.KEY_SLOW_DOWN = `${exports.KEY_PREFIX}:sd`;
22
+ exports.DEFAULT_MEMORY_MAX_KEYS = 100_000;
23
+ exports.DEFAULT_HEADERS_STANDARD = 'draft-7';
24
+ exports.ALL_LAYERS = [
25
+ 'whitelist',
26
+ 'blacklist',
27
+ 'auto-ban',
28
+ 'user-agent',
29
+ 'payload',
30
+ 'burst',
31
+ 'rate-limit',
32
+ 'slow-down',
33
+ ];
@@ -0,0 +1,21 @@
1
+ import { ShieldBlockedException, ShieldPayloadException, ShieldRateLimitException } from './exceptions/shield.exceptions';
2
+ import type { AnyRequest, AnyResponse, DecoratorOverrides, ShieldConfig } from './shield.types';
3
+ import type { ShieldStorage } from './storage/shield-storage.interface';
4
+ export interface EngineDecision {
5
+ allowed: boolean;
6
+ delayMs?: number;
7
+ release?: () => Promise<void> | void;
8
+ ip: string;
9
+ exception?: ShieldRateLimitException | ShieldBlockedException | ShieldPayloadException;
10
+ }
11
+ export declare class ShieldEngine {
12
+ private readonly config;
13
+ private readonly storage;
14
+ constructor(config: ShieldConfig, storage: ShieldStorage);
15
+ getConfig(): ShieldConfig;
16
+ getStorage(): ShieldStorage;
17
+ run(req: AnyRequest, res: AnyResponse, overrides?: DecoratorOverrides): Promise<EngineDecision>;
18
+ private merge;
19
+ private mergeRateLimit;
20
+ private notifyReject;
21
+ }