UNPKG

@batolye/bdk-core

Version:

Module to provide core utilities for BulusAtolyesi applications and services

108 lines (83 loc) 2.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.rateLimit = rateLimit; exports.countLimit = countLimit; var _errors = require("@feathersjs/errors"); var _limiter = require("limiter"); var _debug = _interopRequireDefault(require("debug")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const debug = (0, _debug.default)("batolye:bdk-core:service:hooks"); function rateLimit(options) { const limiter = new _limiter.RateLimiter(options.tokensPerInterval, options.interval); return function (hook) { if (hook.type !== "before") { throw new Error(`The 'rateLimit' hook should only be used as a 'before' hook.`); } const operation = hook.method; const service = hook.service.core_name; let rateLimit = true; if (options.operation && options.operation !== operation) { rateLimit = false; } if (options.service && options.service !== service) { rateLimit = false; } if (rateLimit) { debug(limiter.getTokensRemaining() + " remaining token for rateLimit hook on service " + service); if (!limiter.tryRemoveTokens(1)) { // if exceeded throw new _errors.TooManyRequests("Too many requests in a given amount of time (rate limiting) on service " + service, { translation: { key: "RATE_LIMITING" } }); } } return hook; }; } function countLimit(options) { return async function (hook) { if (hook.type !== "before") { throw new Error(`The 'countLimit' hook should only be used as a 'before' hook.`); } let app = hook.app; const customMax = typeof options.max === "function"; const max = customMax ? await options.max(hook) : options.max; // -1 means no limit if (max >= 0) { let count = options.max; // Either we build a count request using a service or the caller has its own count routine const customCount = typeof options.count === "function"; if (!customCount) { let service; if (typeof options.service === "function") { service = await options.service(hook); } else { service = app.core_getService(options.service, hook.service.zone); } // Indicate we'd only like to count let query = { $limit: 0 }; if (typeof options.query === "function") { Object.assign(query, options.query(hook)); } else { Object.assign(query, options.query); } count = service.find({ query }).total; } else { count = await options.count(hook); } if (count > max) { throw new _errors.Forbidden("Resource quota exceeded (count limiting) on service " + options.service, { translation: { key: "COUNT_LIMITING" } }); } } return hook; }; }