getta 0.2.3 → 0.4.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.
@@ -3,7 +3,7 @@ import _merge from "lodash/merge";
3
3
  import _castArray from "lodash/castArray";
4
4
  import "core-js/modules/es.promise.js";
5
5
  import md5 from "md5";
6
- import { CACHE_CONTROL_HEADER, DEFAULT_BODY_PARSER, DEFAULT_FETCH_TIMEOUT, DEFAULT_HEADERS, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RETRIES, DEFAULT_PATH_TEMPLATE_REGEX, DEFAULT_REQUEST_RETRY_WAIT, DELETE_METHOD, ETAG_HEADER, FETCH_METHODS, FETCH_TIMEOUT_ERROR, GET_METHOD, IF_NONE_MATCH_HEADER, INVALID_FETCH_METHOD_ERROR, JSON_FORMAT, LOCATION_HEADER, MAX_REDIRECTS_EXCEEDED_ERROR, MAX_RETRIES_EXCEEDED_ERROR, MISSING_BASE_PATH_ERROR, NOT_FOUND_STATUS_CODE, NOT_MODIFIED_STATUS_CODE, OPTIONAL_PATH_TEMPLATE_REGEX, POST_METHOD, PUT_METHOD, REDIRECTION_REPSONSE, RESOURCE_NOT_FOUND_ERROR, SERVER_ERROR_REPSONSE } from "./constants";
6
+ import { CACHE_CONTROL_HEADER, DEFAULT_BODY_PARSER, DEFAULT_FETCH_TIMEOUT, DEFAULT_HEADERS, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RETRIES, DEFAULT_PATH_TEMPLATE_REGEX, DEFAULT_RATE_LIMIT, DEFAULT_REQUEST_RETRY_WAIT, DELETE_METHOD, ETAG_HEADER, FETCH_METHODS, FETCH_TIMEOUT_ERROR, GET_METHOD, IF_NONE_MATCH_HEADER, INVALID_FETCH_METHOD_ERROR, JSON_FORMAT, LOCATION_HEADER, MAX_REDIRECTS_EXCEEDED_ERROR, MAX_RETRIES_EXCEEDED_ERROR, MISSING_BASE_PATH_ERROR, NOT_FOUND_STATUS_CODE, NOT_MODIFIED_STATUS_CODE, OPTIONAL_PATH_TEMPLATE_REGEX, POST_METHOD, PUT_METHOD, REDIRECTION_REPSONSE, REQUEST_SENT, RESOURCE_NOT_FOUND_ERROR, RESPONSE_RECEIVED, SERVER_ERROR_REPSONSE } from "./constants";
7
7
  import buildEndpoint from "./helpers/build-endpoint";
8
8
  import defaultPathTemplateCallback from "./helpers/default-path-template-callback";
9
9
  import delay from "./helpers/delay";
@@ -23,6 +23,8 @@ export class Getta {
23
23
 
24
24
  _defineProperty(this, "_headers", void 0);
25
25
 
26
+ _defineProperty(this, "_log", void 0);
27
+
26
28
  _defineProperty(this, "_maxRedirects", void 0);
27
29
 
28
30
  _defineProperty(this, "_maxRetries", void 0);
@@ -33,8 +35,18 @@ export class Getta {
33
35
 
34
36
  _defineProperty(this, "_pathTemplateRegExp", void 0);
35
37
 
38
+ _defineProperty(this, "_performance", void 0);
39
+
36
40
  _defineProperty(this, "_queryParams", void 0);
37
41
 
42
+ _defineProperty(this, "_rateLimitCount", 0);
43
+
44
+ _defineProperty(this, "_rateLimitedRequestQueue", []);
45
+
46
+ _defineProperty(this, "_rateLimitPerSecond", void 0);
47
+
48
+ _defineProperty(this, "_rateLimitTimer", null);
49
+
38
50
  _defineProperty(this, "_requestRetryWait", void 0);
39
51
 
40
52
  _defineProperty(this, "_requestTracker", {
@@ -51,12 +63,15 @@ export class Getta {
51
63
  enableConditionalRequests = true,
52
64
  fetchTimeout = DEFAULT_FETCH_TIMEOUT,
53
65
  headers,
66
+ log,
54
67
  maxRedirects = DEFAULT_MAX_REDIRECTS,
55
68
  maxRetries = DEFAULT_MAX_RETRIES,
56
69
  optionalPathTemplateRegExp = OPTIONAL_PATH_TEMPLATE_REGEX,
57
70
  pathTemplateCallback = defaultPathTemplateCallback,
58
71
  pathTemplateRegExp = DEFAULT_PATH_TEMPLATE_REGEX,
72
+ performance,
59
73
  queryParams = {},
74
+ rateLimitPerSecond = DEFAULT_RATE_LIMIT,
60
75
  requestRetryWait = DEFAULT_REQUEST_RETRY_WAIT,
61
76
  streamReader = JSON_FORMAT
62
77
  } = options;
@@ -73,12 +88,15 @@ export class Getta {
73
88
  this._headers = { ...DEFAULT_HEADERS,
74
89
  ...(headers || {})
75
90
  };
91
+ this._log = log;
76
92
  this._maxRedirects = maxRedirects;
77
93
  this._maxRetries = maxRetries;
78
94
  this._optionalPathTemplateRegExp = optionalPathTemplateRegExp;
79
95
  this._pathTemplateCallback = pathTemplateCallback;
80
96
  this._pathTemplateRegExp = pathTemplateRegExp;
97
+ this._performance = performance;
81
98
  this._queryParams = queryParams;
99
+ this._rateLimitPerSecond = rateLimitPerSecond;
82
100
  this._requestRetryWait = requestRetryWait;
83
101
  this._streamReader = streamReader;
84
102
  }
@@ -101,23 +119,29 @@ export class Getta {
101
119
  } = {}) => this[requestMethod !== null && requestMethod !== void 0 ? requestMethod : method](path, _merge({}, rest, requestRest));
102
120
  }
103
121
 
104
- async delete(path, options = {}) {
105
- return this._delete(path, options);
122
+ async delete(path, options = {}, context) {
123
+ return this._delete(path, options, context);
106
124
  }
107
125
 
108
- async get(path, options = {}) {
109
- return this._get(path, options);
126
+ async get(path, options = {}, context) {
127
+ return this._get(path, options, context);
110
128
  }
111
129
 
112
- async post(path, options) {
130
+ async post(path, options, context) {
113
131
  return this._request(path, { ...options,
114
132
  method: POST_METHOD
115
- });
133
+ }, context);
116
134
  }
117
135
 
118
- async put(path, options) {
136
+ async put(path, options, context) {
119
137
  return this._request(path, { ...options,
120
138
  method: PUT_METHOD
139
+ }, context);
140
+ }
141
+
142
+ _addRequestToRateLimitedQueue(endpoint, options) {
143
+ return new Promise(resolve => {
144
+ this._rateLimitedRequestQueue.push([resolve, endpoint, options]);
121
145
  });
122
146
  }
123
147
 
@@ -168,7 +192,7 @@ export class Getta {
168
192
  pathTemplateData,
169
193
  queryParams = {},
170
194
  ...rest
171
- }) {
195
+ }, context) {
172
196
  const endpoint = buildEndpoint(this._basePath, path, {
173
197
  optionalPathTemplateRegExp: this._optionalPathTemplateRegExp,
174
198
  pathTemplateCallback: this._pathTemplateCallback,
@@ -191,20 +215,66 @@ export class Getta {
191
215
  },
192
216
  method: DELETE_METHOD,
193
217
  ...rest
194
- });
218
+ }, context);
195
219
  }
196
220
 
197
221
  async _fetch(endpoint, {
198
222
  redirects,
199
223
  retries,
200
224
  ...rest
201
- }) {
225
+ }, context = {}) {
202
226
  try {
203
227
  return new Promise(async (resolve, reject) => {
228
+ var _this$_log, _this$_log2;
229
+
204
230
  const fetchTimer = setTimeout(() => {
205
231
  reject(new Error(`${FETCH_TIMEOUT_ERROR} ${this._fetchTimeout}ms.`));
206
232
  }, this._fetchTimeout);
233
+
234
+ this._rateLimit();
235
+
236
+ if (!(this._rateLimitCount < this._rateLimitPerSecond)) {
237
+ resolve(await this._addRequestToRateLimitedQueue(endpoint, {
238
+ redirects,
239
+ retries,
240
+ ...rest
241
+ }));
242
+ return;
243
+ }
244
+
245
+ const startTime = this._performance.now();
246
+
247
+ (_this$_log = this._log) === null || _this$_log === void 0 ? void 0 : _this$_log.call(this, REQUEST_SENT, {
248
+ context: {
249
+ redirects,
250
+ retries,
251
+ url: endpoint,
252
+ ...rest,
253
+ ...context
254
+ },
255
+ stats: {
256
+ startTime
257
+ }
258
+ });
207
259
  const res = await fetch(endpoint, rest);
260
+
261
+ const endTime = this._performance.now();
262
+
263
+ const duration = endTime - startTime;
264
+ (_this$_log2 = this._log) === null || _this$_log2 === void 0 ? void 0 : _this$_log2.call(this, RESPONSE_RECEIVED, {
265
+ context: {
266
+ redirects,
267
+ retries,
268
+ url: endpoint,
269
+ ...rest,
270
+ ...context
271
+ },
272
+ stats: {
273
+ duration,
274
+ endTime,
275
+ startTime
276
+ }
277
+ });
208
278
  clearTimeout(fetchTimer);
209
279
  const {
210
280
  headers,
@@ -218,6 +288,7 @@ export class Getta {
218
288
  status,
219
289
  ...rest
220
290
  }));
291
+ return;
221
292
  }
222
293
 
223
294
  if (responseGroup === SERVER_ERROR_REPSONSE) {
@@ -225,27 +296,16 @@ export class Getta {
225
296
  retries,
226
297
  ...rest
227
298
  }));
299
+ return;
228
300
  }
229
301
 
230
302
  const fetchRes = res;
231
- const resClone = res.clone();
232
303
 
233
304
  try {
234
305
  fetchRes.data = res.body ? this._bodyParser(await res[this._streamReader]()) : undefined;
235
306
  resolve(fetchRes);
236
307
  } catch (e) {
237
- try {
238
- if (this._streamReader === "json" && res.body) {
239
- const fetchResClone = resClone;
240
- const text = await resClone.text();
241
- fetchResClone.data = JSON.parse(text);
242
- resolve(fetchResClone);
243
- } else {
244
- reject([e, new Error(`Unable to ${rest.method} ${endpoint} due to previous error`)]);
245
- }
246
- } catch {
247
- reject([e, new Error(`Unable to ${rest.method} ${endpoint} due to previous error`)]);
248
- }
308
+ reject([e, new Error(`Unable to ${rest.method} ${endpoint} due to previous error`)]);
249
309
  }
250
310
  });
251
311
  } catch (error) {
@@ -300,7 +360,7 @@ export class Getta {
300
360
  headers = {},
301
361
  pathTemplateData,
302
362
  queryParams = {}
303
- }) {
363
+ }, context) {
304
364
  const endpoint = buildEndpoint(this._basePath, path, {
305
365
  optionalPathTemplateRegExp: this._optionalPathTemplateRegExp,
306
366
  pathTemplateCallback: this._pathTemplateCallback,
@@ -339,7 +399,7 @@ export class Getta {
339
399
  ...headers
340
400
  },
341
401
  method: GET_METHOD
342
- }));
402
+ }, context));
343
403
  }
344
404
 
345
405
  async _getResolve(requestHash, res) {
@@ -381,6 +441,29 @@ export class Getta {
381
441
  return res;
382
442
  }
383
443
 
444
+ _rateLimit() {
445
+ if (!this._rateLimitTimer) {
446
+ this._rateLimitTimer = setTimeout(() => {
447
+ this._rateLimitTimer = null;
448
+ this._rateLimitCount = 0;
449
+
450
+ if (this._rateLimitedRequestQueue.length) {
451
+ this._releaseRateLimitedRequestQueue();
452
+ }
453
+ }, 1000);
454
+ }
455
+
456
+ this._rateLimitCount += 1;
457
+ }
458
+
459
+ _releaseRateLimitedRequestQueue() {
460
+ this._rateLimitedRequestQueue.forEach(async ([resolve, endpoint, options]) => {
461
+ resolve(await this._fetch(endpoint, options));
462
+ });
463
+
464
+ this._rateLimitedRequestQueue = [];
465
+ }
466
+
384
467
  async _request(path, {
385
468
  body,
386
469
  headers,
@@ -388,7 +471,7 @@ export class Getta {
388
471
  pathTemplateData,
389
472
  queryParams,
390
473
  ...rest
391
- }) {
474
+ }, context) {
392
475
  const endpoint = buildEndpoint(this._basePath, path, {
393
476
  optionalPathTemplateRegExp: this._optionalPathTemplateRegExp,
394
477
  pathTemplateCallback: this._pathTemplateCallback,
@@ -405,7 +488,7 @@ export class Getta {
405
488
  },
406
489
  method,
407
490
  ...rest
408
- });
491
+ }, context);
409
492
  }
410
493
 
411
494
  _resolvePendingRequests(requestHash, responseData) {
@@ -20,6 +20,7 @@ export declare const DEFAULT_MAX_REDIRECTS: 5;
20
20
  export declare const DEFAULT_MAX_RETRIES: 3;
21
21
  export declare const DEFAULT_PATH_TEMPLATE_REGEX: RegExp;
22
22
  export declare const OPTIONAL_PATH_TEMPLATE_REGEX: RegExp;
23
+ export declare const DEFAULT_RATE_LIMIT = 50;
23
24
  export declare const DEFAULT_REQUEST_RETRY_WAIT = 100;
24
25
  export declare const MISSING_BASE_PATH_ERROR = "Getta expected to receive 'basePath' in the constructor options,\n but recevied undefined.";
25
26
  export declare const MAX_REDIRECTS_EXCEEDED_ERROR = "The request exceeded the maximum number of redirects, which is";
@@ -44,4 +45,6 @@ export declare const ETAG_HEADER: "ETag";
44
45
  export declare const LOCATION_HEADER: "Location";
45
46
  export declare const IF_NONE_MATCH_HEADER: "If-None-Match";
46
47
  export declare const CACHE_CONTROL_HEADER: "Cache-Control";
48
+ export declare const REQUEST_SENT: "request_sent";
49
+ export declare const RESPONSE_RECEIVED: "response_received";
47
50
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,eAAO,MAAM,mBAAmB,eAAyB,CAAC;AAC1D,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,YAAsB,CAAC;AACpD,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAE3C,eAAO,MAAM,cAAc;;;;;;CAM1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,SAAU,WAAW,gBAAS,CAAC;AAC/D,eAAO,MAAM,qBAAqB,MAAgB,CAAC;AACnD,eAAO,MAAM,eAAe;;CAAyC,CAAC;AACtE,eAAO,MAAM,qBAAqB,GAAa,CAAC;AAChD,eAAO,MAAM,mBAAmB,GAAa,CAAC;AAC9C,eAAO,MAAM,2BAA2B,QAAmD,CAAC;AAC5F,eAAO,MAAM,4BAA4B,QAAyB,CAAC;AACnE,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,uBAAuB,gGACV,CAAC;AAE3B,eAAO,MAAM,4BAA4B,mEAAmE,CAAC;AAE7G,eAAO,MAAM,0BAA0B,iEAAiE,CAAC;AAEzG,eAAO,MAAM,0BAA0B,6EAA6E,CAAC;AAErH,eAAO,MAAM,wBAAwB,iDAAiD,CAAC;AAEvF,eAAO,MAAM,mBAAmB,+DAA+D,CAAC;AAEhG,eAAO,MAAM,UAAU,OAAiB,CAAC;AACzC,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,OAAiB,CAAC;AACzC,eAAO,MAAM,aAAa,UAAoB,CAAC;AAE/C,eAAO,MAAM,aAAa,uCAAuD,CAAC;AAElF,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAC3D,eAAO,MAAM,mBAAmB,cAAwB,CAAC;AACzD,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,eAAyB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,eAAyB,CAAC;AAE5D,eAAO,MAAM,wBAAwB,KAAe,CAAC;AACrD,eAAO,MAAM,qBAAqB,KAAe,CAAC;AAElD,eAAO,MAAM,aAAa,UAAoB,CAAC;AAC/C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,eAAe,YAAsB,CAAC;AACnD,eAAO,MAAM,oBAAoB,iBAA2B,CAAC;AAC7D,eAAO,MAAM,oBAAoB,iBAA2B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,eAAO,MAAM,mBAAmB,eAAyB,CAAC;AAC1D,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,YAAsB,CAAC;AACpD,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAE3C,eAAO,MAAM,cAAc;;;;;;CAM1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,SAAU,WAAW,gBAAS,CAAC;AAC/D,eAAO,MAAM,qBAAqB,MAAgB,CAAC;AACnD,eAAO,MAAM,eAAe;;CAAyC,CAAC;AACtE,eAAO,MAAM,qBAAqB,GAAa,CAAC;AAChD,eAAO,MAAM,mBAAmB,GAAa,CAAC;AAC9C,eAAO,MAAM,2BAA2B,QAAmD,CAAC;AAC5F,eAAO,MAAM,4BAA4B,QAAyB,CAAC;AACnE,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,uBAAuB,gGACV,CAAC;AAE3B,eAAO,MAAM,4BAA4B,mEAAmE,CAAC;AAE7G,eAAO,MAAM,0BAA0B,iEAAiE,CAAC;AAEzG,eAAO,MAAM,0BAA0B,6EAA6E,CAAC;AAErH,eAAO,MAAM,wBAAwB,iDAAiD,CAAC;AAEvF,eAAO,MAAM,mBAAmB,+DAA+D,CAAC;AAEhG,eAAO,MAAM,UAAU,OAAiB,CAAC;AACzC,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,OAAiB,CAAC;AACzC,eAAO,MAAM,aAAa,UAAoB,CAAC;AAE/C,eAAO,MAAM,aAAa,uCAAuD,CAAC;AAElF,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAC3D,eAAO,MAAM,mBAAmB,cAAwB,CAAC;AACzD,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,eAAyB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,eAAyB,CAAC;AAE5D,eAAO,MAAM,wBAAwB,KAAe,CAAC;AACrD,eAAO,MAAM,qBAAqB,KAAe,CAAC;AAElD,eAAO,MAAM,aAAa,UAAoB,CAAC;AAC/C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,eAAe,YAAsB,CAAC;AACnD,eAAO,MAAM,oBAAoB,iBAA2B,CAAC;AAC7D,eAAO,MAAM,oBAAoB,iBAA2B,CAAC;AAE7D,eAAO,MAAM,YAAY,gBAA0B,CAAC;AACpD,eAAO,MAAM,iBAAiB,qBAA+B,CAAC"}
@@ -9,25 +9,32 @@ export declare class Getta {
9
9
  private _conditionalRequestsEnabled;
10
10
  private _fetchTimeout;
11
11
  private _headers;
12
+ private _log;
12
13
  private _maxRedirects;
13
14
  private _maxRetries;
14
15
  private _optionalPathTemplateRegExp;
15
16
  private _pathTemplateCallback;
16
17
  private _pathTemplateRegExp;
18
+ private _performance;
17
19
  private _queryParams;
20
+ private _rateLimitCount;
21
+ private _rateLimitedRequestQueue;
22
+ private _rateLimitPerSecond;
23
+ private _rateLimitTimer;
18
24
  private _requestRetryWait;
19
25
  private _requestTracker;
20
26
  private _streamReader;
21
27
  constructor(options: ConstructorOptions);
22
28
  get cache(): Cachemap | undefined;
23
29
  createShortcut(name: string, path: string, { method, ...rest }: Required<RequestOptions, "method">): void;
24
- delete(path: string, options?: Omit<RequestOptions, "method">): Promise<FetchResponse<PlainObject>>;
25
- get(path: string, options?: Omit<RequestOptions, "method">): Promise<FetchResponse<PlainObject> | {
30
+ delete(path: string, options?: Omit<RequestOptions, "method">, context?: PlainObject): Promise<FetchResponse<PlainObject>>;
31
+ get(path: string, options?: Omit<RequestOptions, "method">, context?: PlainObject): Promise<FetchResponse<PlainObject> | {
26
32
  data: PlainObject | undefined;
27
33
  headers: Headers;
28
34
  }>;
29
- post(path: string, options: Omit<Required<RequestOptions, "body">, "method">): Promise<FetchResponse<PlainObject>>;
30
- put(path: string, options: Omit<Required<RequestOptions, "body">, "methood">): Promise<FetchResponse<PlainObject>>;
35
+ post(path: string, options: Omit<Required<RequestOptions, "body">, "method">, context?: PlainObject): Promise<FetchResponse<PlainObject>>;
36
+ put(path: string, options: Omit<Required<RequestOptions, "body">, "methood">, context?: PlainObject): Promise<FetchResponse<PlainObject>>;
37
+ private _addRequestToRateLimitedQueue;
31
38
  private _cacheEntryDelete;
32
39
  private _cacheEntryGet;
33
40
  private _cacheEntryHas;
@@ -38,6 +45,8 @@ export declare class Getta {
38
45
  private _fetchRetryHandler;
39
46
  private _get;
40
47
  private _getResolve;
48
+ private _rateLimit;
49
+ private _releaseRateLimitedRequestQueue;
41
50
  private _request;
42
51
  private _resolvePendingRequests;
43
52
  private _setPendingRequest;
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,QAA0B,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAQ,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAIjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAoCzC,OAAO,EACL,kBAAkB,EAGlB,aAAa,EAIb,cAAc,EAEd,kBAAkB,EAClB,SAAS,EAEV,MAAM,SAAS,CAAC;AAEjB,qBAAa,KAAK;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAW;IAC1B,OAAO,CAAC,2BAA2B,CAAU;IAC7C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,2BAA2B,CAAS;IAC5C,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAsD;IAC7E,OAAO,CAAC,aAAa,CAAe;gBAExB,OAAO,EAAE,kBAAkB;IAsCvC,IAAI,KAAK,IAAI,QAAQ,GAAG,SAAS,CAEhC;IAEM,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC;IAW5F,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAM;IAIjE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAM;;;;IAI9D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAI5E,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC;YAI3E,iBAAiB;YAUjB,cAAc;YAUd,cAAc;YAUd,cAAc;YAUd,OAAO;YA0BP,MAAM;YA4DN,qBAAqB;YAiBrB,kBAAkB;YAYlB,IAAI;YAsCJ,WAAW;YAkCX,QAAQ;IAoBtB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,aAAa;CAStB;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,SAAS,iCAS5G"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,QAA0B,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAQ,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAIjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuCzC,OAAO,EACL,kBAAkB,EAGlB,aAAa,EAMb,cAAc,EAGd,kBAAkB,EAClB,SAAS,EAEV,MAAM,SAAS,CAAC;AAEjB,qBAAa,KAAK;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAW;IAC1B,OAAO,CAAC,2BAA2B,CAAU;IAC7C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,2BAA2B,CAAS;IAC5C,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,wBAAwB,CAAoB;IACpD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAsD;IAC7E,OAAO,CAAC,aAAa,CAAe;gBAExB,OAAO,EAAE,kBAAkB;IA4CvC,IAAI,KAAK,IAAI,QAAQ,GAAG,SAAS,CAEhC;IAEM,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC;IAW5F,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAM,EAAE,OAAO,CAAC,EAAE,WAAW;IAIxF,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAM,EAAE,OAAO,CAAC,EAAE,WAAW;;;;IAIrF,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW;IAInG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW;IAIhH,OAAO,CAAC,6BAA6B;YAMvB,iBAAiB;YAUjB,cAAc;YAUd,cAAc;YAUd,cAAc;YAUd,OAAO;YA+BP,MAAM;YA8EN,qBAAqB;YAiBrB,kBAAkB;YAYlB,IAAI;YAuCJ,WAAW;IAkCzB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,+BAA+B;YASzB,QAAQ;IAyBtB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,aAAa;CAStB;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,SAAS,iCAS5G"}
@@ -13,12 +13,15 @@ export interface ConstructorOptions {
13
13
  enableConditionalRequests?: boolean;
14
14
  fetchTimeout?: number;
15
15
  headers?: StringObject;
16
+ log?: Log;
16
17
  maxRedirects?: number;
17
18
  maxRetries?: number;
18
19
  optionalPathTemplateRegExp?: RegExp;
19
20
  pathTemplateCallback?: PathTemplateCallback;
20
21
  pathTemplateRegExp?: RegExp;
22
+ performance: Performance;
21
23
  queryParams?: PlainObject;
24
+ rateLimitPerSecond?: number;
22
25
  requestRetryWait?: number;
23
26
  streamReader?: StreamReader;
24
27
  }
@@ -34,6 +37,11 @@ export interface FetchResponse<Resource = PlainObject> extends ResponseDataWithE
34
37
  export interface FetchRedirectHandlerOptions extends FetchOptions {
35
38
  status: number;
36
39
  }
40
+ export declare type Log = (message: string, data: PlainObject, logLevel?: LogLevel) => void;
41
+ export declare type LogLevel = "error" | "warn" | "info" | "http" | "verbose" | "debug" | "silly";
42
+ export interface Performance {
43
+ now(): number;
44
+ }
37
45
  export interface RequestOptions {
38
46
  body?: BodyInit;
39
47
  headers?: StringObject;
@@ -41,6 +49,7 @@ export interface RequestOptions {
41
49
  pathTemplateData?: StringObject;
42
50
  queryParams?: PlainObject;
43
51
  }
52
+ export declare type RequestQueue = [(value: FetchResponse) => void, string, FetchOptions][];
44
53
  export interface ResponseDataWithErrors<Resource = PlainObject> {
45
54
  data?: Resource;
46
55
  errors?: Error[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,oBAAY,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE5D,oBAAY,YAAY,GAAG,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjF,oBAAY,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;KACzD,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;CACvF,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa,CAAC,QAAQ,GAAG,WAAW,CAAE,SAAQ,sBAAsB,CAAC,QAAQ,CAAC,EAAE,QAAQ;CAAG;AAE5G,MAAM,WAAW,2BAA4B,SAAQ,YAAY;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB,CAAC,QAAQ,GAAG,WAAW;IAC5D,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB;AAED,oBAAY,oBAAoB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,KAAK,MAAM,CAAC;AAE5G,oBAAY,sBAAsB,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;AAEjF,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;CAC7D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getta",
3
- "version": "0.2.3",
3
+ "version": "0.4.0",
4
4
  "description": "An isomorphic rest client based on the Fetch API.",
5
5
  "keywords": [
6
6
  "api-client",
package/src/constants.ts CHANGED
@@ -21,6 +21,7 @@ export const DEFAULT_MAX_REDIRECTS = 5 as const;
21
21
  export const DEFAULT_MAX_RETRIES = 3 as const;
22
22
  export const DEFAULT_PATH_TEMPLATE_REGEX = /({type})|({id})|({id,\+})|({brief\|standard})/g;
23
23
  export const OPTIONAL_PATH_TEMPLATE_REGEX = /({[a-zA-Z0-9_]+\?})/g;
24
+ export const DEFAULT_RATE_LIMIT = 50;
24
25
  export const DEFAULT_REQUEST_RETRY_WAIT = 100;
25
26
 
26
27
  export const MISSING_BASE_PATH_ERROR = `Getta expected to receive 'basePath' in the constructor options,
@@ -57,3 +58,6 @@ export const ETAG_HEADER = "ETag" as const;
57
58
  export const LOCATION_HEADER = "Location" as const;
58
59
  export const IF_NONE_MATCH_HEADER = "If-None-Match" as const;
59
60
  export const CACHE_CONTROL_HEADER = "Cache-Control" as const;
61
+
62
+ export const REQUEST_SENT = "request_sent" as const;
63
+ export const RESPONSE_RECEIVED = "response_received" as const;
package/src/main.test.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { StringObject } from "@repodog/types";
2
2
  import fetchMock, { MockRequest } from "fetch-mock";
3
3
  import md5 from "md5";
4
+ import { performance } from "perf_hooks";
4
5
  import { PRD_136_7317 } from "./__tests__/data";
5
6
  import {
6
7
  basePath,
@@ -33,7 +34,7 @@ import { ResponseDataWithErrors, ShortcutProperties } from "./types";
33
34
  describe("Getta", () => {
34
35
  describe("constructor", () => {
35
36
  it("SHOULD return an instance of the Getta class", () => {
36
- const restClient = createRestClient({ basePath, cache: getCache() });
37
+ const restClient = createRestClient({ basePath, cache: getCache(), performance });
37
38
  expect(restClient).toBeInstanceOf(Getta);
38
39
  });
39
40
  });
@@ -44,7 +45,7 @@ describe("Getta", () => {
44
45
 
45
46
  beforeAll(() => {
46
47
  restClient = createRestClient<"getProduct">(
47
- { basePath, cache: getCache() },
48
+ { basePath, cache: getCache(), performance },
48
49
  {
49
50
  getProduct: [
50
51
  defaultPath,
@@ -397,7 +398,7 @@ describe("Getta", () => {
397
398
 
398
399
  beforeAll(() => {
399
400
  restClient = createRestClient<"postProduct">(
400
- { basePath, cache: getCache() },
401
+ { basePath, cache: getCache(), performance },
401
402
  {
402
403
  postProduct: [
403
404
  defaultPath,
@@ -483,7 +484,7 @@ describe("Getta", () => {
483
484
 
484
485
  beforeAll(() => {
485
486
  restClient = createRestClient<"deleteProduct">(
486
- { basePath, cache: getCache() },
487
+ { basePath, cache: getCache(), performance },
487
488
  {
488
489
  deleteProduct: [
489
490
  defaultPath,
@@ -589,7 +590,7 @@ describe("Getta", () => {
589
590
 
590
591
  beforeAll(() => {
591
592
  restClient = createRestClient<"putProduct">(
592
- { basePath, cache: getCache() },
593
+ { basePath, cache: getCache(), performance },
593
594
  {
594
595
  putProduct: [
595
596
  defaultPath,
@@ -657,4 +658,44 @@ describe("Getta", () => {
657
658
  });
658
659
  });
659
660
  });
661
+
662
+ describe("rate limiting", () => {
663
+ let restClient: Getta;
664
+
665
+ beforeAll(() => {
666
+ restClient = createRestClient({ basePath, performance });
667
+ });
668
+
669
+ describe("WHEN the number of requests per second exceeds rateLimitPerSecond", () => {
670
+ beforeAll(async () => {
671
+ const requestKeys = [...Array(55).keys()];
672
+
673
+ requestKeys.forEach(key => {
674
+ mockRequest(`product/${key}`, {}, {}, ({ endpoint, ...rest }) => {
675
+ fetchMock.get(endpoint, rest);
676
+ });
677
+ });
678
+
679
+ // @ts-ignore
680
+ restClient._addRequestToRateLimitedQueue = jest
681
+ .fn()
682
+ .mockResolvedValue({ data: {}, headers: new Headers(), status: 200 });
683
+
684
+ await Promise.all(requestKeys.map(key => restClient.get(`product/${key}`)));
685
+ });
686
+
687
+ afterAll(async () => {
688
+ await tearDownTest({ fetchMock, restClient });
689
+ });
690
+
691
+ it("SHOULD call fetch one less than the rate limit", () => {
692
+ expect(fetchMock.calls().length).toBe(49);
693
+ });
694
+
695
+ it("SHOULD add the excess requests to rateLimitedRequestQueue", async () => {
696
+ // @ts-ignore
697
+ expect(restClient._addRequestToRateLimitedQueue).toHaveBeenCalledTimes(6);
698
+ });
699
+ });
700
+ });
660
701
  });