api-def 0.6.0-alpha9 → 0.6.2-alpha.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/LICENSE +20 -20
- package/README.md +34 -34
- package/cjs/Api.d.ts +1 -0
- package/cjs/Api.js +2 -1
- package/cjs/ApiConstants.d.ts +1 -0
- package/cjs/ApiConstants.js +1 -0
- package/cjs/ApiUtils.d.ts +2 -3
- package/cjs/ApiUtils.js +13 -21
- package/cjs/Endpoint.js +4 -4
- package/cjs/MockingTypes.d.ts +1 -0
- package/cjs/RequestContext.d.ts +3 -0
- package/cjs/RequestContext.js +29 -2
- package/cjs/RequestError.js +4 -1
- package/cjs/Requester.js +52 -20
- package/cjs/backend/AxiosRequestBackend.d.ts +3 -3
- package/cjs/backend/AxiosRequestBackend.js +8 -15
- package/cjs/backend/FetchRequestBackend.d.ts +3 -3
- package/cjs/backend/FetchRequestBackend.js +27 -39
- package/cjs/backend/MockRequestBackend.js +15 -7
- package/cjs/backend/RequestBackend.d.ts +4 -1
- package/cjs/cache/Caching.d.ts +1 -1
- package/cjs/index.js +5 -1
- package/cjs/middleware/LoggingMiddleware.js +7 -7
- package/esm/Api.d.ts +1 -0
- package/esm/Api.js +2 -1
- package/esm/ApiConstants.d.ts +1 -0
- package/esm/ApiConstants.js +1 -0
- package/esm/ApiUtils.d.ts +2 -3
- package/esm/ApiUtils.js +12 -19
- package/esm/Endpoint.js +4 -4
- package/esm/MockingTypes.d.ts +1 -0
- package/esm/RequestContext.d.ts +3 -0
- package/esm/RequestContext.js +29 -2
- package/esm/RequestError.js +4 -1
- package/esm/Requester.js +46 -14
- package/esm/backend/AxiosRequestBackend.d.ts +3 -3
- package/esm/backend/AxiosRequestBackend.js +7 -14
- package/esm/backend/FetchRequestBackend.d.ts +3 -3
- package/esm/backend/FetchRequestBackend.js +26 -38
- package/esm/backend/MockRequestBackend.js +11 -3
- package/esm/backend/RequestBackend.d.ts +4 -1
- package/esm/cache/Caching.d.ts +1 -1
- package/esm/middleware/LoggingMiddleware.js +7 -7
- package/package.json +17 -5
- package/CHANGELOG.md +0 -71
|
@@ -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() {
|
|
@@ -65,7 +64,7 @@ var FetchError = /** @class */ (function (_super) {
|
|
|
65
64
|
}(Error));
|
|
66
65
|
var FetchRequestBackend = /** @class */ (function () {
|
|
67
66
|
function FetchRequestBackend(fetchLibrary) {
|
|
68
|
-
this.fetch = Utils_1.getGlobalFetch();
|
|
67
|
+
this.fetch = (0, Utils_1.getGlobalFetch)();
|
|
69
68
|
this.id = "fetch";
|
|
70
69
|
if (fetchLibrary !== undefined) {
|
|
71
70
|
this.fetch = fetchLibrary;
|
|
@@ -83,59 +82,47 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
83
82
|
});
|
|
84
83
|
});
|
|
85
84
|
};
|
|
86
|
-
FetchRequestBackend.prototype.convertResponse = function (context, response
|
|
85
|
+
FetchRequestBackend.prototype.convertResponse = function (context, response) {
|
|
87
86
|
return __awaiter(this, void 0, void 0, function () {
|
|
88
|
-
var
|
|
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
|
-
|
|
94
|
-
|
|
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 = (0, 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
|
|
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
|
-
|
|
113
|
-
|
|
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
|
|
107
|
+
case 4:
|
|
119
108
|
data = _b.sent();
|
|
120
|
-
return [3 /*break*/,
|
|
121
|
-
case
|
|
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 =
|
|
126
|
-
case
|
|
127
|
-
case
|
|
114
|
+
_b.label = 6;
|
|
115
|
+
case 6: return [3 /*break*/, 8];
|
|
116
|
+
case 7:
|
|
128
117
|
error_1 = _b.sent();
|
|
129
|
-
throw Object.assign(new Error("[api-def] Invalid '"
|
|
118
|
+
throw Object.assign(new Error("[api-def] Invalid '".concat(context.responseType, "' response, got: '").concat(response.__text, "'")), {
|
|
130
119
|
response: response,
|
|
131
120
|
});
|
|
132
|
-
case
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
});
|
|
@@ -174,7 +161,8 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
174
161
|
var abortSignal = abortController ? abortController.signal : undefined;
|
|
175
162
|
var softAbort = false;
|
|
176
163
|
var responded = false;
|
|
177
|
-
var
|
|
164
|
+
var body = context.getParsedBody();
|
|
165
|
+
var bodyJsonify = body !== null && typeof body === "object";
|
|
178
166
|
var headers = Utils.assign({
|
|
179
167
|
// logic from axios
|
|
180
168
|
"Content-Type": bodyJsonify ? "application/json;charset=utf-8" : "application/x-www-form-urlencoded",
|
|
@@ -188,7 +176,7 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
188
176
|
}, {});
|
|
189
177
|
var promise = this.fetch(url.href, {
|
|
190
178
|
method: context.method,
|
|
191
|
-
body: bodyJsonify ? JSON.stringify(
|
|
179
|
+
body: bodyJsonify ? JSON.stringify(body) : body,
|
|
192
180
|
headers: parsedHeaders,
|
|
193
181
|
mode: "cors",
|
|
194
182
|
signal: abortSignal,
|
|
@@ -65,25 +65,26 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
65
65
|
MockRequestBackend.prototype.runRequest = function (context) {
|
|
66
66
|
var _a, _b, _c, _d;
|
|
67
67
|
return __awaiter(this, void 0, void 0, function () {
|
|
68
|
-
var mockingFunc, req, res, delay, delayMs, min, max, _e;
|
|
68
|
+
var mockingFunc, req, res, delay, delayMs, min, max, _e, parsedHeaders;
|
|
69
69
|
return __generator(this, function (_f) {
|
|
70
70
|
switch (_f.label) {
|
|
71
71
|
case 0:
|
|
72
72
|
mockingFunc = (_a = context.mocking) === null || _a === void 0 ? void 0 : _a.handler;
|
|
73
73
|
if (!mockingFunc) {
|
|
74
|
-
throw RequestError_1.convertToRequestError({
|
|
74
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
75
75
|
error: new Error("[api-def] Attempted to run mocked request without mocking function"),
|
|
76
76
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
req = {
|
|
80
|
-
body: context.
|
|
80
|
+
body: context.getParsedBody(),
|
|
81
81
|
params: (_b = context.computedConfig.params) !== null && _b !== void 0 ? _b : {},
|
|
82
82
|
query: context.computedConfig.query,
|
|
83
83
|
headers: (_c = context.computedConfig.headers) !== null && _c !== void 0 ? _c : {},
|
|
84
84
|
};
|
|
85
85
|
res = {
|
|
86
86
|
statusCode: -1,
|
|
87
|
+
headers: {},
|
|
87
88
|
response: undefined,
|
|
88
89
|
status: function (statusCode) {
|
|
89
90
|
res.statusCode = statusCode;
|
|
@@ -91,6 +92,9 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
91
92
|
},
|
|
92
93
|
send: function (response) {
|
|
93
94
|
res.response = response;
|
|
95
|
+
if (response && typeof response === "object") {
|
|
96
|
+
res.headers["Content-Type"] = "application/json";
|
|
97
|
+
}
|
|
94
98
|
return res;
|
|
95
99
|
},
|
|
96
100
|
};
|
|
@@ -103,12 +107,12 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
103
107
|
else {
|
|
104
108
|
min = delay[0], max = delay[1];
|
|
105
109
|
if (min > max) {
|
|
106
|
-
throw RequestError_1.convertToRequestError({
|
|
110
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
107
111
|
error: new Error("[api-def] Min delay cannot be greater than max delay"),
|
|
108
112
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
109
113
|
});
|
|
110
114
|
}
|
|
111
|
-
delayMs = Utils_1.randInt(min, max);
|
|
115
|
+
delayMs = (0, Utils_1.randInt)(min, max);
|
|
112
116
|
}
|
|
113
117
|
_e = Utils_1.delayThenReturn;
|
|
114
118
|
return [4 /*yield*/, mockingFunc(req, res)];
|
|
@@ -122,13 +126,17 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
122
126
|
_f.label = 5;
|
|
123
127
|
case 5:
|
|
124
128
|
if (res.response === undefined) {
|
|
125
|
-
throw RequestError_1.convertToRequestError({
|
|
129
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
126
130
|
error: new Error("[api-def] Mocked API did not respond"),
|
|
127
131
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
128
132
|
});
|
|
129
133
|
}
|
|
134
|
+
parsedHeaders = Object.keys(res.headers).reduce(function (parsedHeaders, key) {
|
|
135
|
+
parsedHeaders[key] = res.headers[key].toString();
|
|
136
|
+
return parsedHeaders;
|
|
137
|
+
}, {});
|
|
130
138
|
return [2 /*return*/, {
|
|
131
|
-
headers:
|
|
139
|
+
headers: parsedHeaders,
|
|
132
140
|
data: res.response,
|
|
133
141
|
status: res.statusCode,
|
|
134
142
|
}];
|
|
@@ -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
|
|
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/cjs/cache/Caching.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export interface CacheEntry {
|
|
|
6
6
|
data: any;
|
|
7
7
|
expiry: number | null;
|
|
8
8
|
}
|
|
9
|
-
export declare const setCachedItem: <T>(key: string, value: T, expiry?: number
|
|
9
|
+
export declare const setCachedItem: <T>(key: string, value: T, expiry?: number) => Promise<T>;
|
|
10
10
|
export declare const getCachedItem: <T = any>(key: string) => Promise<T | undefined>;
|
package/cjs/index.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
4
|
if (k2 === undefined) k2 = k;
|
|
5
|
-
Object.
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
6
10
|
}) : (function(o, m, k, k2) {
|
|
7
11
|
if (k2 === undefined) k2 = k;
|
|
8
12
|
o[k2] = m[k];
|
|
@@ -30,12 +30,12 @@ var diagnoseError = function (error) {
|
|
|
30
30
|
var _a = error.response, status = _a.status, data = _a.data;
|
|
31
31
|
var code = data === null || data === void 0 ? void 0 : data.code;
|
|
32
32
|
return {
|
|
33
|
-
message: "responded with "
|
|
33
|
+
message: "responded with ".concat(status).concat(code ? " (".concat(code, ")") : ""),
|
|
34
34
|
response: error.response,
|
|
35
35
|
};
|
|
36
36
|
};
|
|
37
37
|
var formatTime = function (time) {
|
|
38
|
-
return Utils.padNumber(time.getHours(), 2)
|
|
38
|
+
return "".concat(Utils.padNumber(time.getHours(), 2), ":").concat(Utils.padNumber(time.getMinutes(), 2), ":").concat(Utils.padNumber(time.getSeconds(), 2), ".").concat(Utils.padNumber(time.getMilliseconds(), 3));
|
|
39
39
|
};
|
|
40
40
|
var log = function (context, type, message, config, objects) {
|
|
41
41
|
if (typeof config.predicate === "function" && !config.predicate()) {
|
|
@@ -45,10 +45,10 @@ var log = function (context, type, message, config, objects) {
|
|
|
45
45
|
var color = COLOR_MAP[type];
|
|
46
46
|
var timestamp = formatTime(new Date());
|
|
47
47
|
var args = [
|
|
48
|
-
"%cnetwork %c["
|
|
48
|
+
"%cnetwork %c[".concat(context.api.name, "] ").concat(context.method.toUpperCase(), " ").concat(computedPath, " %c").concat(message, " %c@ ").concat(timestamp),
|
|
49
49
|
"color:gray",
|
|
50
50
|
"color:auto",
|
|
51
|
-
"color:"
|
|
51
|
+
"color:".concat(color),
|
|
52
52
|
"color:gray",
|
|
53
53
|
];
|
|
54
54
|
/* eslint-disable-next-line no-console */
|
|
@@ -68,18 +68,18 @@ var LoggingMiddleware = function (config) {
|
|
|
68
68
|
_a[ApiConstants_1.RequestEvent.Success] = function (context) {
|
|
69
69
|
var _a;
|
|
70
70
|
var cacheSource = context.cacheInfo.source;
|
|
71
|
-
log(context, LogType.Success, "responded with "
|
|
71
|
+
log(context, LogType.Success, "responded with ".concat((_a = context.response) === null || _a === void 0 ? void 0 : _a.status).concat(cacheSource ? " (cached by ".concat(cacheSource, ")") : ""), config);
|
|
72
72
|
},
|
|
73
73
|
_a[ApiConstants_1.RequestEvent.Error] = function (context) {
|
|
74
74
|
if (context.error) {
|
|
75
75
|
var _a = diagnoseError(context.error), error = _a.error, message = _a.message;
|
|
76
|
-
log(context, LogType.Warn, "error on attempt "
|
|
76
|
+
log(context, LogType.Warn, "error on attempt ".concat(context.stats.attempt, " - ").concat(message), config, { error: error });
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
_a[ApiConstants_1.RequestEvent.UnrecoverableError] = function (context) {
|
|
80
80
|
if (context.error) {
|
|
81
81
|
var _a = diagnoseError(context.error), error = _a.error, message = _a.message;
|
|
82
|
-
log(context, LogType.Error, "failed - "
|
|
82
|
+
log(context, LogType.Error, "failed - ".concat(message), config, {
|
|
83
83
|
error: error,
|
|
84
84
|
});
|
|
85
85
|
}
|
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
|
@@ -71,7 +71,7 @@ var HotRequestHost = /** @class */ (function () {
|
|
|
71
71
|
return Utils.assign({}, apiDefaults, config);
|
|
72
72
|
};
|
|
73
73
|
HotRequestHost.prototype.computePath = function (path, config) {
|
|
74
|
-
return path.startsWith("/") ? path : "/"
|
|
74
|
+
return path.startsWith("/") ? path : "/".concat(path);
|
|
75
75
|
};
|
|
76
76
|
return HotRequestHost;
|
|
77
77
|
}());
|
|
@@ -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 || [];
|
package/esm/ApiConstants.d.ts
CHANGED
package/esm/ApiConstants.js
CHANGED
package/esm/ApiUtils.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { AcceptableStatus,
|
|
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
|
|
6
|
-
export declare const isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[] | undefined) => boolean;
|
|
5
|
+
export declare const isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[]) => 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
|
|
50
|
-
|
|
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
|
};
|
package/esm/Endpoint.js
CHANGED
|
@@ -60,7 +60,7 @@ var Endpoint = /** @class */ (function () {
|
|
|
60
60
|
mockingEnabled = (_a = (typeof apiMocking.enabled === "function" ? apiMocking.enabled() : apiMocking.enabled)) !== null && _a !== void 0 ? _a : false;
|
|
61
61
|
if (mockingEnabled) {
|
|
62
62
|
if (!((_b = this.mocking) === null || _b === void 0 ? void 0 : _b.handler)) {
|
|
63
|
-
throw new Error("[api-def] Endpoint for '"
|
|
63
|
+
throw new Error("[api-def] Endpoint for '".concat(this.path, "' has no mocking"));
|
|
64
64
|
}
|
|
65
65
|
mock = true;
|
|
66
66
|
}
|
|
@@ -70,16 +70,16 @@ var Endpoint = /** @class */ (function () {
|
|
|
70
70
|
});
|
|
71
71
|
};
|
|
72
72
|
Endpoint.prototype.computePath = function (path, request) {
|
|
73
|
-
var computedPath = path.startsWith("/") ? path : "/"
|
|
73
|
+
var computedPath = path.startsWith("/") ? path : "/".concat(path);
|
|
74
74
|
if (request.params) {
|
|
75
75
|
var keys = Object.keys(request.params);
|
|
76
76
|
for (var i = 0; i < keys.length; i++) {
|
|
77
77
|
var argName = keys[i];
|
|
78
|
-
computedPath = computedPath.replace(":"
|
|
78
|
+
computedPath = computedPath.replace(":".concat(argName), request.params[argName]);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
if (computedPath.includes(":")) {
|
|
82
|
-
throw new Error("[api-def] Not all path params have been resolved: '"
|
|
82
|
+
throw new Error("[api-def] Not all path params have been resolved: '".concat(computedPath, "'"));
|
|
83
83
|
}
|
|
84
84
|
return computedPath;
|
|
85
85
|
};
|
package/esm/MockingTypes.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface MockRequest<R = any, P extends Params | undefined = Params | un
|
|
|
11
11
|
export interface MockResponse<R = any, P extends Params | undefined = Params | undefined, Q extends Query | undefined = Query | undefined, B extends Body | undefined = Body | undefined> {
|
|
12
12
|
statusCode: number;
|
|
13
13
|
response: R | undefined;
|
|
14
|
+
headers: Headers;
|
|
14
15
|
status(statusCode: number): this;
|
|
15
16
|
send(response: R): this;
|
|
16
17
|
}
|
package/esm/RequestContext.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export default class RequestContext<R = any, P extends Params | undefined = Para
|
|
|
19
19
|
cancelled: boolean;
|
|
20
20
|
readonly computedConfig: RequestConfig<P, Q, B>;
|
|
21
21
|
readonly mocking: EndpointMockingConfig<R, P, Q, B> | null | undefined;
|
|
22
|
+
private parsedBody;
|
|
22
23
|
constructor(backend: RequestBackend, host: RequestHost, config: RequestConfig<P, Q, B>, computedPath: string, mocking: EndpointMockingConfig<R, P, Q, B> | null | undefined);
|
|
23
24
|
get method(): RequestMethod;
|
|
24
25
|
get api(): Api;
|
|
@@ -27,6 +28,8 @@ export default class RequestContext<R = any, P extends Params | undefined = Para
|
|
|
27
28
|
private initMiddleware;
|
|
28
29
|
private generateKey;
|
|
29
30
|
updateHeaders(newHeaders: Headers): this;
|
|
31
|
+
private parseRequestBody;
|
|
32
|
+
getParsedBody(): any;
|
|
30
33
|
updateQuery(newQuery: Partial<Q>): this;
|
|
31
34
|
triggerEvent(eventType: RequestEvent): Promise<EventResult<R> | undefined>;
|
|
32
35
|
addCanceller(canceler: () => void): void;
|
package/esm/RequestContext.js
CHANGED
|
@@ -35,6 +35,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
import * as Utils from "./Utils";
|
|
38
|
+
import { URLSearchParams } from "url";
|
|
38
39
|
var contextIdCounter = 0;
|
|
39
40
|
var RequestContext = /** @class */ (function () {
|
|
40
41
|
function RequestContext(backend, host, config, computedPath, mocking) {
|
|
@@ -47,7 +48,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
47
48
|
this.id = contextIdCounter++;
|
|
48
49
|
this.host = host;
|
|
49
50
|
this.computedConfig = config;
|
|
50
|
-
Utils.assign({}, this.computedConfig.headers
|
|
51
|
+
Utils.assign({}, this.computedConfig.headers);
|
|
51
52
|
this.computedPath = computedPath;
|
|
52
53
|
this.key = this.generateKey();
|
|
53
54
|
this.stats = {
|
|
@@ -57,6 +58,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
57
58
|
this.eventHandlers = {};
|
|
58
59
|
this.mocking = mocking;
|
|
59
60
|
this.initMiddleware();
|
|
61
|
+
this.parseRequestBody();
|
|
60
62
|
}
|
|
61
63
|
Object.defineProperty(RequestContext.prototype, "method", {
|
|
62
64
|
get: function () {
|
|
@@ -109,7 +111,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
109
111
|
var queryKeys = Object.keys(computedConfig.query);
|
|
110
112
|
for (var i = 0; i < queryKeys.length; i++) {
|
|
111
113
|
var queryKey = queryKeys[i];
|
|
112
|
-
queryStrings.push(queryKey
|
|
114
|
+
queryStrings.push("".concat(queryKey, "=").concat(computedConfig.query[queryKey]));
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
if (queryStrings.length > 0) {
|
|
@@ -119,8 +121,33 @@ var RequestContext = /** @class */ (function () {
|
|
|
119
121
|
};
|
|
120
122
|
RequestContext.prototype.updateHeaders = function (newHeaders) {
|
|
121
123
|
this.computedConfig.headers = Utils.assign({}, this.computedConfig.headers, newHeaders);
|
|
124
|
+
this.parseRequestBody();
|
|
122
125
|
return this;
|
|
123
126
|
};
|
|
127
|
+
RequestContext.prototype.parseRequestBody = function () {
|
|
128
|
+
if (this.computedConfig.body && this.computedConfig.headers) {
|
|
129
|
+
var contentTypeKey = Object.keys(this.computedConfig.headers).find(function (key) { return key.toLowerCase() === "content-type"; });
|
|
130
|
+
var contentType = contentTypeKey && this.computedConfig.headers[contentTypeKey];
|
|
131
|
+
if (typeof contentType === "string" && contentType.toLowerCase() === "multipart/form-data") {
|
|
132
|
+
var searchParams = new URLSearchParams();
|
|
133
|
+
for (var _i = 0, _a = Object.keys(this.computedConfig.body); _i < _a.length; _i++) {
|
|
134
|
+
var key = _a[_i];
|
|
135
|
+
var value = this.computedConfig.body[key];
|
|
136
|
+
searchParams.set(key, value === null || value === void 0 ? void 0 : value.toString());
|
|
137
|
+
}
|
|
138
|
+
this.parsedBody = searchParams.toString();
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.parsedBody = this.computedConfig.body;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
this.parsedBody = undefined;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
RequestContext.prototype.getParsedBody = function () {
|
|
149
|
+
return this.parsedBody;
|
|
150
|
+
};
|
|
124
151
|
RequestContext.prototype.updateQuery = function (newQuery) {
|
|
125
152
|
this.computedConfig.query = Utils.assign(this.computedConfig.query || {}, newQuery);
|
|
126
153
|
return this;
|
package/esm/RequestError.js
CHANGED
|
@@ -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:
|
|
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();
|
|
@@ -153,7 +154,7 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
|
|
|
153
154
|
parsedResponse = (_b.sent());
|
|
154
155
|
if (!isAcceptableStatus(parsedResponse.status, context.computedConfig.acceptableStatus)) {
|
|
155
156
|
throw convertToRequestError({
|
|
156
|
-
error: new Error("[api-def] Invalid response status code '"
|
|
157
|
+
error: new Error("[api-def] Invalid response status code '".concat(parsedResponse.status, "'")),
|
|
157
158
|
response: parsedResponse,
|
|
158
159
|
code: RequestErrorCode.REQUEST_INVALID_STATUS,
|
|
159
160
|
});
|
|
@@ -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
|
|
214
|
-
|
|
215
|
-
|
|
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
|
|
216
|
+
return [4 /*yield*/, context.backend.convertResponse(context, response)];
|
|
219
217
|
case 1:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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 '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(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 '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
|
|
248
|
+
code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
|
|
249
|
+
response: parsedResponse_1,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
223
255
|
}
|
|
224
|
-
return [2 /*return*/,
|
|
256
|
+
return [2 /*return*/, parsedResponse_1];
|
|
225
257
|
case 2: return [2 /*return*/, response];
|
|
226
258
|
}
|
|
227
259
|
});
|