@fluojs/throttler 1.0.0 → 1.0.2
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/README.ko.md +8 -2
- package/README.md +8 -2
- package/dist/guard.d.ts.map +1 -1
- package/dist/guard.js +5 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/package.json +7 -6
package/README.ko.md
CHANGED
|
@@ -125,11 +125,12 @@ ThrottlerModule.forRoot({
|
|
|
125
125
|
- `ThrottlerModule.forRoot(options)`: 검증된 throttler 옵션과 `ThrottlerGuard`를 모듈 그래프에 제공합니다.
|
|
126
126
|
- 패키지 수준 등록은 `ThrottlerModule.forRoot(options)`를 통해 지원합니다. 내부 프로바이더 조합 헬퍼와 DI 토큰은 공개 계약에 포함되지 않습니다.
|
|
127
127
|
|
|
128
|
-
`ttl`과 `limit`은 양의 finite integer여야 합니다. `trustProxyHeaders`와 `keyGenerator`로 client identity를 조정할 수 있습니다. `store` 옵션을 제공하지 않으면 각 `ThrottlerGuard` 인스턴스가 자체 in-memory store를 소유합니다. 저장소를 공유하거나 외부에서 관리해야 한다면 `RedisThrottlerStore` 같은 `ThrottlerStore` 구현을 전달하세요.
|
|
128
|
+
`ttl`과 `limit`은 양의 finite integer여야 합니다. `trustProxyHeaders`와 `keyGenerator`로 client identity를 조정할 수 있습니다. 모듈 옵션은 guard가 연결될 때 검증되고 값으로 캡처되므로, 호출자가 나중에 options 객체를 변경해도 실행 중인 throttling 정책은 바뀌지 않습니다. `store` 옵션을 제공하지 않으면 각 `ThrottlerGuard` 인스턴스가 자체 in-memory store를 소유합니다. 저장소를 공유하거나 외부에서 관리해야 한다면 `RedisThrottlerStore` 같은 `ThrottlerStore` 구현을 전달하세요.
|
|
129
129
|
|
|
130
130
|
### 데코레이터
|
|
131
131
|
- `@Throttle({ ttl, limit })`: 클래스나 메서드에 특정 속도 제한을 설정합니다.
|
|
132
132
|
- `@SkipThrottle()`: 클래스나 메서드에 대해 속도 제한을 비활성화합니다.
|
|
133
|
+
- 기존 root-barrel metadata helper(`throttleRouteMetadataKey`, `getThrottleMetadata`, `getSkipThrottleMetadata`, `getClassThrottleMetadata`, `getClassSkipThrottleMetadata`)는 decorator metadata를 직접 검사하던 advanced integration과의 호환성을 위해 계속 export됩니다.
|
|
133
134
|
|
|
134
135
|
### 가드
|
|
135
136
|
- `ThrottlerGuard`: 속도 제한을 강제하는 가드입니다. `ThrottlerModule.forRoot()`는 이를 주입 가능하게 만들며, 라우트 핸들러는 `@UseGuards(ThrottlerGuard)` 같은 Fluo guard metadata로 직접 활성화해야 합니다.
|
|
@@ -143,6 +144,11 @@ ThrottlerModule.forRoot({
|
|
|
143
144
|
### status와 diagnostics
|
|
144
145
|
- `createThrottlerPlatformStatusSnapshot(...)`: 플랫폼 status snapshot을 생성합니다.
|
|
145
146
|
- `createThrottlerPlatformDiagnosticIssues(...)`: 잘못된 throttler 상태에 대한 diagnostic issue를 생성합니다.
|
|
147
|
+
- `ThrottlerStatusAdapterInput`: status 및 diagnostic helper의 공개 입력 shape입니다. 부트스트랩 중 수집한 store kind, ownership mode, operation mode, backing-store readiness, dependency linkage, readiness criticality 힌트를 전달합니다.
|
|
148
|
+
- `ThrottlerPlatformStatusSnapshot`: `createThrottlerPlatformStatusSnapshot(...)`이 반환하는 공개 출력 shape입니다. 런타임 platform snapshot과 호환되는 readiness, health, ownership, details 섹션을 포함합니다.
|
|
149
|
+
- `ThrottlerStoreKind`: status adapter가 인식하는 store category입니다: `memory`, `redis`, `custom`.
|
|
150
|
+
- `ThrottlerStoreOwnershipMode`: status snapshot에 보고되는 ownership mode입니다: guard가 소유한 리소스는 `framework`, 외부에서 관리되는 store는 `external`입니다.
|
|
151
|
+
- `ThrottlerOperationMode`: status details에 보고되는 operation mode입니다: `local-only`, `distributed`, `local-fallback`, `custom`.
|
|
146
152
|
|
|
147
153
|
메서드 수준 `@Throttle(...)`은 클래스 수준 설정보다 우선하고, 클래스 수준 설정은 모듈 기본값보다 우선합니다. `@SkipThrottle()`은 클래스나 메서드 수준 모두에서 throttling을 우회합니다.
|
|
148
154
|
|
|
@@ -153,7 +159,7 @@ ThrottlerModule.forRoot({
|
|
|
153
159
|
|
|
154
160
|
## 예제 소스
|
|
155
161
|
|
|
156
|
-
- `packages/throttler/src/module.test.ts`: 모듈
|
|
162
|
+
- `packages/throttler/src/module.test.ts`: 모듈 설정, 데코레이터 오버라이드, `createTestApp(...)` 기반 HTTP guard 통합 테스트.
|
|
157
163
|
- `packages/throttler/src/guard.ts`: 요청 제한 및 헤더 관리 코어 로직.
|
|
158
164
|
- `packages/throttler/src/redis-store.test.ts`: Redis store 계약과 server-time 동작.
|
|
159
165
|
- `packages/throttler/src/status.test.ts`: status 및 diagnostic helper 동작.
|
package/README.md
CHANGED
|
@@ -125,11 +125,12 @@ ThrottlerModule.forRoot({
|
|
|
125
125
|
- `ThrottlerModule.forRoot(options)`: Provides validated throttler options and `ThrottlerGuard` to the module graph.
|
|
126
126
|
- Package-level registration is supported through `ThrottlerModule.forRoot(options)`. Internal provider-composition helpers and DI tokens are not part of the public contract.
|
|
127
127
|
|
|
128
|
-
`ttl` and `limit` must be positive finite integers. `trustProxyHeaders` and `keyGenerator` customize client identity. If no `store` option is supplied, each `ThrottlerGuard` instance owns its own in-memory store; pass a `ThrottlerStore` implementation such as `RedisThrottlerStore` when storage must be shared or externally managed.
|
|
128
|
+
`ttl` and `limit` must be positive finite integers. `trustProxyHeaders` and `keyGenerator` customize client identity. Module options are validated and captured by value when the guard is wired so later mutation of the caller's options object does not change live throttling policy. If no `store` option is supplied, each `ThrottlerGuard` instance owns its own in-memory store; pass a `ThrottlerStore` implementation such as `RedisThrottlerStore` when storage must be shared or externally managed.
|
|
129
129
|
|
|
130
130
|
### Decorators
|
|
131
131
|
- `@Throttle({ ttl, limit })`: Sets a specific rate limit for a class or method.
|
|
132
132
|
- `@SkipThrottle()`: Disables throttling for a class or method.
|
|
133
|
+
- Existing root-barrel metadata helpers (`throttleRouteMetadataKey`, `getThrottleMetadata`, `getSkipThrottleMetadata`, `getClassThrottleMetadata`, and `getClassSkipThrottleMetadata`) remain exported for compatibility with advanced integrations that already inspect decorator metadata directly.
|
|
133
134
|
|
|
134
135
|
### Guards
|
|
135
136
|
- `ThrottlerGuard`: The guard responsible for enforcing rate limits. `ThrottlerModule.forRoot()` makes it injectable; route handlers still activate it through Fluo guard metadata such as `@UseGuards(ThrottlerGuard)`.
|
|
@@ -143,6 +144,11 @@ ThrottlerModule.forRoot({
|
|
|
143
144
|
### Status and diagnostics
|
|
144
145
|
- `createThrottlerPlatformStatusSnapshot(...)`: Creates a platform status snapshot.
|
|
145
146
|
- `createThrottlerPlatformDiagnosticIssues(...)`: Creates diagnostic issues for invalid throttler state.
|
|
147
|
+
- `ThrottlerStatusAdapterInput`: Public input shape for status and diagnostic helpers. It carries store kind, ownership mode, operation mode, backing-store readiness, dependency linkage, and readiness criticality hints collected during bootstrap.
|
|
148
|
+
- `ThrottlerPlatformStatusSnapshot`: Public output shape returned by `createThrottlerPlatformStatusSnapshot(...)`, containing readiness, health, ownership, and details sections compatible with runtime platform snapshots.
|
|
149
|
+
- `ThrottlerStoreKind`: Store categories recognized by the status adapter: `memory`, `redis`, or `custom`.
|
|
150
|
+
- `ThrottlerStoreOwnershipMode`: Ownership modes reported in status snapshots: `framework` for guard-owned resources or `external` for externally managed stores.
|
|
151
|
+
- `ThrottlerOperationMode`: Operation modes reported in status details: `local-only`, `distributed`, `local-fallback`, or `custom`.
|
|
146
152
|
|
|
147
153
|
Method-level `@Throttle(...)` overrides class-level settings, class-level settings override module defaults, and `@SkipThrottle()` bypasses throttling at either class or method level.
|
|
148
154
|
|
|
@@ -153,7 +159,7 @@ Method-level `@Throttle(...)` overrides class-level settings, class-level settin
|
|
|
153
159
|
|
|
154
160
|
## Example Sources
|
|
155
161
|
|
|
156
|
-
- `packages/throttler/src/module.test.ts`: Tests for module configuration and
|
|
162
|
+
- `packages/throttler/src/module.test.ts`: Tests for module configuration, decorator overrides, and HTTP guard integration through `createTestApp(...)`.
|
|
157
163
|
- `packages/throttler/src/guard.ts`: The core logic for request throttling and header management.
|
|
158
164
|
- `packages/throttler/src/redis-store.test.ts`: Redis store contract and server-time behavior.
|
|
159
165
|
- `packages/throttler/src/status.test.ts`: Status and diagnostic helper behavior.
|
package/dist/guard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAoD,MAAM,cAAc,CAAC;AAa/G,OAAO,KAAK,EAAE,sBAAsB,EAAuC,MAAM,YAAY,CAAC;AAuD9F;;GAEG;AACH,qBACa,cAAe,YAAW,KAAK;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAE3B,OAAO,EAAE,sBAAsB;IAO3C;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;CAkD3D"}
|
package/dist/guard.js
CHANGED
|
@@ -9,8 +9,8 @@ import { getStandardMetadataBag } from '@fluojs/core/internal';
|
|
|
9
9
|
import { TooManyRequestsException } from '@fluojs/http';
|
|
10
10
|
import { resolveClientIdentity } from '@fluojs/http/internal';
|
|
11
11
|
import { getClassSkipThrottleMetadata, getClassThrottleMetadata, getSkipThrottleMetadata, getThrottleMetadata, throttleRouteMetadataKey } from './decorators.js';
|
|
12
|
-
import { throttlerRetryAfterMsSymbol } from './store-internals.js';
|
|
13
12
|
import { createMemoryThrottlerStore } from './store.js';
|
|
13
|
+
import { throttlerRetryAfterMsSymbol } from './store-internals.js';
|
|
14
14
|
import { THROTTLER_OPTIONS } from './tokens.js';
|
|
15
15
|
import { validateThrottleOptions, validateThrottlerModuleOptions, validateThrottlerStoreEntry } from './validation.js';
|
|
16
16
|
function getClassMetadataBag(target) {
|
|
@@ -54,11 +54,12 @@ class ThrottlerGuard {
|
|
|
54
54
|
static {
|
|
55
55
|
[_ThrottlerGuard, _initClass] = _applyDecs(this, [Inject(THROTTLER_OPTIONS)], []).c;
|
|
56
56
|
}
|
|
57
|
+
options;
|
|
57
58
|
store;
|
|
58
59
|
constructor(options) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.store =
|
|
60
|
+
const validatedOptions = validateThrottlerModuleOptions(options);
|
|
61
|
+
this.options = validatedOptions;
|
|
62
|
+
this.store = validatedOptions.store ?? createMemoryThrottlerStore();
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { getClassSkipThrottleMetadata, getClassThrottleMetadata, getSkipThrottleMetadata, getThrottleMetadata, SkipThrottle, Throttle, throttleRouteMetadataKey, } from './decorators.js';
|
|
2
2
|
export { ThrottlerGuard } from './guard.js';
|
|
3
|
-
export { RedisThrottlerStore } from './redis-store.js';
|
|
4
3
|
export * from './module.js';
|
|
4
|
+
export { RedisThrottlerStore } from './redis-store.js';
|
|
5
5
|
export * from './status.js';
|
|
6
6
|
export { createMemoryThrottlerStore } from './store.js';
|
|
7
7
|
export type { ThrottlerConsumeInput, ThrottlerHandlerOptions, ThrottlerModuleOptions, ThrottlerStore, ThrottlerStoreEntry, } from './types.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AACxD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { getClassSkipThrottleMetadata, getClassThrottleMetadata, getSkipThrottleMetadata, getThrottleMetadata, SkipThrottle, Throttle, throttleRouteMetadataKey } from './decorators.js';
|
|
2
2
|
export { ThrottlerGuard } from './guard.js';
|
|
3
|
-
export { RedisThrottlerStore } from './redis-store.js';
|
|
4
3
|
export * from './module.js';
|
|
4
|
+
export { RedisThrottlerStore } from './redis-store.js';
|
|
5
5
|
export * from './status.js';
|
|
6
6
|
export { createMemoryThrottlerStore } from './store.js';
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"redis",
|
|
10
10
|
"decorator"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.
|
|
12
|
+
"version": "1.0.2",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.
|
|
40
|
-
"@fluojs/di": "^1.0.
|
|
41
|
-
"@fluojs/
|
|
42
|
-
"@fluojs/
|
|
39
|
+
"@fluojs/core": "^1.0.2",
|
|
40
|
+
"@fluojs/di": "^1.0.2",
|
|
41
|
+
"@fluojs/http": "^1.0.0",
|
|
42
|
+
"@fluojs/runtime": "^1.1.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"ioredis": "^5.0.0",
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"ioredis": "^5.10.0",
|
|
58
|
-
"vitest": "^3.2.4"
|
|
58
|
+
"vitest": "^3.2.4",
|
|
59
|
+
"@fluojs/testing": "^1.0.2"
|
|
59
60
|
},
|
|
60
61
|
"scripts": {
|
|
61
62
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|