api-def 0.8.2 → 0.8.4

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.
package/cjs/ApiTypes.d.ts CHANGED
@@ -21,10 +21,16 @@ interface QueryHandling {
21
21
  parse: QueryParse;
22
22
  stringify: QueryStringify;
23
23
  }
24
+ export interface RetryOptions {
25
+ maxAttempts: number;
26
+ shouldRetry?: (error: Error) => boolean;
27
+ minDelay?: number;
28
+ maxDelay?: number;
29
+ }
24
30
  export interface BaseRequestConfig {
25
31
  cache?: number | boolean;
26
32
  lock?: RequestLock;
27
- retry?: number | false;
33
+ retry?: number | false | RetryOptions;
28
34
  headers?: Readonly<Headers>;
29
35
  acceptableStatus?: AcceptableStatus[];
30
36
  /**
@@ -13,6 +13,7 @@ export interface RequestError extends Error {
13
13
  isRequestError: true;
14
14
  response: ApiResponse | undefined | null;
15
15
  code: string;
16
+ attempts: number;
16
17
  }
17
18
  export declare const isRequestError: (error: Error) => error is RequestError;
18
19
  export interface RequestErrorConfig {
@@ -20,6 +20,7 @@ var convertToRequestError = function (config) {
20
20
  response: response,
21
21
  code: code,
22
22
  isRequestError: true,
23
+ attempts: context.stats.attempt,
23
24
  request: {
24
25
  url: context.getRequestUrl().href,
25
26
  query: context.computedConfig.queryObject,
package/cjs/Requester.js CHANGED
@@ -48,7 +48,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
48
48
  };
49
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
50
  exports.submit = void 0;
51
- var ApiUtils = require("./ApiUtils");
52
51
  var ApiUtils_1 = require("./ApiUtils");
53
52
  var RequestContext_1 = require("./RequestContext");
54
53
  var ApiConstants_1 = require("./ApiConstants");
@@ -105,29 +104,38 @@ var submit = function (host, config, mocking) { return __awaiter(void 0, void 0,
105
104
  });
106
105
  }); };
107
106
  exports.submit = submit;
107
+ var parseRetryOptions = function (retryConfig) {
108
+ if (retryConfig && typeof retryConfig === "object") {
109
+ return retryConfig;
110
+ }
111
+ if (typeof retryConfig === "number") {
112
+ return { maxAttempts: retryConfig };
113
+ }
114
+ return { maxAttempts: 0 };
115
+ };
108
116
  var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0, function () {
109
- var beforeSendEventResult, maxRetries, retryOpts, performRequest, response;
110
- var _a;
111
- return __generator(this, function (_b) {
112
- switch (_b.label) {
117
+ var beforeSendEventResult, retryOptions, internalRetryOptions, performRequest, response;
118
+ var _a, _b, _c;
119
+ return __generator(this, function (_d) {
120
+ switch (_d.label) {
113
121
  case 0: return [4 /*yield*/, context.triggerEvent(ApiConstants_1.RequestEvent.BeforeSend)];
114
122
  case 1:
115
- beforeSendEventResult = _b.sent();
123
+ beforeSendEventResult = _d.sent();
116
124
  if (beforeSendEventResult &&
117
125
  beforeSendEventResult.type === ApiConstants_1.EventResultType.Respond) {
118
126
  return [2 /*return*/, (context.response = beforeSendEventResult.response)];
119
127
  }
120
- maxRetries = ((_a = context.computedConfig) === null || _a === void 0 ? void 0 : _a.retry) || 0;
121
- retryOpts = {
122
- retries: maxRetries,
128
+ retryOptions = parseRetryOptions((_a = context.computedConfig) === null || _a === void 0 ? void 0 : _a.retry);
129
+ internalRetryOptions = {
130
+ retries: retryOptions.maxAttempts,
123
131
  // assume most users won't want to tune the delay between retries
124
- minTimeout: 1 * 1000,
125
- maxTimeout: 5 * 1000,
132
+ minTimeout: (_b = retryOptions.minDelay) !== null && _b !== void 0 ? _b : 200,
133
+ maxTimeout: (_c = retryOptions.maxDelay) !== null && _c !== void 0 ? _c : 1000,
126
134
  randomize: true,
127
135
  };
128
136
  context.stats.attempt = 0;
129
137
  performRequest = function (fnBail, attemptCount) { return __awaiter(void 0, void 0, void 0, function () {
130
- var _a, promise, canceler, response_1, parsedResponse, rawError_1, error, errorEventResult, shouldNaturallyRetry, forceRetry, unrecoverableErrorEventResult;
138
+ var _a, promise, canceler, response_1, parsedResponse, rawError_1, error, errorEventResult, forceRetry, unrecoverableErrorEventResult;
131
139
  return __generator(this, function (_b) {
132
140
  switch (_b.label) {
133
141
  case 0:
@@ -169,14 +177,14 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
169
177
  if ((errorEventResult === null || errorEventResult === void 0 ? void 0 : errorEventResult.type) === ApiConstants_1.EventResultType.Respond) {
170
178
  return [2 /*return*/, errorEventResult.response];
171
179
  }
172
- shouldNaturallyRetry = ApiUtils.isNetworkError(error);
173
- if (shouldNaturallyRetry) {
174
- throw error;
175
- }
176
180
  forceRetry = (errorEventResult === null || errorEventResult === void 0 ? void 0 : errorEventResult.type) === ApiConstants_1.EventResultType.Retry;
177
181
  if (forceRetry) {
178
182
  return [2 /*return*/, performRequest(fnBail, attemptCount)];
179
183
  }
184
+ // allow retry logic to handle
185
+ if (!retryOptions.shouldRetry || retryOptions.shouldRetry(error)) {
186
+ throw error;
187
+ }
180
188
  return [4 /*yield*/, context.triggerEvent(ApiConstants_1.RequestEvent.UnrecoverableError)];
181
189
  case 7:
182
190
  unrecoverableErrorEventResult = _b.sent();
@@ -191,9 +199,9 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
191
199
  }
192
200
  });
193
201
  }); };
194
- return [4 /*yield*/, (0, retry_1.default)(performRequest, retryOpts)];
202
+ return [4 /*yield*/, (0, retry_1.default)(performRequest, internalRetryOptions)];
195
203
  case 2:
196
- response = _b.sent();
204
+ response = _d.sent();
197
205
  return [2 /*return*/, (response)];
198
206
  }
199
207
  });
@@ -163,7 +163,7 @@ var FetchRequestBackend = /** @class */ (function () {
163
163
  }, {});
164
164
  var url = context.getRequestUrl();
165
165
  var promise = this.fetch(url.href, {
166
- method: context.method,
166
+ method: context.method.toUpperCase(),
167
167
  body: bodyJsonify ? JSON.stringify(body) : body,
168
168
  headers: parsedHeaders,
169
169
  mode: "cors",
package/esm/ApiTypes.d.ts CHANGED
@@ -21,10 +21,16 @@ interface QueryHandling {
21
21
  parse: QueryParse;
22
22
  stringify: QueryStringify;
23
23
  }
24
+ export interface RetryOptions {
25
+ maxAttempts: number;
26
+ shouldRetry?: (error: Error) => boolean;
27
+ minDelay?: number;
28
+ maxDelay?: number;
29
+ }
24
30
  export interface BaseRequestConfig {
25
31
  cache?: number | boolean;
26
32
  lock?: RequestLock;
27
- retry?: number | false;
33
+ retry?: number | false | RetryOptions;
28
34
  headers?: Readonly<Headers>;
29
35
  acceptableStatus?: AcceptableStatus[];
30
36
  /**
@@ -13,6 +13,7 @@ export interface RequestError extends Error {
13
13
  isRequestError: true;
14
14
  response: ApiResponse | undefined | null;
15
15
  code: string;
16
+ attempts: number;
16
17
  }
17
18
  export declare const isRequestError: (error: Error) => error is RequestError;
18
19
  export interface RequestErrorConfig {
@@ -16,6 +16,7 @@ export const convertToRequestError = (config) => {
16
16
  response: response,
17
17
  code: code,
18
18
  isRequestError: true,
19
+ attempts: context.stats.attempt,
19
20
  request: {
20
21
  url: context.getRequestUrl().href,
21
22
  query: context.computedConfig.queryObject,
package/esm/Requester.js CHANGED
@@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import * as ApiUtils from "./ApiUtils";
11
10
  import { inferResponseType, isAcceptableStatus, isNetworkError } from "./ApiUtils";
12
11
  import RequestContext from "./RequestContext";
13
12
  import { EventResultType, RequestEvent } from "./ApiConstants";
@@ -59,19 +58,28 @@ export const submit = (host, config, mocking) => __awaiter(void 0, void 0, void
59
58
  }
60
59
  }
61
60
  });
61
+ const parseRetryOptions = (retryConfig) => {
62
+ if (retryConfig && typeof retryConfig === "object") {
63
+ return retryConfig;
64
+ }
65
+ if (typeof retryConfig === "number") {
66
+ return { maxAttempts: retryConfig };
67
+ }
68
+ return { maxAttempts: 0 };
69
+ };
62
70
  const makeRequest = (context) => __awaiter(void 0, void 0, void 0, function* () {
63
- var _a;
71
+ var _a, _b, _c;
64
72
  const beforeSendEventResult = yield context.triggerEvent(RequestEvent.BeforeSend);
65
73
  if (beforeSendEventResult &&
66
74
  beforeSendEventResult.type === EventResultType.Respond) {
67
75
  return (context.response = beforeSendEventResult.response);
68
76
  }
69
- const maxRetries = ((_a = context.computedConfig) === null || _a === void 0 ? void 0 : _a.retry) || 0;
70
- const retryOpts = {
71
- retries: maxRetries,
77
+ const retryOptions = parseRetryOptions((_a = context.computedConfig) === null || _a === void 0 ? void 0 : _a.retry);
78
+ const internalRetryOptions = {
79
+ retries: retryOptions.maxAttempts,
72
80
  // assume most users won't want to tune the delay between retries
73
- minTimeout: 1 * 1000,
74
- maxTimeout: 5 * 1000,
81
+ minTimeout: (_b = retryOptions.minDelay) !== null && _b !== void 0 ? _b : 200,
82
+ maxTimeout: (_c = retryOptions.maxDelay) !== null && _c !== void 0 ? _c : 1000,
75
83
  randomize: true,
76
84
  };
77
85
  context.stats.attempt = 0;
@@ -105,15 +113,19 @@ const makeRequest = (context) => __awaiter(void 0, void 0, void 0, function* ()
105
113
  return errorEventResult.response;
106
114
  }
107
115
  // allow retry logic to handle network errors
108
- const shouldNaturallyRetry = ApiUtils.isNetworkError(error);
109
- if (shouldNaturallyRetry) {
110
- throw error;
111
- }
116
+ //const shouldNaturallyRetry = ApiUtils.isNetworkError(error);
117
+ //if (shouldNaturallyRetry) {
118
+ // throw error;
119
+ //}
112
120
  // if we have an event that tells us to retry, we must do it
113
121
  const forceRetry = (errorEventResult === null || errorEventResult === void 0 ? void 0 : errorEventResult.type) === EventResultType.Retry;
114
122
  if (forceRetry) {
115
123
  return performRequest(fnBail, attemptCount);
116
124
  }
125
+ // allow retry logic to handle
126
+ if (!retryOptions.shouldRetry || retryOptions.shouldRetry(error)) {
127
+ throw error;
128
+ }
117
129
  // error is unrecoverable, bail
118
130
  const unrecoverableErrorEventResult = yield context.triggerEvent(RequestEvent.UnrecoverableError);
119
131
  if (unrecoverableErrorEventResult) {
@@ -124,11 +136,11 @@ const makeRequest = (context) => __awaiter(void 0, void 0, void 0, function* ()
124
136
  fnBail(error);
125
137
  }
126
138
  });
127
- const response = yield retry(performRequest, retryOpts);
139
+ const response = yield retry(performRequest, internalRetryOptions);
128
140
  return (response);
129
141
  });
130
142
  const parseResponse = (context, response, error) => __awaiter(void 0, void 0, void 0, function* () {
131
- var _b;
143
+ var _d;
132
144
  if (response) {
133
145
  const parsedResponse = yield context.backend.convertResponse(context, response);
134
146
  // lowercase all header names
@@ -153,7 +165,7 @@ const parseResponse = (context, response, error) => __awaiter(void 0, void 0, vo
153
165
  if (parsedResponse.data &&
154
166
  typeof parsedResponse.data === "object") {
155
167
  const data = response.data;
156
- if (((_b = data.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ArrayBuffer") {
168
+ if (((_d = data.constructor) === null || _d === void 0 ? void 0 : _d.name) === "ArrayBuffer") {
157
169
  try {
158
170
  const decodedData = (response.data = textDecode(data));
159
171
  response.data = JSON.parse(decodedData);
@@ -94,7 +94,7 @@ export default class FetchRequestBackend {
94
94
  }, {});
95
95
  const url = context.getRequestUrl();
96
96
  const promise = this.fetch(url.href, {
97
- method: context.method,
97
+ method: context.method.toUpperCase(),
98
98
  body: bodyJsonify ? JSON.stringify(body) : body,
99
99
  headers: parsedHeaders,
100
100
  mode: "cors",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-def",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "Typed API definitions with middleware support",
5
5
  "main": "cjs/index.js",
6
6
  "types": "esm/index.d.ts",