@cqrs-ddd/pipeline-rate-limit 0.5.1 → 0.6.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.
@@ -2,8 +2,9 @@
2
2
  * Thrown by {@link RateLimitBehavior} when a request exceeds its allotted
3
3
  * points for the current window.
4
4
  *
5
- * Map it to HTTP `429 Too Many Requests` with {@link RateLimitExceededFilter},
6
- * which also emits a `Retry-After` header from {@link retryAfterSeconds}.
5
+ * Map it to HTTP `429 Too Many Requests` with `toHttpResponse` of
6
+ * `@cqrs-ddd/pipeline-rate-limit/http`, which also gives a `Retry-After` header
7
+ * from {@link retryAfterSeconds}.
7
8
  */
8
9
  export declare class RateLimitExceededError extends Error {
9
10
  /** The rate-limit bucket key that was exhausted. */
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit-exceeded.error.d.ts","sourceRoot":"","sources":["../../src/errors/rate-limit-exceeded.error.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,oDAAoD;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,YAAY,MAAM,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAiBA;CACF"}
1
+ {"version":3,"file":"rate-limit-exceeded.error.d.ts","sourceRoot":"","sources":["../../src/errors/rate-limit-exceeded.error.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,oDAAoD;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,YAAY,MAAM,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAiBA;CACF"}
@@ -3,8 +3,9 @@
3
3
  * Thrown by {@link RateLimitBehavior} when a request exceeds its allotted
4
4
  * points for the current window.
5
5
  *
6
- * Map it to HTTP `429 Too Many Requests` with {@link RateLimitExceededFilter},
7
- * which also emits a `Retry-After` header from {@link retryAfterSeconds}.
6
+ * Map it to HTTP `429 Too Many Requests` with `toHttpResponse` of
7
+ * `@cqrs-ddd/pipeline-rate-limit/http`, which also gives a `Retry-After` header
8
+ * from {@link retryAfterSeconds}.
8
9
  */
9
10
  export class RateLimitExceededError extends Error {
10
11
  /** The rate-limit bucket key that was exhausted. */
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit-exceeded.error.js","sourceRoot":"","sources":["../../src/errors/rate-limit-exceeded.error.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE;;;;;;GAMG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,oDAAoD;IAC3C,GAAG,CAAS;IACrB,gEAAgE;IACvD,WAAW,CAAS;IAC7B,+CAA+C;IACtC,YAAY,CAAS;IAC9B,0EAA0E;IACjE,iBAAiB,CAAS;IACnC,2DAA2D;IAClD,eAAe,CAAS;IACjC,wDAAwD;IAC/C,KAAK,CAAU;IACxB;;;OAGG;IACM,MAAM,CAAU;IAEzB,YAAY,MAOX;QACC,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAChC,CAAC,EACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CACtC,CAAC;QACF,KAAK,CACH,2BAA2B,MAAM,CAAC,WAAW,GAAG;YAC9C,SAAS,MAAM,CAAC,GAAG,kBAAkB,iBAAiB,GAAG,CAC5D,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;CACF"}
1
+ {"version":3,"file":"rate-limit-exceeded.error.js","sourceRoot":"","sources":["../../src/errors/rate-limit-exceeded.error.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,oDAAoD;IAC3C,GAAG,CAAS;IACrB,gEAAgE;IACvD,WAAW,CAAS;IAC7B,+CAA+C;IACtC,YAAY,CAAS;IAC9B,0EAA0E;IACjE,iBAAiB,CAAS;IACnC,2DAA2D;IAClD,eAAe,CAAS;IACjC,wDAAwD;IAC/C,KAAK,CAAU;IACxB;;;OAGG;IACM,MAAM,CAAU;IAEzB,YAAY,MAOX;QACC,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAChC,CAAC,EACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CACtC,CAAC;QACF,KAAK,CACH,2BAA2B,MAAM,CAAC,WAAW,GAAG;YAC9C,SAAS,MAAM,CAAC,GAAG,kBAAkB,iBAAiB,GAAG,CAC5D,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;CACF"}
@@ -6,8 +6,11 @@ import type { RateLimitKeyFactory } from '../interfaces/rate-limit-options.inter
6
6
  *
7
7
  * Typical values are an authenticated user ID, account ID, API-client ID, or a
8
8
  * trusted transport identity copied into `context.items` by an earlier behavior.
9
+ *
10
+ * @typeParam TRequest - The request class the handler receives, which types
11
+ * `context.request`. The factory does not check it at run time.
9
12
  */
10
- export type RateLimitPartitionFactory = (context: IPipelineContext) => string | undefined;
13
+ export type RateLimitPartitionFactory<TRequest = unknown> = (context: IPipelineContext<TRequest>) => string | undefined;
11
14
  /** Options for {@link createPartitionedRateLimitKeyFactory}. */
12
15
  export interface PartitionedRateLimitKeyOptions extends TenantPartitionOptions {
13
16
  /**
@@ -51,6 +54,11 @@ export interface PartitionedRateLimitKeyOptions extends TenantPartitionOptions {
51
54
  * }
52
55
  * ```
53
56
  *
57
+ * @example Per value of the request, typed by the request class
58
+ * ```ts
59
+ * createPartitionedRateLimitKeyFactory<LoginCommand>((ctx) => ctx.request.clientIp);
60
+ * ```
61
+ *
54
62
  * @example Single-tenant deployment — say so explicitly
55
63
  * ```ts
56
64
  * createPartitionedRateLimitKeyFactory(readUserId, { includeTenant: false });
@@ -61,5 +69,5 @@ export interface PartitionedRateLimitKeyOptions extends TenantPartitionOptions {
61
69
  * createPartitionedRateLimitKeyFactory(readAccountId, { includeTenant: true });
62
70
  * ```
63
71
  */
64
- export declare function createPartitionedRateLimitKeyFactory(partitionFactory: RateLimitPartitionFactory, options?: PartitionedRateLimitKeyOptions): RateLimitKeyFactory;
72
+ export declare function createPartitionedRateLimitKeyFactory<TRequest = unknown>(partitionFactory: RateLimitPartitionFactory<TRequest>, options?: PartitionedRateLimitKeyOptions): RateLimitKeyFactory;
65
73
  //# sourceMappingURL=partitioned-key.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"partitioned-key.d.ts","sourceRoot":"","sources":["../../src/helpers/partitioned-key.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAE5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AAEzF;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,OAAO,EAAE,gBAAgB,KACtB,MAAM,GAAG,SAAS,CAAC;AAExB,gEAAgE;AAChE,MAAM,WAAW,8BAA+B,SAAQ,sBAAsB;IAC5E;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,oCAAoC,CAClD,gBAAgB,EAAE,yBAAyB,EAC3C,OAAO,GAAE,8BAAmC,GAC3C,mBAAmB,CA8BrB"}
1
+ {"version":3,"file":"partitioned-key.d.ts","sourceRoot":"","sources":["../../src/helpers/partitioned-key.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,sBAAsB,EAE5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AAEzF;;;;;;;;;GASG;AACH,MAAM,MAAM,yBAAyB,CAAC,QAAQ,GAAG,OAAO,IAAI,CAC1D,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAChC,MAAM,GAAG,SAAS,CAAC;AAExB,gEAAgE;AAChE,MAAM,WAAW,8BAA+B,SAAQ,sBAAsB;IAC5E;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,oCAAoC,CAAC,QAAQ,GAAG,OAAO,EACrE,gBAAgB,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EACrD,OAAO,GAAE,8BAAmC,GAC3C,mBAAmB,CAgCrB"}
@@ -1,5 +1,5 @@
1
1
  /* Copyright (C) 2026-present Aristotelis — see repository license. */
2
- import { tenantSegments, } from '@cqrs-ddd/pipeline';
2
+ import { principalSegments, tenantSegments, } from '@cqrs-ddd/pipeline';
3
3
  import { joinKeySegments } from '@cqrs-ddd/safe-stringify';
4
4
  import { MissingRateLimitPartitionError } from '../errors/missing-partition.error.js';
5
5
  /**
@@ -31,6 +31,11 @@ import { MissingRateLimitPartitionError } from '../errors/missing-partition.erro
31
31
  * }
32
32
  * ```
33
33
  *
34
+ * @example Per value of the request, typed by the request class
35
+ * ```ts
36
+ * createPartitionedRateLimitKeyFactory<LoginCommand>((ctx) => ctx.request.clientIp);
37
+ * ```
38
+ *
34
39
  * @example Single-tenant deployment — say so explicitly
35
40
  * ```ts
36
41
  * createPartitionedRateLimitKeyFactory(readUserId, { includeTenant: false });
@@ -46,7 +51,7 @@ export function createPartitionedRateLimitKeyFactory(partitionFactory, options =
46
51
  const keyFor = (context) => {
47
52
  const tenant = tenantSegments(context, options, MissingRateLimitPartitionError);
48
53
  const resolved = partitionFactory(context);
49
- const partition = typeof resolved === 'string' ? resolved.trim() : '';
54
+ const partition = principalSegments(typeof resolved === 'string' ? resolved : undefined);
50
55
  if (!partition) {
51
56
  if (onMissingPartition === 'throw') {
52
57
  throw new MissingRateLimitPartitionError(context.requestName, 'caller', "Return a stable caller/account identifier, or configure onMissingPartition: 'request'.");
@@ -55,7 +60,7 @@ export function createPartitionedRateLimitKeyFactory(partitionFactory, options =
55
60
  // so an anonymous caller in one tenant cannot exhaust another tenant's quota.
56
61
  return joinKeySegments([...tenant, context.requestName]);
57
62
  }
58
- return joinKeySegments([...tenant, partition, context.requestName]);
63
+ return joinKeySegments([...tenant, ...partition, context.requestName]);
59
64
  };
60
65
  return keyFor;
61
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"partitioned-key.js","sourceRoot":"","sources":["../../src/helpers/partitioned-key.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAGL,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AA6BtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,UAAU,oCAAoC,CAClD,gBAA2C,EAC3C,OAAO,GAAmC,EAAE;IAE5C,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC;IAEjE,MAAM,MAAM,GAAwB,CAAC,OAAO,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,cAAc,CAC3B,OAAO,EACP,OAAO,EACP,8BAA8B,CAC/B,CAAC;QAEF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,kBAAkB,KAAK,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,8BAA8B,CACtC,OAAO,CAAC,WAAW,EACnB,QAAQ,EACR,wFAAwF,CACzF,CAAC;YACJ,CAAC;YACD,yEAAyE;YACzE,8EAA8E;YAC9E,OAAO,eAAe,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,eAAe,CAAC,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"partitioned-key.js","sourceRoot":"","sources":["../../src/helpers/partitioned-key.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAEL,iBAAiB,EAEjB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAgCtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,UAAU,oCAAoC,CAClD,gBAAqD,EACrD,OAAO,GAAmC,EAAE;IAE5C,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC;IAEjE,MAAM,MAAM,GAAwB,CAAC,OAAO,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,cAAc,CAC3B,OAAO,EACP,OAAO,EACP,8BAA8B,CAC/B,CAAC;QAEF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAqC,CAAC,CAAC;QACzE,MAAM,SAAS,GAAG,iBAAiB,CACjC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CACpD,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,kBAAkB,KAAK,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,8BAA8B,CACtC,OAAO,CAAC,WAAW,EACnB,QAAQ,EACR,wFAAwF,CACzF,CAAC;YACJ,CAAC;YACD,yEAAyE;YACzE,8EAA8E;YAC9E,OAAO,eAAe,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,eAAe,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/http.d.ts CHANGED
@@ -1,13 +1,10 @@
1
+ import type { HttpResponse } from '@cqrs-ddd/pipeline';
1
2
  import { RateLimitExceededError } from './errors/rate-limit-exceeded.error.js';
2
- /** An HTTP answer for an error: status, JSON body and headers. */
3
- export interface HttpResponse {
4
- status: number;
5
- body: Record<string, unknown>;
6
- headers: Record<string, string>;
7
- }
3
+ export type { HttpResponse };
8
4
  /**
9
5
  * The HTTP answer for a {@link RateLimitExceededError}: `429 Too Many Requests` with a
10
6
  * `Retry-After` header. Framework filters and Express handlers reply with it.
7
+ * The body never carries the bucket key, which holds the tenant and the caller.
11
8
  *
12
9
  * @example
13
10
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAW1E"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAW1E"}
package/dist/http.js CHANGED
@@ -2,6 +2,7 @@
2
2
  /**
3
3
  * The HTTP answer for a {@link RateLimitExceededError}: `429 Too Many Requests` with a
4
4
  * `Retry-After` header. Framework filters and Express handlers reply with it.
5
+ * The body never carries the bucket key, which holds the tenant and the caller.
5
6
  *
6
7
  * @example
7
8
  * ```ts
@@ -18,7 +19,7 @@ export function toHttpResponse(error) {
18
19
  body: {
19
20
  statusCode: 429,
20
21
  error: 'Too Many Requests',
21
- message: error.message,
22
+ message: `Rate limit exceeded; retry after ${error.retryAfterSeconds}s`,
22
23
  retryAfter: error.retryAfterSeconds,
23
24
  },
24
25
  headers: { 'Retry-After': String(error.retryAfterSeconds) },
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAWtE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,KAA6B;IAC1D,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,mBAAmB;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,iBAAiB;SACpC;QACD,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;KAC5D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAOtE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,KAA6B;IAC1D,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,mBAAmB;YAC1B,OAAO,EAAE,oCAAoC,KAAK,CAAC,iBAAiB,GAAG;YACvE,UAAU,EAAE,KAAK,CAAC,iBAAiB;SACpC;QACD,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;KAC5D,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -11,5 +11,5 @@ export { createPartitionedRateLimitKeyFactory, type PartitionedRateLimitKeyOptio
11
11
  export { type RateLimitIntentOptions, rateLimit, } from './helpers/rate-limit.intent.js';
12
12
  export type { RateLimitBehaviorOptions, RateLimitCostFactory, RateLimitKeyFactory, } from './interfaces/rate-limit-options.interface.js';
13
13
  export type { RateLimiterLike, RateLimiterResLike, } from './interfaces/rate-limiter.interface.js';
14
- export { RATE_LIMIT_ITEM, RATE_LIMIT_ITEM_TOKEN, RATE_LIMIT_KEY_ITEM, RATE_LIMIT_KEY_ITEM_TOKEN, RateLimitBehavior, } from './rate-limit.behavior.js';
14
+ export { RATE_LIMIT_ITEM_TOKEN, RATE_LIMIT_KEY_ITEM_TOKEN, RateLimitBehavior, } from './rate-limit.behavior.js';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EACL,8BAA8B,EAC9B,KAAK,2BAA2B,GACjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,oCAAoC,EACpC,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,sBAAsB,EAC3B,SAAS,GACV,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,8CAA8C,CAAC;AACtD,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EACL,8BAA8B,EAC9B,KAAK,2BAA2B,GACjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,oCAAoC,EACpC,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,sBAAsB,EAC3B,SAAS,GACV,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,8CAA8C,CAAC;AACtD,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -10,5 +10,5 @@ export { buildRateLimitAttributes } from './helpers/build-attributes.js';
10
10
  export { buildRateLimitKey } from './helpers/build-key.js';
11
11
  export { createPartitionedRateLimitKeyFactory, } from './helpers/partitioned-key.js';
12
12
  export { rateLimit, } from './helpers/rate-limit.intent.js';
13
- export { RATE_LIMIT_ITEM, RATE_LIMIT_ITEM_TOKEN, RATE_LIMIT_KEY_ITEM, RATE_LIMIT_KEY_ITEM_TOKEN, RateLimitBehavior, } from './rate-limit.behavior.js';
13
+ export { RATE_LIMIT_ITEM_TOKEN, RATE_LIMIT_KEY_ITEM_TOKEN, RateLimitBehavior, } from './rate-limit.behavior.js';
14
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE;;;;GAIG;AAEH,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,oCAAoC,GAGrC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,SAAS,GACV,MAAM,gCAAgC,CAAC;AAUxC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE;;;;GAIG;AAEH,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,oCAAoC,GAGrC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,SAAS,GACV,MAAM,gCAAgC,CAAC;AAUxC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC"}
@@ -2,31 +2,15 @@ import { type IPipelineBehavior, type IPipelineBehaviorContract, type IPipelineB
2
2
  import type { RateLimitBehaviorOptions } from './interfaces/rate-limit-options.interface.js';
3
3
  import type { RateLimiterLike, RateLimiterResLike } from './interfaces/rate-limiter.interface.js';
4
4
  /**
5
- * Unique symbol key set on `context.items` containing the result of a rate-limit check (or rejection payload).
5
+ * The `context.items` entry containing the result of a rate-limit check (or rejection payload).
6
6
  *
7
- * @example
8
- * ```ts
9
- * const result = context.items.get(RATE_LIMIT_ITEM);
10
- * ```
11
- */
12
- export declare const RATE_LIMIT_ITEM: unique symbol;
13
- /**
14
- * Typed token for {@link RATE_LIMIT_ITEM}: the rate-limit result. Reads and writes the same
15
- * `context.items` entry through `getPipelineItem` / `requirePipelineItem`.
7
+ * Read it with `getPipelineItem` or `requirePipelineItem`.
16
8
  */
17
9
  export declare const RATE_LIMIT_ITEM_TOKEN: PipelineItemToken<RateLimiterResLike>;
18
10
  /**
19
- * Unique symbol key set on `context.items` containing the resolved rate limit bucket key string.
11
+ * The `context.items` entry containing the resolved rate limit bucket key string.
20
12
  *
21
- * @example
22
- * ```ts
23
- * const key = context.items.get(RATE_LIMIT_KEY_ITEM) as string | undefined;
24
- * ```
25
- */
26
- export declare const RATE_LIMIT_KEY_ITEM: unique symbol;
27
- /**
28
- * Typed token for {@link RATE_LIMIT_KEY_ITEM}: the resolved rate-limit key. Reads and writes the same
29
- * `context.items` entry through `getPipelineItem` / `requirePipelineItem`.
13
+ * Read it with `getPipelineItem` or `requirePipelineItem`.
30
14
  */
31
15
  export declare const RATE_LIMIT_KEY_ITEM_TOKEN: PipelineItemToken<string>;
32
16
  /**
@@ -66,8 +50,8 @@ export declare class RateLimitBehavior implements IPipelineBehavior, IPipelineBe
66
50
  private readonly defaults;
67
51
  constructor(limiter: RateLimiterLike, defaults?: RateLimitBehaviorOptions, logger?: PipelineLogger);
68
52
  handle(context: IPipelineContext, next: NextDelegate): Promise<unknown>;
69
- /** Fail-open (default) or fail-closed when the backing store itself errors. */
70
- private handleStoreError;
53
+ /** Logs a failure of the backing store, and rethrows it unless failing open (default). */
54
+ private reportStoreError;
71
55
  /** Shallow-merges pipeline-level options over the constructor defaults. */
72
56
  resolveEffectiveOptions(options?: RateLimitBehaviorOptions): RateLimitBehaviorOptions;
73
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.behavior.d.ts","sourceRoot":"","sources":["../src/rate-limit.behavior.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,gCAAgC,EACrC,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,0BAA0B,EAG1B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,eAA4B,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,iBAAiB,CAAC,kBAAkB,CACI,CAAC;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAAgC,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,iBAAiB,CAAC,MAAM,CACQ,CAAC;AAmBzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,iBACX,YACE,iBAAiB,EACjB,gCAAgC,CAAC,wBAAwB,CAAC;IA2D1D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAzD1B,MAAM,CAAC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,EAAE,yBAAyB,CAmDrE;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IAEpD,YACmB,OAAO,EAAE,eAAe,EACzC,QAAQ,CAAC,EAAE,wBAAwB,EACnC,MAAM,CAAC,EAAE,cAAc,EAUxB;IAEK,MAAM,CACV,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,OAAO,CAAC,CAgClB;IAED,+EAA+E;IAC/E,OAAO,CAAC,gBAAgB;IAyBxB,2EAA2E;IAC3E,uBAAuB,CACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,wBAAwB,CAG1B;CACF"}
1
+ {"version":3,"file":"rate-limit.behavior.d.ts","sourceRoot":"","sources":["../src/rate-limit.behavior.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,gCAAgC,EACrC,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,0BAA0B,EAC1B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,iBAAiB,CAAC,kBAAkB,CACb,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,iBAAiB,CAAC,MAAM,CACb,CAAC;AAmBpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,iBACX,YACE,iBAAiB,EACjB,gCAAgC,CAAC,wBAAwB,CAAC;IA0C1D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxC1B,MAAM,CAAC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,EAAE,yBAAyB,CAkCrE;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IAEpD,YACmB,OAAO,EAAE,eAAe,EACzC,QAAQ,CAAC,EAAE,wBAAwB,EACnC,MAAM,CAAC,EAAE,cAAc,EAUxB;IAEK,MAAM,CACV,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,OAAO,CAAC,CA+BlB;IAED,0FAA0F;IAC1F,OAAO,CAAC,gBAAgB;IAaxB,2EAA2E;IAC3E,uBAAuB,CACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,wBAAwB,CAG1B;CACF"}
@@ -1,35 +1,19 @@
1
1
  /* Copyright (C) 2026-present Aristotelis — see repository license. */
2
- import { createPipelineItem, PIPELINE_BEHAVIOR_CONTRACT, setPipelineItem, } from '@cqrs-ddd/pipeline';
2
+ import { behaviorDiagnostic, createPipelineItem, PIPELINE_BEHAVIOR_CONTRACT, setPipelineItem, } from '@cqrs-ddd/pipeline';
3
3
  import { RateLimitExceededError } from './errors/rate-limit-exceeded.error.js';
4
4
  import { buildRateLimitKey } from './helpers/build-key.js';
5
5
  /**
6
- * Unique symbol key set on `context.items` containing the result of a rate-limit check (or rejection payload).
6
+ * The `context.items` entry containing the result of a rate-limit check (or rejection payload).
7
7
  *
8
- * @example
9
- * ```ts
10
- * const result = context.items.get(RATE_LIMIT_ITEM);
11
- * ```
12
- */
13
- export const RATE_LIMIT_ITEM = Symbol('RATE_LIMIT_ITEM');
14
- /**
15
- * Typed token for {@link RATE_LIMIT_ITEM}: the rate-limit result. Reads and writes the same
16
- * `context.items` entry through `getPipelineItem` / `requirePipelineItem`.
8
+ * Read it with `getPipelineItem` or `requirePipelineItem`.
17
9
  */
18
- export const RATE_LIMIT_ITEM_TOKEN = createPipelineItem('RATE_LIMIT_ITEM', RATE_LIMIT_ITEM);
10
+ export const RATE_LIMIT_ITEM_TOKEN = createPipelineItem('RATE_LIMIT_ITEM');
19
11
  /**
20
- * Unique symbol key set on `context.items` containing the resolved rate limit bucket key string.
12
+ * The `context.items` entry containing the resolved rate limit bucket key string.
21
13
  *
22
- * @example
23
- * ```ts
24
- * const key = context.items.get(RATE_LIMIT_KEY_ITEM) as string | undefined;
25
- * ```
26
- */
27
- export const RATE_LIMIT_KEY_ITEM = Symbol('RATE_LIMIT_KEY_ITEM');
28
- /**
29
- * Typed token for {@link RATE_LIMIT_KEY_ITEM}: the resolved rate-limit key. Reads and writes the same
30
- * `context.items` entry through `getPipelineItem` / `requirePipelineItem`.
14
+ * Read it with `getPipelineItem` or `requirePipelineItem`.
31
15
  */
32
- export const RATE_LIMIT_KEY_ITEM_TOKEN = createPipelineItem('RATE_LIMIT_KEY_ITEM', RATE_LIMIT_KEY_ITEM);
16
+ export const RATE_LIMIT_KEY_ITEM_TOKEN = createPipelineItem('RATE_LIMIT_KEY_ITEM');
33
17
  /** Whether a rejection value is a `rate-limiter-flexible` result (a limit hit). */
34
18
  function isRateLimiterRes(value) {
35
19
  return (typeof value === 'object' &&
@@ -73,38 +57,27 @@ export class RateLimitBehavior {
73
57
  validate: (context) => {
74
58
  const options = context.effectiveOptions;
75
59
  if (!options?.keyFactory) {
76
- return [
77
- {
78
- handlerName: context.handlerName,
79
- behaviorName: RateLimitBehavior.name,
80
- message: 'Active RateLimitBehavior requires an explicit `keyFactory`',
81
- fix: 'Provide keyFactory in the [RateLimitBehavior, { keyFactory: ... }] entry, ' +
82
- 'the constructor defaults, or use createPartitionedRateLimitKeyFactory(...).',
83
- },
84
- ];
60
+ return behaviorDiagnostic(context, RateLimitBehavior.name, {
61
+ message: 'Active RateLimitBehavior requires an explicit `keyFactory`',
62
+ fix: 'Provide keyFactory in the [RateLimitBehavior, { keyFactory: ... }] entry, ' +
63
+ 'the constructor defaults, or use createPartitionedRateLimitKeyFactory(...).',
64
+ });
85
65
  }
86
66
  if (typeof options.keyFactory !== 'function') {
87
- return [
88
- {
89
- handlerName: context.handlerName,
90
- behaviorName: RateLimitBehavior.name,
91
- message: `RateLimitBehavior keyFactory must be a callable function, received ${typeof options.keyFactory}`,
92
- fix: 'Pass a valid function (ctx) => string to the keyFactory option of the [RateLimitBehavior, { keyFactory: ... }] entry.',
93
- },
94
- ];
67
+ return behaviorDiagnostic(context, RateLimitBehavior.name, {
68
+ message: `RateLimitBehavior keyFactory must be a callable function, received ${typeof options.keyFactory}`,
69
+ fix: 'Pass a valid function (ctx) => string to the keyFactory option of the [RateLimitBehavior, { keyFactory: ... }] entry.',
70
+ });
95
71
  }
96
72
  const { points } = options;
97
- if (points !== undefined &&
73
+ const isInvalidPoints = points !== undefined &&
98
74
  typeof points !== 'function' &&
99
- !isValidPoints(points)) {
100
- return [
101
- {
102
- handlerName: context.handlerName,
103
- behaviorName: RateLimitBehavior.name,
104
- message: `RateLimitBehavior points must be a non-negative safe integer or a function, received ${String(points)}`,
105
- fix: 'Pass an integer from 0 up (0 charges nothing) or a function (ctx) => number as the points option.',
106
- },
107
- ];
75
+ !isValidPoints(points);
76
+ if (isInvalidPoints) {
77
+ return behaviorDiagnostic(context, RateLimitBehavior.name, {
78
+ message: `RateLimitBehavior points must be a non-negative safe integer or a function, received ${String(points)}`,
79
+ fix: 'Pass an integer from 0 up (0 charges nothing) or a function (ctx) => number as the points option.',
80
+ });
108
81
  }
109
82
  return undefined;
110
83
  },
@@ -127,39 +100,36 @@ export class RateLimitBehavior {
127
100
  const limiter = options.limiter ?? this.limiter;
128
101
  const key = buildRateLimitKey(context, options);
129
102
  setPipelineItem(context, RATE_LIMIT_KEY_ITEM_TOKEN, key);
130
- let result;
131
103
  try {
132
- result = await limiter.consume(key, points);
104
+ const result = await limiter.consume(key, points);
105
+ setPipelineItem(context, RATE_LIMIT_ITEM_TOKEN, result);
133
106
  }
134
107
  catch (error) {
135
- if (isRateLimiterRes(error)) {
136
- setPipelineItem(context, RATE_LIMIT_ITEM_TOKEN, error);
137
- throw new RateLimitExceededError({
138
- key,
139
- requestName: context.requestName,
140
- msBeforeNext: error.msBeforeNext,
141
- remainingPoints: error.remainingPoints,
142
- limit: limiter.points,
143
- points,
144
- });
108
+ if (!isRateLimiterRes(error)) {
109
+ this.reportStoreError(error, { context, options, key });
110
+ return next();
145
111
  }
146
- return this.handleStoreError(error, { context, options, key }, next);
112
+ setPipelineItem(context, RATE_LIMIT_ITEM_TOKEN, error);
113
+ throw new RateLimitExceededError({
114
+ key,
115
+ requestName: context.requestName,
116
+ msBeforeNext: error.msBeforeNext,
117
+ remainingPoints: error.remainingPoints,
118
+ limit: limiter.points,
119
+ points,
120
+ });
147
121
  }
148
- setPipelineItem(context, RATE_LIMIT_ITEM_TOKEN, result);
149
122
  return next();
150
123
  }
151
- /** Fail-open (default) or fail-closed when the backing store itself errors. */
152
- handleStoreError(error, check, next) {
124
+ /** Logs a failure of the backing store, and rethrows it unless failing open (default). */
125
+ reportStoreError(error, check) {
153
126
  const { context, options, key } = check;
154
127
  const message = error instanceof Error ? error.message : String(error);
155
- if (options.failOpen ?? true) {
156
- this.logger.warn?.(`Rate limiter store error for ${context.requestName} ` +
157
- `(key: ${key}); failing open: ${message}`, RateLimitBehavior.name);
158
- return next();
159
- }
160
- this.logger.error?.(`Rate limiter store error for ${context.requestName} ` +
161
- `(key: ${key}); failing closed: ${message}`, RateLimitBehavior.name);
162
- throw error;
128
+ const failOpen = options.failOpen ?? true;
129
+ this.logger[failOpen ? 'warn' : 'error']?.(`Rate limiter store error for ${context.requestName} ` +
130
+ `(key: ${key}); failing ${failOpen ? 'open' : 'closed'}: ${message}`, RateLimitBehavior.name);
131
+ if (!failOpen)
132
+ throw error;
163
133
  }
164
134
  /** Shallow-merges pipeline-level options over the constructor defaults. */
165
135
  resolveEffectiveOptions(options) {
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.behavior.js","sourceRoot":"","sources":["../src/rate-limit.behavior.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-limit.behavior.js","sourceRoot":"","sources":["../src/rate-limit.behavior.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cqrs-ddd/pipeline-rate-limit",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Rate limiting for @cqrs-ddd/pipeline, with keys partitioned by tenant, principal and operation",
5
5
  "author": "Aristotelis",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -50,16 +50,16 @@
50
50
  "access": "public"
51
51
  },
52
52
  "peerDependencies": {
53
- "@cqrs-ddd/pipeline": "^0.5.1"
53
+ "@cqrs-ddd/pipeline": "^0.6.0"
54
54
  },
55
55
  "devDependencies": {
56
+ "@cqrs-ddd/pipeline": "0.6.0",
56
57
  "@vitest/coverage-v8": "^5.0.5",
57
58
  "rate-limiter-flexible": "^11.2.3",
58
- "vitest": "^5.0.5",
59
- "@cqrs-ddd/pipeline": "0.5.1"
59
+ "vitest": "^5.0.5"
60
60
  },
61
61
  "dependencies": {
62
- "@cqrs-ddd/safe-stringify": "^0.5.1"
62
+ "@cqrs-ddd/safe-stringify": "^0.6.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsc -p tsconfig.build.json",