api-def 0.6.0-alpha9 → 0.6.1

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/Api.d.ts CHANGED
@@ -28,4 +28,5 @@ export declare class Api implements ApiInfo {
28
28
  post: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
29
29
  put: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
30
30
  delete: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
31
+ patch: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
31
32
  }
package/cjs/Api.js CHANGED
@@ -98,6 +98,7 @@ var Api = /** @class */ (function () {
98
98
  this.post = this.hotRequest(ApiConstants_1.RequestMethod.POST);
99
99
  this.put = this.hotRequest(ApiConstants_1.RequestMethod.PUT);
100
100
  this.delete = this.hotRequest(ApiConstants_1.RequestMethod.DELETE);
101
+ this.patch = this.hotRequest(ApiConstants_1.RequestMethod.PATCH);
101
102
  this.name = info.name;
102
103
  this.baseUrl = info.baseUrl;
103
104
  this.middleware = info.middleware || [];
@@ -8,6 +8,7 @@ export declare const RequestMethod: {
8
8
  readonly GET: "get";
9
9
  readonly PUT: "put";
10
10
  readonly DELETE: "delete";
11
+ readonly PATCH: "patch";
11
12
  };
12
13
  export declare type RequestMethod = EnumOf<typeof RequestMethod>;
13
14
  export declare const RequestEvent: {
@@ -10,6 +10,7 @@ exports.RequestMethod = {
10
10
  GET: "get",
11
11
  PUT: "put",
12
12
  DELETE: "delete",
13
+ PATCH: "patch",
13
14
  };
14
15
  exports.RequestEvent = {
15
16
  /** @deprecated use 'BEFORE_SEND' */
package/cjs/ApiUtils.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { AcceptableStatus, ApiResponse, CancelledRequestError } from "./ApiTypes";
1
+ import { AcceptableStatus, CancelledRequestError } from "./ApiTypes";
2
2
  import { ResponseType } from "./ApiConstants";
3
3
  export declare const isCancelledError: (error: Error) => error is CancelledRequestError;
4
4
  export declare const isNetworkError: (error: Error) => boolean;
5
- export declare const parseResponseDataToObject: (response: ApiResponse) => void;
6
5
  export declare const isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[] | undefined) => boolean;
7
6
  export declare const inferResponseType: (contentType: string | null | undefined) => ResponseType;
package/cjs/ApiUtils.js CHANGED
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.inferResponseType = exports.isAcceptableStatus = exports.parseResponseDataToObject = exports.isNetworkError = exports.isCancelledError = void 0;
4
- var TextDecoding_1 = require("./TextDecoding");
3
+ exports.inferResponseType = exports.isAcceptableStatus = exports.isNetworkError = exports.isCancelledError = void 0;
5
4
  var isCancelledError = function (error) {
6
5
  return "isCancelledRequest" in error;
7
6
  };
@@ -13,23 +12,6 @@ var isNetworkError = function (error) {
13
12
  ((_a = error.constructor) === null || _a === void 0 ? void 0 : _a.name) === "NetworkError");
14
13
  };
15
14
  exports.isNetworkError = isNetworkError;
16
- var parseResponseDataToObject = function (response) {
17
- if (response.data &&
18
- typeof response.data === "object") {
19
- var data = response.data;
20
- if (data.constructor && data.constructor.name === "ArrayBuffer") {
21
- try {
22
- var decodedData = (response.data = TextDecoding_1.textDecode(data));
23
- response.data = JSON.parse(decodedData);
24
- }
25
- catch (e) {
26
- // eslint-disable-next-line
27
- console.warn("[api-def] Couldn't parse array buffer content to JSON response", e);
28
- }
29
- }
30
- }
31
- };
32
- exports.parseResponseDataToObject = parseResponseDataToObject;
33
15
  var DEFAULT_ACCEPTABLE_STATUS = [[200, 299], 304];
34
16
  var isAcceptableStatus = function (status, acceptableStatus) {
35
17
  var acceptable = acceptableStatus !== null && acceptableStatus !== void 0 ? acceptableStatus : DEFAULT_ACCEPTABLE_STATUS;
@@ -50,11 +32,21 @@ var isAcceptableStatus = function (status, acceptableStatus) {
50
32
  return (false);
51
33
  };
52
34
  exports.isAcceptableStatus = isAcceptableStatus;
35
+ var TEXT_CONTENT_TYPES = ["text/plain"];
53
36
  var JSON_CONTENT_TYPES = ["text/json", "application/json"];
37
+ var ARRRAY_BUFFER_CONTENT_TYPES = ["application/octet-stream"];
54
38
  var inferResponseType = function (contentType) {
55
39
  var contentTypePart = contentType === null || contentType === void 0 ? void 0 : contentType.split(";")[0].trim();
56
- if (contentTypePart && JSON_CONTENT_TYPES.includes(contentTypePart)) {
57
- return "json";
40
+ if (contentTypePart) {
41
+ if (TEXT_CONTENT_TYPES.includes(contentTypePart)) {
42
+ return "text";
43
+ }
44
+ else if (JSON_CONTENT_TYPES.includes(contentTypePart)) {
45
+ return "json";
46
+ }
47
+ else if (ARRRAY_BUFFER_CONTENT_TYPES.includes(contentTypePart)) {
48
+ return "arraybuffer";
49
+ }
58
50
  }
59
51
  return "text";
60
52
  };
@@ -15,10 +15,13 @@ exports.isRequestError = isRequestError;
15
15
  var convertToRequestError = function (config) {
16
16
  var error = config.error, response = config.response, code = config.code;
17
17
  return Object.assign(error, {
18
- name: error.name === "Error" ? "RequestError" : error.name,
18
+ name: "RequestError",
19
19
  response: response,
20
20
  code: code,
21
21
  isRequestError: true,
22
+ config: undefined,
23
+ request: undefined,
24
+ toJSON: undefined,
22
25
  });
23
26
  };
24
27
  exports.convertToRequestError = convertToRequestError;
package/cjs/Requester.js CHANGED
@@ -56,6 +56,7 @@ var ApiConstants_1 = require("./ApiConstants");
56
56
  var retry_1 = require("./util/retry");
57
57
  var MockRequestBackend_1 = require("./backend/MockRequestBackend");
58
58
  var RequestError_1 = require("./RequestError");
59
+ var TextDecoding_1 = require("./TextDecoding");
59
60
  var locks = {};
60
61
  var runningOperations = {};
61
62
  var MOCK_REQUEST_BACKEND = new MockRequestBackend_1.default();
@@ -174,10 +175,6 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
174
175
  error = _b.sent();
175
176
  context.error = error;
176
177
  context.response = error.response;
177
- // transform array buffer responses to objs
178
- if (context.response) {
179
- ApiUtils.parseResponseDataToObject(context.response);
180
- }
181
178
  return [4 /*yield*/, context.triggerEvent(ApiConstants_1.RequestEvent.Error)];
182
179
  case 6:
183
180
  errorEventResult = _b.sent();
@@ -214,18 +211,53 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
214
211
  });
215
212
  }); };
216
213
  var parseResponse = function (context, response, error) { return __awaiter(void 0, void 0, void 0, function () {
217
- var parsedResponse;
218
- return __generator(this, function (_a) {
219
- switch (_a.label) {
214
+ var parsedResponse_1, contentType, inferredResponseType, data, decodedData;
215
+ var _a;
216
+ return __generator(this, function (_b) {
217
+ switch (_b.label) {
220
218
  case 0:
221
219
  if (!response) return [3 /*break*/, 2];
222
- return [4 /*yield*/, context.backend.convertResponse(context, response, error)];
220
+ return [4 /*yield*/, context.backend.convertResponse(context, response)];
223
221
  case 1:
224
- parsedResponse = _a.sent();
225
- if (parsedResponse) {
226
- ApiUtils.parseResponseDataToObject(parsedResponse);
222
+ parsedResponse_1 = _b.sent();
223
+ // lowercase all header names
224
+ parsedResponse_1.headers = parsedResponse_1.__lowercaseHeaders || Object.keys(parsedResponse_1.headers).reduce(function (headers, header) {
225
+ headers[header.toLowerCase()] = parsedResponse_1.headers[header];
226
+ return headers;
227
+ }, {});
228
+ contentType = parsedResponse_1.headers["content-type"];
229
+ inferredResponseType = ApiUtils_1.inferResponseType(contentType);
230
+ if (!error) {
231
+ // expand to array buffer once we support that in inferResponseType
232
+ if (inferredResponseType === "text" && context.responseType === "json") {
233
+ throw RequestError_1.convertToRequestError({
234
+ error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
235
+ code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
236
+ response: parsedResponse_1,
237
+ });
238
+ }
239
+ // transform arrayBuffer to json
240
+ if (inferredResponseType === "arraybuffer" && context.responseType === "json") {
241
+ if (parsedResponse_1.data &&
242
+ typeof parsedResponse_1.data === "object") {
243
+ data = response.data;
244
+ if (((_a = data.constructor) === null || _a === void 0 ? void 0 : _a.name) === "ArrayBuffer") {
245
+ try {
246
+ decodedData = (response.data = TextDecoding_1.textDecode(data));
247
+ response.data = JSON.parse(decodedData);
248
+ }
249
+ catch (e) {
250
+ throw RequestError_1.convertToRequestError({
251
+ error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
252
+ code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
253
+ response: parsedResponse_1,
254
+ });
255
+ }
256
+ }
257
+ }
258
+ }
227
259
  }
228
- return [2 /*return*/, parsedResponse];
260
+ return [2 /*return*/, parsedResponse_1];
229
261
  case 2: return [2 /*return*/, response];
230
262
  }
231
263
  });
@@ -1,4 +1,4 @@
1
- import RequestBackend, { RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
1
+ import RequestBackend, { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
2
2
  import { ApiResponse } from "../ApiTypes";
3
3
  import type { AxiosError, AxiosResponse } from "axios";
4
4
  import RequestContext from "../RequestContext";
@@ -7,7 +7,7 @@ export default class AxiosRequestBackend implements RequestBackend<AxiosResponse
7
7
  readonly id = "axios";
8
8
  constructor(axiosLibrary: any);
9
9
  extractResponseFromError(error: Error): Promise<AxiosResponse | null | undefined>;
10
- convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ApiResponse<T>>;
10
+ convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ConvertedApiResponse<T>>;
11
11
  makeRequest(context: RequestContext): RequestOperation<AxiosResponse>;
12
12
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
13
13
  }
@@ -37,8 +37,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.isAxiosError = void 0;
40
- var ApiUtils_1 = require("../ApiUtils");
41
- var RequestError_1 = require("../RequestError");
42
40
  var axios;
43
41
  var isAxiosError = function (error) {
44
42
  return "isAxiosError" in error;
@@ -62,18 +60,13 @@ var AxiosRequestBackend = /** @class */ (function () {
62
60
  };
63
61
  AxiosRequestBackend.prototype.convertResponse = function (context, response) {
64
62
  return __awaiter(this, void 0, void 0, function () {
65
- var contentType, inferredResponseType;
66
63
  return __generator(this, function (_a) {
67
- contentType = response.headers["content-type"];
68
- inferredResponseType = ApiUtils_1.inferResponseType(contentType);
69
- // expand to array buffer once we support that in inferResponseType
70
- if (inferredResponseType === "text" && context.responseType === "json") {
71
- throw RequestError_1.convertToRequestError({
72
- error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
73
- code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
74
- });
75
- }
76
- return [2 /*return*/, response];
64
+ return [2 /*return*/, {
65
+ data: response.data,
66
+ headers: response.headers,
67
+ status: response.status,
68
+ __lowercaseHeaders: response._lowerCaseResponseHeaders,
69
+ }];
77
70
  });
78
71
  });
79
72
  };
@@ -1,4 +1,4 @@
1
- import RequestBackend, { RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
1
+ import RequestBackend, { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
2
2
  import { ApiResponse } from "../ApiTypes";
3
3
  import RequestContext from "../RequestContext";
4
4
  import { Fetch } from "../Utils";
@@ -9,7 +9,7 @@ export default class FetchRequestBackend implements RequestBackend<Response> {
9
9
  extractResponseFromError(error: Error): Promise<Response | null | undefined>;
10
10
  convertResponse<T>(context: RequestContext, response: Response & {
11
11
  __text?: string;
12
- }, error?: boolean): Promise<ApiResponse<T>>;
12
+ }): Promise<ConvertedApiResponse<T>>;
13
13
  makeRequest(context: RequestContext): RequestOperation<Response>;
14
14
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
15
15
  }
@@ -55,7 +55,6 @@ var Utils = require("../Utils");
55
55
  var Utils_1 = require("../Utils");
56
56
  var ApiConstants_1 = require("../ApiConstants");
57
57
  var ApiUtils_1 = require("../ApiUtils");
58
- var RequestError_1 = require("../RequestError");
59
58
  var FetchError = /** @class */ (function (_super) {
60
59
  __extends(FetchError, _super);
61
60
  function FetchError() {
@@ -83,59 +82,47 @@ var FetchRequestBackend = /** @class */ (function () {
83
82
  });
84
83
  });
85
84
  };
86
- FetchRequestBackend.prototype.convertResponse = function (context, response, error) {
85
+ FetchRequestBackend.prototype.convertResponse = function (context, response) {
87
86
  return __awaiter(this, void 0, void 0, function () {
88
- var data, contentType, inferredResponseType, responseType, _a, error_1, status;
87
+ var contentType, responseType, _a, data, status, headers, error_1;
89
88
  return __generator(this, function (_b) {
90
89
  switch (_b.label) {
91
90
  case 0:
92
91
  contentType = response.headers.get("Content-Type");
93
- inferredResponseType = ApiUtils_1.inferResponseType(contentType);
94
- responseType = error ? inferredResponseType : context.responseType;
95
- // expand to array buffer once we support that in inferResponseType
96
- if (inferredResponseType === "text" && context.responseType === "json") {
97
- throw RequestError_1.convertToRequestError({
98
- error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
99
- code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
100
- });
101
- }
102
- _b.label = 1;
103
- case 1:
104
- _b.trys.push([1, 8, , 9]);
105
- if (!!response.__text) return [3 /*break*/, 3];
92
+ responseType = ApiUtils_1.inferResponseType(contentType);
93
+ if (!!response.__text) return [3 /*break*/, 2];
106
94
  _a = response;
107
95
  return [4 /*yield*/, response.clone().text()];
108
- case 2:
96
+ case 1:
109
97
  _a.__text = _b.sent();
98
+ _b.label = 2;
99
+ case 2:
100
+ data = response.__text;
101
+ status = response.status, headers = response.headers;
110
102
  _b.label = 3;
111
103
  case 3:
112
- if (!(responseType === ApiConstants_1.ResponseType.Text)) return [3 /*break*/, 4];
113
- data = response.__text;
114
- return [3 /*break*/, 7];
115
- case 4:
116
- if (!(responseType === ApiConstants_1.ResponseType.ArrayBuffer)) return [3 /*break*/, 6];
104
+ _b.trys.push([3, 7, , 8]);
105
+ if (!(responseType === ApiConstants_1.ResponseType.ArrayBuffer)) return [3 /*break*/, 5];
117
106
  return [4 /*yield*/, response.clone().arrayBuffer()];
118
- case 5:
107
+ case 4:
119
108
  data = _b.sent();
120
- return [3 /*break*/, 7];
121
- case 6:
109
+ return [3 /*break*/, 6];
110
+ case 5:
122
111
  if (responseType === ApiConstants_1.ResponseType.Json) {
123
112
  data = JSON.parse(response.__text);
124
113
  }
125
- _b.label = 7;
126
- case 7: return [3 /*break*/, 9];
127
- case 8:
114
+ _b.label = 6;
115
+ case 6: return [3 /*break*/, 8];
116
+ case 7:
128
117
  error_1 = _b.sent();
129
118
  throw Object.assign(new Error("[api-def] Invalid '" + context.responseType + "' response, got: '" + response.__text + "'"), {
130
119
  response: response,
131
120
  });
132
- case 9:
133
- status = response.status;
134
- return [2 /*return*/, {
135
- data: data,
136
- status: status,
137
- headers: response.headers,
138
- }];
121
+ case 8: return [2 /*return*/, {
122
+ data: data,
123
+ status: status,
124
+ headers: headers,
125
+ }];
139
126
  }
140
127
  });
141
128
  });
@@ -7,10 +7,13 @@ export interface RequestOperation<R> {
7
7
  export interface RequestBackendErrorInfo {
8
8
  code: string;
9
9
  }
10
+ export declare type ConvertedApiResponse<T> = ApiResponse<T> & {
11
+ __lowercaseHeaders?: any;
12
+ };
10
13
  export default interface RequestBackend<R = any> {
11
14
  readonly id: string;
12
15
  makeRequest(context: RequestContext): RequestOperation<R>;
13
- convertResponse<T>(context: RequestContext, response: R, error?: boolean): Promise<ApiResponse<T>>;
16
+ convertResponse<T>(context: RequestContext, response: R): Promise<ConvertedApiResponse<T>>;
14
17
  extractResponseFromError(error: Error): Promise<R | null | undefined>;
15
18
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
16
19
  }
package/esm/Api.d.ts CHANGED
@@ -28,4 +28,5 @@ export declare class Api implements ApiInfo {
28
28
  post: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
29
29
  put: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
30
30
  delete: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
31
+ patch: <R = unknown>(path: string, config: RequestConfig) => Promise<ApiResponse<R>>;
31
32
  }
package/esm/Api.js CHANGED
@@ -92,6 +92,7 @@ var Api = /** @class */ (function () {
92
92
  this.post = this.hotRequest(RequestMethod.POST);
93
93
  this.put = this.hotRequest(RequestMethod.PUT);
94
94
  this.delete = this.hotRequest(RequestMethod.DELETE);
95
+ this.patch = this.hotRequest(RequestMethod.PATCH);
95
96
  this.name = info.name;
96
97
  this.baseUrl = info.baseUrl;
97
98
  this.middleware = info.middleware || [];
@@ -8,6 +8,7 @@ export declare const RequestMethod: {
8
8
  readonly GET: "get";
9
9
  readonly PUT: "put";
10
10
  readonly DELETE: "delete";
11
+ readonly PATCH: "patch";
11
12
  };
12
13
  export declare type RequestMethod = EnumOf<typeof RequestMethod>;
13
14
  export declare const RequestEvent: {
@@ -7,6 +7,7 @@ export var RequestMethod = {
7
7
  GET: "get",
8
8
  PUT: "put",
9
9
  DELETE: "delete",
10
+ PATCH: "patch",
10
11
  };
11
12
  export var RequestEvent = {
12
13
  /** @deprecated use 'BEFORE_SEND' */
package/esm/ApiUtils.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { AcceptableStatus, ApiResponse, CancelledRequestError } from "./ApiTypes";
1
+ import { AcceptableStatus, CancelledRequestError } from "./ApiTypes";
2
2
  import { ResponseType } from "./ApiConstants";
3
3
  export declare const isCancelledError: (error: Error) => error is CancelledRequestError;
4
4
  export declare const isNetworkError: (error: Error) => boolean;
5
- export declare const parseResponseDataToObject: (response: ApiResponse) => void;
6
5
  export declare const isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[] | undefined) => boolean;
7
6
  export declare const inferResponseType: (contentType: string | null | undefined) => ResponseType;
package/esm/ApiUtils.js CHANGED
@@ -1,4 +1,3 @@
1
- import { textDecode } from "./TextDecoding";
2
1
  export var isCancelledError = function (error) {
3
2
  return "isCancelledRequest" in error;
4
3
  };
@@ -8,22 +7,6 @@ export var isNetworkError = function (error) {
8
7
  error.message === "Network Error" ||
9
8
  ((_a = error.constructor) === null || _a === void 0 ? void 0 : _a.name) === "NetworkError");
10
9
  };
11
- export var parseResponseDataToObject = function (response) {
12
- if (response.data &&
13
- typeof response.data === "object") {
14
- var data = response.data;
15
- if (data.constructor && data.constructor.name === "ArrayBuffer") {
16
- try {
17
- var decodedData = (response.data = textDecode(data));
18
- response.data = JSON.parse(decodedData);
19
- }
20
- catch (e) {
21
- // eslint-disable-next-line
22
- console.warn("[api-def] Couldn't parse array buffer content to JSON response", e);
23
- }
24
- }
25
- }
26
- };
27
10
  var DEFAULT_ACCEPTABLE_STATUS = [[200, 299], 304];
28
11
  export var isAcceptableStatus = function (status, acceptableStatus) {
29
12
  var acceptable = acceptableStatus !== null && acceptableStatus !== void 0 ? acceptableStatus : DEFAULT_ACCEPTABLE_STATUS;
@@ -43,11 +26,21 @@ export var isAcceptableStatus = function (status, acceptableStatus) {
43
26
  }
44
27
  return (false);
45
28
  };
29
+ var TEXT_CONTENT_TYPES = ["text/plain"];
46
30
  var JSON_CONTENT_TYPES = ["text/json", "application/json"];
31
+ var ARRRAY_BUFFER_CONTENT_TYPES = ["application/octet-stream"];
47
32
  export var inferResponseType = function (contentType) {
48
33
  var contentTypePart = contentType === null || contentType === void 0 ? void 0 : contentType.split(";")[0].trim();
49
- if (contentTypePart && JSON_CONTENT_TYPES.includes(contentTypePart)) {
50
- return "json";
34
+ if (contentTypePart) {
35
+ if (TEXT_CONTENT_TYPES.includes(contentTypePart)) {
36
+ return "text";
37
+ }
38
+ else if (JSON_CONTENT_TYPES.includes(contentTypePart)) {
39
+ return "json";
40
+ }
41
+ else if (ARRRAY_BUFFER_CONTENT_TYPES.includes(contentTypePart)) {
42
+ return "arraybuffer";
43
+ }
51
44
  }
52
45
  return "text";
53
46
  };
@@ -11,9 +11,12 @@ export var isRequestError = function (error) {
11
11
  export var convertToRequestError = function (config) {
12
12
  var error = config.error, response = config.response, code = config.code;
13
13
  return Object.assign(error, {
14
- name: error.name === "Error" ? "RequestError" : error.name,
14
+ name: "RequestError",
15
15
  response: response,
16
16
  code: code,
17
17
  isRequestError: true,
18
+ config: undefined,
19
+ request: undefined,
20
+ toJSON: undefined,
18
21
  });
19
22
  };
package/esm/Requester.js CHANGED
@@ -46,13 +46,14 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
46
46
  }
47
47
  };
48
48
  import * as ApiUtils from "./ApiUtils";
49
- import { isAcceptableStatus, isNetworkError } from "./ApiUtils";
49
+ import { inferResponseType, isAcceptableStatus, isNetworkError } from "./ApiUtils";
50
50
  import RequestContext from "./RequestContext";
51
51
  import * as Api from "./Api";
52
52
  import { EventResultType, RequestEvent } from "./ApiConstants";
53
53
  import retry from "./util/retry";
54
54
  import MockRequestBackend from "./backend/MockRequestBackend";
55
55
  import { convertToRequestError, isRequestError, RequestErrorCode } from "./RequestError";
56
+ import { textDecode } from "./TextDecoding";
56
57
  var locks = {};
57
58
  var runningOperations = {};
58
59
  var MOCK_REQUEST_BACKEND = new MockRequestBackend();
@@ -170,10 +171,6 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
170
171
  error = _b.sent();
171
172
  context.error = error;
172
173
  context.response = error.response;
173
- // transform array buffer responses to objs
174
- if (context.response) {
175
- ApiUtils.parseResponseDataToObject(context.response);
176
- }
177
174
  return [4 /*yield*/, context.triggerEvent(RequestEvent.Error)];
178
175
  case 6:
179
176
  errorEventResult = _b.sent();
@@ -210,18 +207,53 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
210
207
  });
211
208
  }); };
212
209
  var parseResponse = function (context, response, error) { return __awaiter(void 0, void 0, void 0, function () {
213
- var parsedResponse;
214
- return __generator(this, function (_a) {
215
- switch (_a.label) {
210
+ var parsedResponse_1, contentType, inferredResponseType, data, decodedData;
211
+ var _a;
212
+ return __generator(this, function (_b) {
213
+ switch (_b.label) {
216
214
  case 0:
217
215
  if (!response) return [3 /*break*/, 2];
218
- return [4 /*yield*/, context.backend.convertResponse(context, response, error)];
216
+ return [4 /*yield*/, context.backend.convertResponse(context, response)];
219
217
  case 1:
220
- parsedResponse = _a.sent();
221
- if (parsedResponse) {
222
- ApiUtils.parseResponseDataToObject(parsedResponse);
218
+ parsedResponse_1 = _b.sent();
219
+ // lowercase all header names
220
+ parsedResponse_1.headers = parsedResponse_1.__lowercaseHeaders || Object.keys(parsedResponse_1.headers).reduce(function (headers, header) {
221
+ headers[header.toLowerCase()] = parsedResponse_1.headers[header];
222
+ return headers;
223
+ }, {});
224
+ contentType = parsedResponse_1.headers["content-type"];
225
+ inferredResponseType = inferResponseType(contentType);
226
+ if (!error) {
227
+ // expand to array buffer once we support that in inferResponseType
228
+ if (inferredResponseType === "text" && context.responseType === "json") {
229
+ throw convertToRequestError({
230
+ error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
231
+ code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
232
+ response: parsedResponse_1,
233
+ });
234
+ }
235
+ // transform arrayBuffer to json
236
+ if (inferredResponseType === "arraybuffer" && context.responseType === "json") {
237
+ if (parsedResponse_1.data &&
238
+ typeof parsedResponse_1.data === "object") {
239
+ data = response.data;
240
+ if (((_a = data.constructor) === null || _a === void 0 ? void 0 : _a.name) === "ArrayBuffer") {
241
+ try {
242
+ decodedData = (response.data = textDecode(data));
243
+ response.data = JSON.parse(decodedData);
244
+ }
245
+ catch (e) {
246
+ throw convertToRequestError({
247
+ error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
248
+ code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
249
+ response: parsedResponse_1,
250
+ });
251
+ }
252
+ }
253
+ }
254
+ }
223
255
  }
224
- return [2 /*return*/, parsedResponse];
256
+ return [2 /*return*/, parsedResponse_1];
225
257
  case 2: return [2 /*return*/, response];
226
258
  }
227
259
  });
@@ -1,4 +1,4 @@
1
- import RequestBackend, { RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
1
+ import RequestBackend, { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
2
2
  import { ApiResponse } from "../ApiTypes";
3
3
  import type { AxiosError, AxiosResponse } from "axios";
4
4
  import RequestContext from "../RequestContext";
@@ -7,7 +7,7 @@ export default class AxiosRequestBackend implements RequestBackend<AxiosResponse
7
7
  readonly id = "axios";
8
8
  constructor(axiosLibrary: any);
9
9
  extractResponseFromError(error: Error): Promise<AxiosResponse | null | undefined>;
10
- convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ApiResponse<T>>;
10
+ convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ConvertedApiResponse<T>>;
11
11
  makeRequest(context: RequestContext): RequestOperation<AxiosResponse>;
12
12
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
13
13
  }
@@ -34,8 +34,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
34
34
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
35
  }
36
36
  };
37
- import { inferResponseType } from "../ApiUtils";
38
- import { convertToRequestError, RequestErrorCode } from "../RequestError";
39
37
  var axios;
40
38
  export var isAxiosError = function (error) {
41
39
  return "isAxiosError" in error;
@@ -58,18 +56,13 @@ var AxiosRequestBackend = /** @class */ (function () {
58
56
  };
59
57
  AxiosRequestBackend.prototype.convertResponse = function (context, response) {
60
58
  return __awaiter(this, void 0, void 0, function () {
61
- var contentType, inferredResponseType;
62
59
  return __generator(this, function (_a) {
63
- contentType = response.headers["content-type"];
64
- inferredResponseType = inferResponseType(contentType);
65
- // expand to array buffer once we support that in inferResponseType
66
- if (inferredResponseType === "text" && context.responseType === "json") {
67
- throw convertToRequestError({
68
- error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
69
- code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
70
- });
71
- }
72
- return [2 /*return*/, response];
60
+ return [2 /*return*/, {
61
+ data: response.data,
62
+ headers: response.headers,
63
+ status: response.status,
64
+ __lowercaseHeaders: response._lowerCaseResponseHeaders,
65
+ }];
73
66
  });
74
67
  });
75
68
  };
@@ -1,4 +1,4 @@
1
- import RequestBackend, { RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
1
+ import RequestBackend, { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
2
2
  import { ApiResponse } from "../ApiTypes";
3
3
  import RequestContext from "../RequestContext";
4
4
  import { Fetch } from "../Utils";
@@ -9,7 +9,7 @@ export default class FetchRequestBackend implements RequestBackend<Response> {
9
9
  extractResponseFromError(error: Error): Promise<Response | null | undefined>;
10
10
  convertResponse<T>(context: RequestContext, response: Response & {
11
11
  __text?: string;
12
- }, error?: boolean): Promise<ApiResponse<T>>;
12
+ }): Promise<ConvertedApiResponse<T>>;
13
13
  makeRequest(context: RequestContext): RequestOperation<Response>;
14
14
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
15
15
  }
@@ -53,7 +53,6 @@ import * as Utils from "../Utils";
53
53
  import { getGlobalFetch } from "../Utils";
54
54
  import { ResponseType } from "../ApiConstants";
55
55
  import { inferResponseType } from "../ApiUtils";
56
- import { convertToRequestError, RequestErrorCode } from "../RequestError";
57
56
  var FetchError = /** @class */ (function (_super) {
58
57
  __extends(FetchError, _super);
59
58
  function FetchError() {
@@ -81,59 +80,47 @@ var FetchRequestBackend = /** @class */ (function () {
81
80
  });
82
81
  });
83
82
  };
84
- FetchRequestBackend.prototype.convertResponse = function (context, response, error) {
83
+ FetchRequestBackend.prototype.convertResponse = function (context, response) {
85
84
  return __awaiter(this, void 0, void 0, function () {
86
- var data, contentType, inferredResponseType, responseType, _a, error_1, status;
85
+ var contentType, responseType, _a, data, status, headers, error_1;
87
86
  return __generator(this, function (_b) {
88
87
  switch (_b.label) {
89
88
  case 0:
90
89
  contentType = response.headers.get("Content-Type");
91
- inferredResponseType = inferResponseType(contentType);
92
- responseType = error ? inferredResponseType : context.responseType;
93
- // expand to array buffer once we support that in inferResponseType
94
- if (inferredResponseType === "text" && context.responseType === "json") {
95
- throw convertToRequestError({
96
- error: new Error("[api-def] Expected '" + context.responseType + "' response, got '" + inferredResponseType + "' (from 'Content-Type' of '" + contentType + "')"),
97
- code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
98
- });
99
- }
100
- _b.label = 1;
101
- case 1:
102
- _b.trys.push([1, 8, , 9]);
103
- if (!!response.__text) return [3 /*break*/, 3];
90
+ responseType = inferResponseType(contentType);
91
+ if (!!response.__text) return [3 /*break*/, 2];
104
92
  _a = response;
105
93
  return [4 /*yield*/, response.clone().text()];
106
- case 2:
94
+ case 1:
107
95
  _a.__text = _b.sent();
96
+ _b.label = 2;
97
+ case 2:
98
+ data = response.__text;
99
+ status = response.status, headers = response.headers;
108
100
  _b.label = 3;
109
101
  case 3:
110
- if (!(responseType === ResponseType.Text)) return [3 /*break*/, 4];
111
- data = response.__text;
112
- return [3 /*break*/, 7];
113
- case 4:
114
- if (!(responseType === ResponseType.ArrayBuffer)) return [3 /*break*/, 6];
102
+ _b.trys.push([3, 7, , 8]);
103
+ if (!(responseType === ResponseType.ArrayBuffer)) return [3 /*break*/, 5];
115
104
  return [4 /*yield*/, response.clone().arrayBuffer()];
116
- case 5:
105
+ case 4:
117
106
  data = _b.sent();
118
- return [3 /*break*/, 7];
119
- case 6:
107
+ return [3 /*break*/, 6];
108
+ case 5:
120
109
  if (responseType === ResponseType.Json) {
121
110
  data = JSON.parse(response.__text);
122
111
  }
123
- _b.label = 7;
124
- case 7: return [3 /*break*/, 9];
125
- case 8:
112
+ _b.label = 6;
113
+ case 6: return [3 /*break*/, 8];
114
+ case 7:
126
115
  error_1 = _b.sent();
127
116
  throw Object.assign(new Error("[api-def] Invalid '" + context.responseType + "' response, got: '" + response.__text + "'"), {
128
117
  response: response,
129
118
  });
130
- case 9:
131
- status = response.status;
132
- return [2 /*return*/, {
133
- data: data,
134
- status: status,
135
- headers: response.headers,
136
- }];
119
+ case 8: return [2 /*return*/, {
120
+ data: data,
121
+ status: status,
122
+ headers: headers,
123
+ }];
137
124
  }
138
125
  });
139
126
  });
@@ -7,10 +7,13 @@ export interface RequestOperation<R> {
7
7
  export interface RequestBackendErrorInfo {
8
8
  code: string;
9
9
  }
10
+ export declare type ConvertedApiResponse<T> = ApiResponse<T> & {
11
+ __lowercaseHeaders?: any;
12
+ };
10
13
  export default interface RequestBackend<R = any> {
11
14
  readonly id: string;
12
15
  makeRequest(context: RequestContext): RequestOperation<R>;
13
- convertResponse<T>(context: RequestContext, response: R, error?: boolean): Promise<ApiResponse<T>>;
16
+ convertResponse<T>(context: RequestContext, response: R): Promise<ConvertedApiResponse<T>>;
14
17
  extractResponseFromError(error: Error): Promise<R | null | undefined>;
15
18
  getErrorInfo(error: Error, response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
16
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-def",
3
- "version": "0.6.0-alpha9",
3
+ "version": "0.6.1",
4
4
  "description": "Typed API definitions with middleware support",
5
5
  "main": "cjs/index.js",
6
6
  "types": "esm/index.d.ts",
package/CHANGELOG.md DELETED
@@ -1,71 +0,0 @@
1
- # 0.6.0
2
-
3
- ## Breaking Changes
4
-
5
- - axios will enforce `ResponseType`
6
-
7
- ## Features
8
-
9
- - add `ResponseOf`, `QueryOf`, `BodyOf`, `ParamsOf` to quickly get types from endpoints
10
- - new `queryParser` config option to allow custom query string parsing
11
-
12
- ## Fixes
13
-
14
- - absolute paths as `baseUrl` is now supported in fetch backend
15
- - don't re-use same requests based upon URL to allow for concurrent POST requests
16
-
17
- # 0.5.0
18
-
19
- ## Breaking Changes
20
-
21
- - Undocumented mocking API has been overhauled
22
-
23
- ## Changes
24
-
25
- - Add mocking!
26
- - Restructured mocking so that mocks are defined on the endpoint level (documentation updated)
27
- - Add `acceptableStatus` to specify which status codes are considered successful
28
- - Extend retry logic to use exponential back-off, rather than retrying immediately
29
- - Support for additional hot-request methods:
30
- - PUT, DELETE
31
-
32
- # 0.4.1
33
-
34
- - fix fetch backend not working with unbound fetch
35
- - add better error handling on parse
36
-
37
- # 0.4.0
38
-
39
- ## Breaking Changes
40
-
41
- - Move config values from options object up one layer
42
- - In config `retries` -> `retry`
43
- - `defaults` -> `config`
44
-
45
- ## Changes
46
-
47
- - Remove need for enum imports
48
- - Make `name` and `description` optional in endpoint definition
49
-
50
- # 0.3.11
51
-
52
- ## Changes
53
-
54
- - Make fetch backend default if fetch is present
55
- - Fix fetch backends text response type support
56
-
57
- # 0.3.0
58
-
59
- ## Features
60
-
61
- - allow defaults to be a function on api
62
- - add content type header in fetch backend to match axios backend
63
- - remove `flatted`
64
- - polyfill object.assign for ie
65
- - change retry logic so that if a middleware event responds with Retry we always attempt a retry
66
-
67
- # 0.2.5
68
-
69
- ## Changes
70
-
71
- - Remove `window` usages to allow node support