Skip to content

Commit e4cdfe0

Browse files
committed
feat: add errorFactory parameter to rejectOnQuotaExceededOrRecordUsage method
1 parent f17c7f0 commit e4cdfe0

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ const limiter = FirebaseFunctionsRateLimiter.mock()
191191
192192
- `isQuotaExceededOrRecordUsage(qualifier?: string)` — Checks if quota was exceed. If not — it records the call time in the appropriate backend.
193193
194-
- `rejectOnQuotaExceededOrRecordUsage(qualifier?: string)` — Checks if quota was exceed. If not — it records the call time in the appropriate backend and is rejected with *functions.https.HttpsException*. This particular exception can be caught when calling the firebase function directly (see https://firebase.google.com/docs/functions/callable).
194+
- `rejectOnQuotaExceededOrRecordUsage(qualifier?: string, errorFactory?: (configuration) => Error)` — Checks if quota was exceed. If not — it records the call time in the appropriate backend and is rejected with *functions.https.HttpsException*. This particular exception can be caught when calling the firebase function directly (see https://firebase.google.com/docs/functions/callable). When errorFactory is provided, it is used to obtain error that is thrown in case of exceeded limit.
195195
196196
- `isQuotaAlreadyExceeded(qualifier?: string)` — Checks if quota was exceed, but does not record a usage. If you use this, you must call isQuotaExceededOrRecordUsage() to record the usage.
197197

src/FirebaseFunctionsRateLimiter.integration.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { _, expect, uuid } from "./_test/test_environment";
77
import { FirebaseFunctionsRateLimiter } from "./FirebaseFunctionsRateLimiter";
88
import { mock } from "./FirebaseFunctionsRateLimiter.mock.integration.test";
99
import { PersistenceRecord } from "./persistence/PersistenceRecord";
10+
import { FirebaseFunctionsRateLimiterConfiguration } from "./FirebaseFunctionsRateLimiterConfiguration";
1011

1112
describe("FirebaseFunctionsRateLimiter", () => {
1213
//
@@ -177,6 +178,36 @@ describe("FirebaseFunctionsRateLimiter", () => {
177178
await expect(rateLimiter.rejectOnQuotaExceededOrRecordUsage(qualifier)).to.eventually.be
178179
.fulfilled;
179180
});
181+
182+
it("When error factory is provided, uses it to throw the error", async () => {
183+
const { rateLimiter } = mock(backend, {
184+
maxCalls: 1,
185+
});
186+
const qualifier = test.qualifierFactory();
187+
await rateLimiter.rejectOnQuotaExceededOrRecordUsage(qualifier);
188+
189+
const errorFactory = () => new Error("error-from-factory");
190+
await expect(
191+
rateLimiter.rejectOnQuotaExceededOrRecordUsage(qualifier, errorFactory),
192+
).to.eventually.be.rejectedWith(/error-from-factory/);
193+
});
194+
195+
it("Provides valid configuration to error factory", async () => {
196+
const { rateLimiter, config } = mock(backend, {
197+
maxCalls: 1,
198+
});
199+
const qualifier = test.qualifierFactory();
200+
await rateLimiter.rejectOnQuotaExceededOrRecordUsage(qualifier);
201+
202+
const errorFactory = configInErrorFactory => {
203+
expect(configInErrorFactory).to.deep.include(config);
204+
return new Error("error-from-factory");
205+
};
206+
207+
await expect(
208+
rateLimiter.rejectOnQuotaExceededOrRecordUsage(qualifier, errorFactory),
209+
).to.eventually.be.rejectedWith(/error-from-factory/);
210+
});
180211
});
181212

182213
[

src/FirebaseFunctionsRateLimiter.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,20 @@ export class FirebaseFunctionsRateLimiter {
124124
* is rejected with functions.https.HttpsError (this is the type of error that can be caught when
125125
* firebase function is called directly: see https://firebase.google.com/docs/functions/callable)
126126
*
127-
* @param qualifier — a string that identifies the limited resource accessor (for example the user id)
127+
* @param qualifier (optional) — a string that identifies the limited resource accessor (for example the user id)
128+
* @param errorFactory (optional) — when errorFactory is provided, it is used to obtain
129+
* error that is thrown in case of exceeded limit.
128130
*/
129-
public async rejectOnQuotaExceededOrRecordUsage(qualifier?: string): Promise<void> {
131+
public async rejectOnQuotaExceededOrRecordUsage(
132+
qualifier?: string,
133+
errorFactory?: (config: FirebaseFunctionsRateLimiterConfiguration) => Error,
134+
): Promise<void> {
130135
const isExceeded = await this.genericRateLimiter.isQuotaExceededOrRecordCall(
131136
qualifier || FirebaseFunctionsRateLimiter.DEFAULT_QUALIFIER,
132137
);
133138
if (isExceeded) {
134-
throw this.constructRejectionError(qualifier);
139+
if (errorFactory) throw errorFactory(this.getConfiguration());
140+
else throw this.constructRejectionError(qualifier);
135141
}
136142
}
137143

0 commit comments

Comments
 (0)