Skip to content

Commit

Permalink
feat: allowfor multiple throttler contexts
Browse files Browse the repository at this point in the history
This is a bit of something that I've wanted to do for a while and inspired by
[this pr][pr]. With the new appraoch, we're now able to let users define scales
at which they would like the throttling to work over, and let it work for any
number of configuratins, from a single 10 requests in 5 seconds to scales of
months, or milliseconds

BREAKING CHANGES:

It's worth noting there are quite a few breaking changes in this which will be
reflected in the changelog as well, but better to have multiple mentions in my
opinion

* ttl is now in milliseconds, not seconds, but there are time helper exposed
to ease the migration to that
* the module options is now either an array or an object with a `throttlers`
array property
* `@Throttle()` now takes in an object instead of two parameters, to allow for
setting multiple throttle contexts at once in a more readable manner
* `@ThrottleSkip()` now takes in an object with string boolean to say which
throttler should be skipped

pr: #1522

ref: #1369
ref: #1522
  • Loading branch information
jmcdo29 committed Jul 6, 2023
1 parent 701e8a5 commit 8668502
Show file tree
Hide file tree
Showing 17 changed files with 422 additions and 81 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"md5": "^2.2.1"
},
"devDependencies": {
"@apollo/server": "4.7.5",
"@changesets/cli": "2.26.2",
"@commitlint/cli": "17.6.6",
"@commitlint/config-angular": "17.6.6",
Expand All @@ -71,7 +72,6 @@
"@types/supertest": "2.0.12",
"@typescript-eslint/eslint-plugin": "5.61.0",
"@typescript-eslint/parser": "5.61.0",
"@apollo/server": "4.7.5",
"apollo-server-fastify": "3.12.0",
"conventional-changelog-cli": "3.0.0",
"cz-conventional-changelog": "3.3.0",
Expand All @@ -84,6 +84,7 @@
"jest": "29.6.1",
"lint-staged": "13.2.3",
"nodemon": "2.0.22",
"pactum": "^3.4.1",
"pinst": "3.0.0",
"prettier": "3.0.0",
"reflect-metadata": "0.1.13",
Expand Down
110 changes: 109 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './throttler.guard';
export * from './throttler.module';
export { getOptionsToken, getStorageToken } from './throttler.providers';
export * from './throttler.service';
export * from './utilities';
42 changes: 35 additions & 7 deletions src/throttler-module-options.interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExecutionContext, ModuleMetadata, Type } from '@nestjs/common/interfaces';
import { ThrottlerStorage } from './throttler-storage.interface';

export type Resolvable<T extends number | string | boolean> =
| T
Expand All @@ -7,14 +8,21 @@ export type Resolvable<T extends number | string | boolean> =
/**
* @publicApi
*/
export interface ThrottlerModuleOptions {
export interface ThrottlerOptions {
/**
* The name for the rate limit to be used.
* This can be left blank and it will be tracked as "default" internally.
* If this is set, it will be added to the return headers.
* e.g. x-ratelimit-remaining-long: 5
*/
name?: string;
/**
* The amount of requests that are allowed within the ttl's time window.
*/
limit?: Resolvable<number>;

/**
* The amount of seconds of how many requests are allowed within this time.
* The number of milliseconds the limit of requests are allowed
*/
ttl?: Resolvable<number>;

Expand All @@ -23,18 +31,38 @@ export interface ThrottlerModuleOptions {
*/
ignoreUserAgents?: RegExp[];

/**
* The storage class to use where all the record will be stored in.
*/
storage?: any;

/**
* A factory method to determine if throttling should be skipped.
* This can be based on the incoming context, or something like an env value.
*/
skipIf?: (context: ExecutionContext) => boolean;
}

/**
* @publicApi
*/
export type ThrottlerModuleOptions =
| Array<ThrottlerOptions>
| {
/**
* A factory method to determine if throttling should be skipped.
* This can be based on the incoming context, or something like an env value.
*/
skipIf?: (context: ExecutionContext) => boolean;
/**
* The user agents that should be ignored (checked against the User-Agent header).
*/
ignoreUserAgents?: RegExp[];
/**
* The storage class to use where all the record will be stored in.
*/
storage?: Type<ThrottlerStorage>;
/**
* The named throttlers to use
*/
throttlers: Array<ThrottlerOptions>;
};

/**
* @publicApi
*/
Expand Down
Loading

0 comments on commit 8668502

Please sign in to comment.