api-def 0.6.1 → 0.6.2-alpha.2
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.js +1 -1
- package/cjs/ApiUtils.d.ts +1 -1
- package/cjs/Endpoint.js +4 -4
- package/cjs/MockingTypes.d.ts +1 -0
- package/cjs/RequestContext.d.ts +4 -0
- package/cjs/RequestContext.js +61 -2
- package/cjs/RequestError.d.ts +2 -0
- package/cjs/RequestError.js +11 -5
- package/cjs/Requester.js +17 -14
- package/cjs/backend/AxiosRequestBackend.d.ts +1 -1
- package/cjs/backend/AxiosRequestBackend.js +2 -2
- package/cjs/backend/FetchRequestBackend.d.ts +1 -1
- package/cjs/backend/FetchRequestBackend.js +7 -29
- package/cjs/backend/MockRequestBackend.js +18 -7
- package/cjs/cache/Caching.d.ts +1 -1
- package/cjs/index.js +5 -1
- package/cjs/middleware/LoggingMiddleware.js +7 -7
- package/esm/Api.js +1 -1
- package/esm/ApiUtils.d.ts +1 -1
- package/esm/Endpoint.js +4 -4
- package/esm/MockingTypes.d.ts +1 -0
- package/esm/RequestContext.d.ts +4 -0
- package/esm/RequestContext.js +61 -2
- package/esm/RequestError.d.ts +2 -0
- package/esm/RequestError.js +11 -5
- package/esm/Requester.js +7 -4
- package/esm/backend/AxiosRequestBackend.d.ts +1 -1
- package/esm/backend/AxiosRequestBackend.js +1 -1
- package/esm/backend/FetchRequestBackend.d.ts +1 -1
- package/esm/backend/FetchRequestBackend.js +5 -27
- package/esm/backend/MockRequestBackend.js +14 -3
- package/esm/cache/Caching.d.ts +1 -1
- package/esm/middleware/LoggingMiddleware.js +7 -7
- package/package.json +17 -5
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.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
|
}());
|
package/esm/ApiUtils.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ 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 isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[]
|
|
5
|
+
export declare const isAcceptableStatus: (status: number, acceptableStatus?: AcceptableStatus[]) => boolean;
|
|
6
6
|
export declare const inferResponseType: (contentType: string | null | undefined) => ResponseType;
|
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,8 +28,11 @@ 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;
|
|
33
36
|
cancel(): void;
|
|
37
|
+
getRequestUrl(): URL;
|
|
34
38
|
}
|
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;
|
|
@@ -162,6 +189,38 @@ var RequestContext = /** @class */ (function () {
|
|
|
162
189
|
this.canceler();
|
|
163
190
|
}
|
|
164
191
|
};
|
|
192
|
+
RequestContext.prototype.getRequestUrl = function () {
|
|
193
|
+
var _a;
|
|
194
|
+
var path = !this.baseUrl.endsWith("/")
|
|
195
|
+
? this.baseUrl + "/"
|
|
196
|
+
: this.baseUrl;
|
|
197
|
+
path += this.computedPath.startsWith("/")
|
|
198
|
+
? this.computedPath.substring(1)
|
|
199
|
+
: this.computedPath;
|
|
200
|
+
var origin = undefined;
|
|
201
|
+
if (typeof window !== "undefined") {
|
|
202
|
+
origin = window.origin;
|
|
203
|
+
}
|
|
204
|
+
if (!origin) {
|
|
205
|
+
if (path.indexOf("://") === -1) {
|
|
206
|
+
path = "https://".concat(path);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
var url = new URL(path, origin);
|
|
210
|
+
if (this.computedConfig.query) {
|
|
211
|
+
if (this.computedConfig.queryParser) {
|
|
212
|
+
url.search = this.computedConfig.queryParser(this.computedConfig.query);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
var queryKeys = Object.keys(this.computedConfig.query);
|
|
216
|
+
for (var i = 0; i < queryKeys.length; i++) {
|
|
217
|
+
var key = queryKeys[i];
|
|
218
|
+
url.searchParams.append(key, ((_a = this.computedConfig.query[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return url;
|
|
223
|
+
};
|
|
165
224
|
return RequestContext;
|
|
166
225
|
}());
|
|
167
226
|
export default RequestContext;
|
package/esm/RequestError.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ApiResponse } from "./ApiTypes";
|
|
2
2
|
import { EnumOf } from "./Utils";
|
|
3
|
+
import RequestContext from "./RequestContext";
|
|
3
4
|
export declare const RequestErrorCode: {
|
|
4
5
|
readonly MISC_UNKNOWN_ERROR: "misc/unknown-error";
|
|
5
6
|
readonly REQUEST_NETWORK_ERROR: "request/network-error";
|
|
@@ -17,6 +18,7 @@ export declare const isRequestError: (error: Error) => error is RequestError;
|
|
|
17
18
|
export interface RequestErrorConfig {
|
|
18
19
|
error: Error;
|
|
19
20
|
code: string;
|
|
21
|
+
context: RequestContext;
|
|
20
22
|
response?: ApiResponse | null;
|
|
21
23
|
}
|
|
22
24
|
export declare const convertToRequestError: (config: RequestErrorConfig) => RequestError;
|
package/esm/RequestError.js
CHANGED
|
@@ -9,14 +9,20 @@ export var isRequestError = function (error) {
|
|
|
9
9
|
return "isRequestError" in error;
|
|
10
10
|
};
|
|
11
11
|
export var convertToRequestError = function (config) {
|
|
12
|
-
var error = config.error, response = config.response, code = config.code;
|
|
13
|
-
|
|
12
|
+
var error = config.error, context = config.context, response = config.response, code = config.code;
|
|
13
|
+
var resultError = Object.assign(error, {
|
|
14
14
|
name: "RequestError",
|
|
15
15
|
response: response,
|
|
16
16
|
code: code,
|
|
17
17
|
isRequestError: true,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
request: {
|
|
19
|
+
url: context.getRequestUrl().href,
|
|
20
|
+
query: context.computedConfig.query,
|
|
21
|
+
headers: context.computedConfig.headers,
|
|
22
|
+
body: context.getParsedBody(),
|
|
23
|
+
},
|
|
21
24
|
});
|
|
25
|
+
delete resultError.config;
|
|
26
|
+
delete resultError.toJSON;
|
|
27
|
+
return resultError;
|
|
22
28
|
};
|
package/esm/Requester.js
CHANGED
|
@@ -154,9 +154,10 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
|
|
|
154
154
|
parsedResponse = (_b.sent());
|
|
155
155
|
if (!isAcceptableStatus(parsedResponse.status, context.computedConfig.acceptableStatus)) {
|
|
156
156
|
throw convertToRequestError({
|
|
157
|
-
error: new Error("[api-def] Invalid response status code '"
|
|
157
|
+
error: new Error("[api-def] Invalid response status code '".concat(parsedResponse.status, "'")),
|
|
158
158
|
response: parsedResponse,
|
|
159
159
|
code: RequestErrorCode.REQUEST_INVALID_STATUS,
|
|
160
|
+
context: context,
|
|
160
161
|
});
|
|
161
162
|
}
|
|
162
163
|
context.response = parsedResponse;
|
|
@@ -227,9 +228,10 @@ var parseResponse = function (context, response, error) { return __awaiter(void
|
|
|
227
228
|
// expand to array buffer once we support that in inferResponseType
|
|
228
229
|
if (inferredResponseType === "text" && context.responseType === "json") {
|
|
229
230
|
throw convertToRequestError({
|
|
230
|
-
error: new Error("[api-def] Expected '"
|
|
231
|
+
error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
|
|
231
232
|
code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
|
|
232
233
|
response: parsedResponse_1,
|
|
234
|
+
context: context,
|
|
233
235
|
});
|
|
234
236
|
}
|
|
235
237
|
// transform arrayBuffer to json
|
|
@@ -244,9 +246,10 @@ var parseResponse = function (context, response, error) { return __awaiter(void
|
|
|
244
246
|
}
|
|
245
247
|
catch (e) {
|
|
246
248
|
throw convertToRequestError({
|
|
247
|
-
error: new Error("[api-def] Expected '"
|
|
249
|
+
error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
|
|
248
250
|
code: RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
|
|
249
251
|
response: parsedResponse_1,
|
|
252
|
+
context: context,
|
|
250
253
|
});
|
|
251
254
|
}
|
|
252
255
|
}
|
|
@@ -283,7 +286,7 @@ var parseError = function (context, rawError) { return __awaiter(void 0, void 0,
|
|
|
283
286
|
}
|
|
284
287
|
}
|
|
285
288
|
errorInfo = context.backend.getErrorInfo(rawError, errorResponse);
|
|
286
|
-
error = convertToRequestError(__assign({ error: rawError, response: errorResponse, code: code }, errorInfo));
|
|
289
|
+
error = convertToRequestError(__assign({ error: rawError, response: errorResponse, code: code, context: context }, errorInfo));
|
|
287
290
|
_a.label = 5;
|
|
288
291
|
case 5: return [2 /*return*/, error];
|
|
289
292
|
}
|
|
@@ -2,7 +2,7 @@ import RequestBackend, { ConvertedApiResponse, RequestBackendErrorInfo, RequestO
|
|
|
2
2
|
import { ApiResponse } from "../ApiTypes";
|
|
3
3
|
import type { AxiosError, AxiosResponse } from "axios";
|
|
4
4
|
import RequestContext from "../RequestContext";
|
|
5
|
-
export declare const isAxiosError: (error: Error) => error is AxiosError<any>;
|
|
5
|
+
export declare const isAxiosError: (error: Error) => error is AxiosError<unknown, any>;
|
|
6
6
|
export default class AxiosRequestBackend implements RequestBackend<AxiosResponse> {
|
|
7
7
|
readonly id = "axios";
|
|
8
8
|
constructor(axiosLibrary: any);
|
|
@@ -73,7 +73,7 @@ var AxiosRequestBackend = /** @class */ (function () {
|
|
|
73
73
|
method: context.method,
|
|
74
74
|
baseURL: context.baseUrl,
|
|
75
75
|
url: context.computedPath,
|
|
76
|
-
data:
|
|
76
|
+
data: context.getParsedBody() || {},
|
|
77
77
|
params: computedConfig.query || {},
|
|
78
78
|
headers: computedConfig.headers || {},
|
|
79
79
|
responseType: context.responseType,
|
|
@@ -3,7 +3,7 @@ import { ApiResponse } from "../ApiTypes";
|
|
|
3
3
|
import RequestContext from "../RequestContext";
|
|
4
4
|
import { Fetch } from "../Utils";
|
|
5
5
|
export default class FetchRequestBackend implements RequestBackend<Response> {
|
|
6
|
-
fetch: (((input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>) & typeof fetch) | undefined;
|
|
6
|
+
fetch: (((input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>) & typeof fetch) | undefined;
|
|
7
7
|
readonly id = "fetch";
|
|
8
8
|
constructor(fetchLibrary?: Fetch);
|
|
9
9
|
extractResponseFromError(error: Error): Promise<Response | null | undefined>;
|
|
@@ -113,7 +113,7 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
113
113
|
case 6: return [3 /*break*/, 8];
|
|
114
114
|
case 7:
|
|
115
115
|
error_1 = _b.sent();
|
|
116
|
-
throw Object.assign(new Error("[api-def] Invalid '"
|
|
116
|
+
throw Object.assign(new Error("[api-def] Invalid '".concat(context.responseType, "' response, got: '").concat(response.__text, "'")), {
|
|
117
117
|
response: response,
|
|
118
118
|
});
|
|
119
119
|
case 8: return [2 /*return*/, {
|
|
@@ -126,40 +126,17 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
126
126
|
});
|
|
127
127
|
};
|
|
128
128
|
FetchRequestBackend.prototype.makeRequest = function (context) {
|
|
129
|
-
var _a;
|
|
130
129
|
if (!this.fetch) {
|
|
131
130
|
throw new Error("[api-def] No fetch impl was provided to FetchRequestBackend");
|
|
132
131
|
}
|
|
133
132
|
var computedConfig = context.computedConfig;
|
|
134
|
-
var path = !context.baseUrl.endsWith("/")
|
|
135
|
-
? context.baseUrl + "/"
|
|
136
|
-
: context.baseUrl;
|
|
137
|
-
path += context.computedPath.startsWith("/")
|
|
138
|
-
? context.computedPath.substring(1)
|
|
139
|
-
: context.computedPath;
|
|
140
|
-
var origin = undefined;
|
|
141
|
-
if (typeof window !== "undefined") {
|
|
142
|
-
origin = window.origin;
|
|
143
|
-
}
|
|
144
|
-
var url = new URL(path, origin);
|
|
145
|
-
if (computedConfig.query) {
|
|
146
|
-
if (context.computedConfig.queryParser) {
|
|
147
|
-
url.search = context.computedConfig.queryParser(computedConfig.query);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
var queryKeys = Object.keys(computedConfig.query);
|
|
151
|
-
for (var i = 0; i < queryKeys.length; i++) {
|
|
152
|
-
var key = queryKeys[i];
|
|
153
|
-
url.searchParams.append(key, ((_a = computedConfig.query[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "");
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
133
|
// abort controller is a newer feature than fetch
|
|
158
134
|
var abortController = AbortController && new AbortController();
|
|
159
135
|
var abortSignal = abortController ? abortController.signal : undefined;
|
|
160
136
|
var softAbort = false;
|
|
161
137
|
var responded = false;
|
|
162
|
-
var
|
|
138
|
+
var body = context.getParsedBody();
|
|
139
|
+
var bodyJsonify = body !== null && typeof body === "object";
|
|
163
140
|
var headers = Utils.assign({
|
|
164
141
|
// logic from axios
|
|
165
142
|
"Content-Type": bodyJsonify ? "application/json;charset=utf-8" : "application/x-www-form-urlencoded",
|
|
@@ -171,9 +148,10 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
171
148
|
}
|
|
172
149
|
return parsedHeaders;
|
|
173
150
|
}, {});
|
|
151
|
+
var url = context.getRequestUrl();
|
|
174
152
|
var promise = this.fetch(url.href, {
|
|
175
153
|
method: context.method,
|
|
176
|
-
body: bodyJsonify ? JSON.stringify(
|
|
154
|
+
body: bodyJsonify ? JSON.stringify(body) : body,
|
|
177
155
|
headers: parsedHeaders,
|
|
178
156
|
mode: "cors",
|
|
179
157
|
signal: abortSignal,
|
|
@@ -63,7 +63,7 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
63
63
|
MockRequestBackend.prototype.runRequest = function (context) {
|
|
64
64
|
var _a, _b, _c, _d;
|
|
65
65
|
return __awaiter(this, void 0, void 0, function () {
|
|
66
|
-
var mockingFunc, req, res, delay, delayMs, min, max, _e;
|
|
66
|
+
var mockingFunc, req, res, delay, delayMs, min, max, _e, parsedHeaders;
|
|
67
67
|
return __generator(this, function (_f) {
|
|
68
68
|
switch (_f.label) {
|
|
69
69
|
case 0:
|
|
@@ -72,16 +72,18 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
72
72
|
throw convertToRequestError({
|
|
73
73
|
error: new Error("[api-def] Attempted to run mocked request without mocking function"),
|
|
74
74
|
code: RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
75
|
+
context: context,
|
|
75
76
|
});
|
|
76
77
|
}
|
|
77
78
|
req = {
|
|
78
|
-
body: context.
|
|
79
|
+
body: context.getParsedBody(),
|
|
79
80
|
params: (_b = context.computedConfig.params) !== null && _b !== void 0 ? _b : {},
|
|
80
81
|
query: context.computedConfig.query,
|
|
81
82
|
headers: (_c = context.computedConfig.headers) !== null && _c !== void 0 ? _c : {},
|
|
82
83
|
};
|
|
83
84
|
res = {
|
|
84
85
|
statusCode: -1,
|
|
86
|
+
headers: {},
|
|
85
87
|
response: undefined,
|
|
86
88
|
status: function (statusCode) {
|
|
87
89
|
res.statusCode = statusCode;
|
|
@@ -89,6 +91,9 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
89
91
|
},
|
|
90
92
|
send: function (response) {
|
|
91
93
|
res.response = response;
|
|
94
|
+
if (response && typeof response === "object") {
|
|
95
|
+
res.headers["Content-Type"] = "application/json";
|
|
96
|
+
}
|
|
92
97
|
return res;
|
|
93
98
|
},
|
|
94
99
|
};
|
|
@@ -104,6 +109,7 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
104
109
|
throw convertToRequestError({
|
|
105
110
|
error: new Error("[api-def] Min delay cannot be greater than max delay"),
|
|
106
111
|
code: RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
112
|
+
context: context,
|
|
107
113
|
});
|
|
108
114
|
}
|
|
109
115
|
delayMs = randInt(min, max);
|
|
@@ -123,10 +129,15 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
123
129
|
throw convertToRequestError({
|
|
124
130
|
error: new Error("[api-def] Mocked API did not respond"),
|
|
125
131
|
code: RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
132
|
+
context: context,
|
|
126
133
|
});
|
|
127
134
|
}
|
|
135
|
+
parsedHeaders = Object.keys(res.headers).reduce(function (parsedHeaders, key) {
|
|
136
|
+
parsedHeaders[key] = res.headers[key].toString();
|
|
137
|
+
return parsedHeaders;
|
|
138
|
+
}, {});
|
|
128
139
|
return [2 /*return*/, {
|
|
129
|
-
headers:
|
|
140
|
+
headers: parsedHeaders,
|
|
130
141
|
data: res.response,
|
|
131
142
|
status: res.statusCode,
|
|
132
143
|
}];
|
package/esm/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>;
|
|
@@ -28,12 +28,12 @@ var diagnoseError = function (error) {
|
|
|
28
28
|
var _a = error.response, status = _a.status, data = _a.data;
|
|
29
29
|
var code = data === null || data === void 0 ? void 0 : data.code;
|
|
30
30
|
return {
|
|
31
|
-
message: "responded with "
|
|
31
|
+
message: "responded with ".concat(status).concat(code ? " (".concat(code, ")") : ""),
|
|
32
32
|
response: error.response,
|
|
33
33
|
};
|
|
34
34
|
};
|
|
35
35
|
var formatTime = function (time) {
|
|
36
|
-
return Utils.padNumber(time.getHours(), 2)
|
|
36
|
+
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));
|
|
37
37
|
};
|
|
38
38
|
var log = function (context, type, message, config, objects) {
|
|
39
39
|
if (typeof config.predicate === "function" && !config.predicate()) {
|
|
@@ -43,10 +43,10 @@ var log = function (context, type, message, config, objects) {
|
|
|
43
43
|
var color = COLOR_MAP[type];
|
|
44
44
|
var timestamp = formatTime(new Date());
|
|
45
45
|
var args = [
|
|
46
|
-
"%cnetwork %c["
|
|
46
|
+
"%cnetwork %c[".concat(context.api.name, "] ").concat(context.method.toUpperCase(), " ").concat(computedPath, " %c").concat(message, " %c@ ").concat(timestamp),
|
|
47
47
|
"color:gray",
|
|
48
48
|
"color:auto",
|
|
49
|
-
"color:"
|
|
49
|
+
"color:".concat(color),
|
|
50
50
|
"color:gray",
|
|
51
51
|
];
|
|
52
52
|
/* eslint-disable-next-line no-console */
|
|
@@ -66,18 +66,18 @@ var LoggingMiddleware = function (config) {
|
|
|
66
66
|
_a[RequestEvent.Success] = function (context) {
|
|
67
67
|
var _a;
|
|
68
68
|
var cacheSource = context.cacheInfo.source;
|
|
69
|
-
log(context, LogType.Success, "responded with "
|
|
69
|
+
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);
|
|
70
70
|
},
|
|
71
71
|
_a[RequestEvent.Error] = function (context) {
|
|
72
72
|
if (context.error) {
|
|
73
73
|
var _a = diagnoseError(context.error), error = _a.error, message = _a.message;
|
|
74
|
-
log(context, LogType.Warn, "error on attempt "
|
|
74
|
+
log(context, LogType.Warn, "error on attempt ".concat(context.stats.attempt, " - ").concat(message), config, { error: error });
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
77
|
_a[RequestEvent.UnrecoverableError] = function (context) {
|
|
78
78
|
if (context.error) {
|
|
79
79
|
var _a = diagnoseError(context.error), error = _a.error, message = _a.message;
|
|
80
|
-
log(context, LogType.Error, "failed - "
|
|
80
|
+
log(context, LogType.Error, "failed - ".concat(message), config, {
|
|
81
81
|
error: error,
|
|
82
82
|
});
|
|
83
83
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api-def",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2-alpha.2",
|
|
4
4
|
"description": "Typed API definitions with middleware support",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"types": "esm/index.d.ts",
|
|
7
7
|
"module": "esm/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"scripts": {
|
|
10
|
+
"prepublishOnly": "npm run test && npm run build",
|
|
10
11
|
"test": "npm run test:types && npm run test:lint && npm run test:unit",
|
|
11
|
-
"test:unit": "
|
|
12
|
+
"test:unit": "ava",
|
|
12
13
|
"test:lint": "npm run lint:strict",
|
|
13
14
|
"test:types": "tsc --noEmit -p .",
|
|
14
15
|
"example:start": "cd example && npm run start",
|
|
@@ -45,19 +46,30 @@
|
|
|
45
46
|
"cjs/"
|
|
46
47
|
],
|
|
47
48
|
"repository": "https://github.com/Censkh/api-def",
|
|
49
|
+
"ava": {
|
|
50
|
+
"extensions": [
|
|
51
|
+
"ts"
|
|
52
|
+
],
|
|
53
|
+
"files": [
|
|
54
|
+
"src/tests/**/*.test.ts"
|
|
55
|
+
],
|
|
56
|
+
"nodeArguments": [
|
|
57
|
+
"--require=@esbuild-kit/cjs-loader"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
48
60
|
"devDependencies": {
|
|
49
61
|
"@babel/preset-env": "7.14.8",
|
|
50
62
|
"@babel/preset-typescript": "7.14.5",
|
|
63
|
+
"@esbuild-kit/cjs-loader": "2.4.0",
|
|
51
64
|
"@types/axios": "0.14.0",
|
|
52
|
-
"@types/jest": "26.0.24",
|
|
53
65
|
"@types/node": "16.4.6",
|
|
54
66
|
"@typescript-eslint/eslint-plugin": "4.28.5",
|
|
55
67
|
"@typescript-eslint/parser": "4.28.5",
|
|
68
|
+
"ava": "5.0.1",
|
|
56
69
|
"cross-env": "7.0.3",
|
|
57
70
|
"eslint": "7.31.0",
|
|
58
71
|
"eslint-watch": "7.0.0",
|
|
59
|
-
"jest": "27.0.6",
|
|
60
72
|
"npm-run-all": "4.1.5",
|
|
61
|
-
"typescript": "4.
|
|
73
|
+
"typescript": "4.8.4"
|
|
62
74
|
}
|
|
63
75
|
}
|