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/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2019 James Waterhouse
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 James Waterhouse
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
# [api-def](https://github.com/Censkh/api-def/) · [](https://github.com/Censkh/api-def/blob/master/LICENSE) [](https://www.npmjs.com/package/api-def) [](https://github.com/Censkh/api-def/actions)
|
|
2
|
-
|
|
3
|
-
Typed APIs with middleware support
|
|
4
|
-
|
|
5
|
-
API def provides a unified way to type your endpoints allowing for compile time checking of query, body, response and even url parameters
|
|
6
|
-
|
|
7
|
-
``` npm i api-def ```
|
|
8
|
-
|
|
9
|
-
- [Documentation](https://censkh.github.io/api-def/)
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import {Api} from "api-def";
|
|
13
|
-
|
|
14
|
-
const api = new Api({
|
|
15
|
-
baseUrl: "https://my-api/",
|
|
16
|
-
name: "My API",
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const fetchData = api.endpoint()
|
|
20
|
-
.queryOf<{ includeAwesome: boolean; }>()
|
|
21
|
-
.responseOf<{ data: {awesome: boolean; } }>()
|
|
22
|
-
.build({
|
|
23
|
-
id: "fetch_data",
|
|
24
|
-
method: "get",
|
|
25
|
-
path: "/data"
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// calls GET https://my-api/data?includeAwesome=true
|
|
29
|
-
const res = await fetchData.submit({
|
|
30
|
-
query: {includeAwesome: true}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
console.log(res.data); // { data: { awesome: true } }
|
|
34
|
-
```
|
|
1
|
+
# [api-def](https://github.com/Censkh/api-def/) · [](https://github.com/Censkh/api-def/blob/master/LICENSE) [](https://www.npmjs.com/package/api-def) [](https://github.com/Censkh/api-def/actions)
|
|
2
|
+
|
|
3
|
+
Typed APIs with middleware support
|
|
4
|
+
|
|
5
|
+
API def provides a unified way to type your endpoints allowing for compile time checking of query, body, response and even url parameters
|
|
6
|
+
|
|
7
|
+
``` npm i api-def ```
|
|
8
|
+
|
|
9
|
+
- [Documentation](https://censkh.github.io/api-def/)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import {Api} from "api-def";
|
|
13
|
+
|
|
14
|
+
const api = new Api({
|
|
15
|
+
baseUrl: "https://my-api/",
|
|
16
|
+
name: "My API",
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const fetchData = api.endpoint()
|
|
20
|
+
.queryOf<{ includeAwesome: boolean; }>()
|
|
21
|
+
.responseOf<{ data: {awesome: boolean; } }>()
|
|
22
|
+
.build({
|
|
23
|
+
id: "fetch_data",
|
|
24
|
+
method: "get",
|
|
25
|
+
path: "/data"
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// calls GET https://my-api/data?includeAwesome=true
|
|
29
|
+
const res = await fetchData.submit({
|
|
30
|
+
query: {includeAwesome: true}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(res.data); // { data: { awesome: true } }
|
|
34
|
+
```
|
package/cjs/Api.js
CHANGED
|
@@ -77,7 +77,7 @@ var HotRequestHost = /** @class */ (function () {
|
|
|
77
77
|
return Utils.assign({}, apiDefaults, config);
|
|
78
78
|
};
|
|
79
79
|
HotRequestHost.prototype.computePath = function (path, config) {
|
|
80
|
-
return path.startsWith("/") ? path : "/"
|
|
80
|
+
return path.startsWith("/") ? path : "/".concat(path);
|
|
81
81
|
};
|
|
82
82
|
return HotRequestHost;
|
|
83
83
|
}());
|
package/cjs/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/cjs/Endpoint.js
CHANGED
|
@@ -62,7 +62,7 @@ var Endpoint = /** @class */ (function () {
|
|
|
62
62
|
mockingEnabled = (_a = (typeof apiMocking.enabled === "function" ? apiMocking.enabled() : apiMocking.enabled)) !== null && _a !== void 0 ? _a : false;
|
|
63
63
|
if (mockingEnabled) {
|
|
64
64
|
if (!((_b = this.mocking) === null || _b === void 0 ? void 0 : _b.handler)) {
|
|
65
|
-
throw new Error("[api-def] Endpoint for '"
|
|
65
|
+
throw new Error("[api-def] Endpoint for '".concat(this.path, "' has no mocking"));
|
|
66
66
|
}
|
|
67
67
|
mock = true;
|
|
68
68
|
}
|
|
@@ -72,16 +72,16 @@ var Endpoint = /** @class */ (function () {
|
|
|
72
72
|
});
|
|
73
73
|
};
|
|
74
74
|
Endpoint.prototype.computePath = function (path, request) {
|
|
75
|
-
var computedPath = path.startsWith("/") ? path : "/"
|
|
75
|
+
var computedPath = path.startsWith("/") ? path : "/".concat(path);
|
|
76
76
|
if (request.params) {
|
|
77
77
|
var keys = Object.keys(request.params);
|
|
78
78
|
for (var i = 0; i < keys.length; i++) {
|
|
79
79
|
var argName = keys[i];
|
|
80
|
-
computedPath = computedPath.replace(":"
|
|
80
|
+
computedPath = computedPath.replace(":".concat(argName), request.params[argName]);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
if (computedPath.includes(":")) {
|
|
84
|
-
throw new Error("[api-def] Not all path params have been resolved: '"
|
|
84
|
+
throw new Error("[api-def] Not all path params have been resolved: '".concat(computedPath, "'"));
|
|
85
85
|
}
|
|
86
86
|
return computedPath;
|
|
87
87
|
};
|
package/cjs/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/cjs/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/cjs/RequestContext.js
CHANGED
|
@@ -37,6 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
var Utils = require("./Utils");
|
|
40
|
+
var url_1 = require("url");
|
|
40
41
|
var contextIdCounter = 0;
|
|
41
42
|
var RequestContext = /** @class */ (function () {
|
|
42
43
|
function RequestContext(backend, host, config, computedPath, mocking) {
|
|
@@ -49,7 +50,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
49
50
|
this.id = contextIdCounter++;
|
|
50
51
|
this.host = host;
|
|
51
52
|
this.computedConfig = config;
|
|
52
|
-
Utils.assign({}, this.computedConfig.headers
|
|
53
|
+
Utils.assign({}, this.computedConfig.headers);
|
|
53
54
|
this.computedPath = computedPath;
|
|
54
55
|
this.key = this.generateKey();
|
|
55
56
|
this.stats = {
|
|
@@ -59,6 +60,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
59
60
|
this.eventHandlers = {};
|
|
60
61
|
this.mocking = mocking;
|
|
61
62
|
this.initMiddleware();
|
|
63
|
+
this.parseRequestBody();
|
|
62
64
|
}
|
|
63
65
|
Object.defineProperty(RequestContext.prototype, "method", {
|
|
64
66
|
get: function () {
|
|
@@ -111,7 +113,7 @@ var RequestContext = /** @class */ (function () {
|
|
|
111
113
|
var queryKeys = Object.keys(computedConfig.query);
|
|
112
114
|
for (var i = 0; i < queryKeys.length; i++) {
|
|
113
115
|
var queryKey = queryKeys[i];
|
|
114
|
-
queryStrings.push(queryKey
|
|
116
|
+
queryStrings.push("".concat(queryKey, "=").concat(computedConfig.query[queryKey]));
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
if (queryStrings.length > 0) {
|
|
@@ -121,8 +123,33 @@ var RequestContext = /** @class */ (function () {
|
|
|
121
123
|
};
|
|
122
124
|
RequestContext.prototype.updateHeaders = function (newHeaders) {
|
|
123
125
|
this.computedConfig.headers = Utils.assign({}, this.computedConfig.headers, newHeaders);
|
|
126
|
+
this.parseRequestBody();
|
|
124
127
|
return this;
|
|
125
128
|
};
|
|
129
|
+
RequestContext.prototype.parseRequestBody = function () {
|
|
130
|
+
if (this.computedConfig.body && this.computedConfig.headers) {
|
|
131
|
+
var contentTypeKey = Object.keys(this.computedConfig.headers).find(function (key) { return key.toLowerCase() === "content-type"; });
|
|
132
|
+
var contentType = contentTypeKey && this.computedConfig.headers[contentTypeKey];
|
|
133
|
+
if (typeof contentType === "string" && contentType.toLowerCase() === "multipart/form-data") {
|
|
134
|
+
var searchParams = new url_1.URLSearchParams();
|
|
135
|
+
for (var _i = 0, _a = Object.keys(this.computedConfig.body); _i < _a.length; _i++) {
|
|
136
|
+
var key = _a[_i];
|
|
137
|
+
var value = this.computedConfig.body[key];
|
|
138
|
+
searchParams.set(key, value === null || value === void 0 ? void 0 : value.toString());
|
|
139
|
+
}
|
|
140
|
+
this.parsedBody = searchParams.toString();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
this.parsedBody = this.computedConfig.body;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.parsedBody = undefined;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
RequestContext.prototype.getParsedBody = function () {
|
|
151
|
+
return this.parsedBody;
|
|
152
|
+
};
|
|
126
153
|
RequestContext.prototype.updateQuery = function (newQuery) {
|
|
127
154
|
this.computedConfig.query = Utils.assign(this.computedConfig.query || {}, newQuery);
|
|
128
155
|
return this;
|
|
@@ -164,6 +191,38 @@ var RequestContext = /** @class */ (function () {
|
|
|
164
191
|
this.canceler();
|
|
165
192
|
}
|
|
166
193
|
};
|
|
194
|
+
RequestContext.prototype.getRequestUrl = function () {
|
|
195
|
+
var _a;
|
|
196
|
+
var path = !this.baseUrl.endsWith("/")
|
|
197
|
+
? this.baseUrl + "/"
|
|
198
|
+
: this.baseUrl;
|
|
199
|
+
path += this.computedPath.startsWith("/")
|
|
200
|
+
? this.computedPath.substring(1)
|
|
201
|
+
: this.computedPath;
|
|
202
|
+
var origin = undefined;
|
|
203
|
+
if (typeof window !== "undefined") {
|
|
204
|
+
origin = window.origin;
|
|
205
|
+
}
|
|
206
|
+
if (!origin) {
|
|
207
|
+
if (path.indexOf("://") === -1) {
|
|
208
|
+
path = "https://".concat(path);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
var url = new URL(path, origin);
|
|
212
|
+
if (this.computedConfig.query) {
|
|
213
|
+
if (this.computedConfig.queryParser) {
|
|
214
|
+
url.search = this.computedConfig.queryParser(this.computedConfig.query);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
var queryKeys = Object.keys(this.computedConfig.query);
|
|
218
|
+
for (var i = 0; i < queryKeys.length; i++) {
|
|
219
|
+
var key = queryKeys[i];
|
|
220
|
+
url.searchParams.append(key, ((_a = this.computedConfig.query[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return url;
|
|
225
|
+
};
|
|
167
226
|
return RequestContext;
|
|
168
227
|
}());
|
|
169
228
|
exports.default = RequestContext;
|
package/cjs/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/cjs/RequestError.js
CHANGED
|
@@ -13,15 +13,21 @@ var isRequestError = function (error) {
|
|
|
13
13
|
};
|
|
14
14
|
exports.isRequestError = isRequestError;
|
|
15
15
|
var convertToRequestError = function (config) {
|
|
16
|
-
var error = config.error, response = config.response, code = config.code;
|
|
17
|
-
|
|
16
|
+
var error = config.error, context = config.context, response = config.response, code = config.code;
|
|
17
|
+
var resultError = Object.assign(error, {
|
|
18
18
|
name: "RequestError",
|
|
19
19
|
response: response,
|
|
20
20
|
code: code,
|
|
21
21
|
isRequestError: true,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
request: {
|
|
23
|
+
url: context.getRequestUrl().href,
|
|
24
|
+
query: context.computedConfig.query,
|
|
25
|
+
headers: context.computedConfig.headers,
|
|
26
|
+
body: context.getParsedBody(),
|
|
27
|
+
},
|
|
25
28
|
});
|
|
29
|
+
delete resultError.config;
|
|
30
|
+
delete resultError.toJSON;
|
|
31
|
+
return resultError;
|
|
26
32
|
};
|
|
27
33
|
exports.convertToRequestError = convertToRequestError;
|
package/cjs/Requester.js
CHANGED
|
@@ -156,11 +156,12 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
|
|
|
156
156
|
return [4 /*yield*/, parseResponse(context, response_1)];
|
|
157
157
|
case 3:
|
|
158
158
|
parsedResponse = (_b.sent());
|
|
159
|
-
if (!ApiUtils_1.isAcceptableStatus(parsedResponse.status, context.computedConfig.acceptableStatus)) {
|
|
160
|
-
throw RequestError_1.convertToRequestError({
|
|
161
|
-
error: new Error("[api-def] Invalid response status code '"
|
|
159
|
+
if (!(0, ApiUtils_1.isAcceptableStatus)(parsedResponse.status, context.computedConfig.acceptableStatus)) {
|
|
160
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
161
|
+
error: new Error("[api-def] Invalid response status code '".concat(parsedResponse.status, "'")),
|
|
162
162
|
response: parsedResponse,
|
|
163
163
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_STATUS,
|
|
164
|
+
context: context,
|
|
164
165
|
});
|
|
165
166
|
}
|
|
166
167
|
context.response = parsedResponse;
|
|
@@ -203,7 +204,7 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
|
|
|
203
204
|
}
|
|
204
205
|
});
|
|
205
206
|
}); };
|
|
206
|
-
return [4 /*yield*/, retry_1.default(performRequest, retryOpts)];
|
|
207
|
+
return [4 /*yield*/, (0, retry_1.default)(performRequest, retryOpts)];
|
|
207
208
|
case 2:
|
|
208
209
|
response = _b.sent();
|
|
209
210
|
return [2 /*return*/, (response)];
|
|
@@ -226,14 +227,15 @@ var parseResponse = function (context, response, error) { return __awaiter(void
|
|
|
226
227
|
return headers;
|
|
227
228
|
}, {});
|
|
228
229
|
contentType = parsedResponse_1.headers["content-type"];
|
|
229
|
-
inferredResponseType = ApiUtils_1.inferResponseType(contentType);
|
|
230
|
+
inferredResponseType = (0, ApiUtils_1.inferResponseType)(contentType);
|
|
230
231
|
if (!error) {
|
|
231
232
|
// expand to array buffer once we support that in inferResponseType
|
|
232
233
|
if (inferredResponseType === "text" && context.responseType === "json") {
|
|
233
|
-
throw RequestError_1.convertToRequestError({
|
|
234
|
-
error: new Error("[api-def] Expected '"
|
|
234
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
235
|
+
error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
|
|
235
236
|
code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
|
|
236
237
|
response: parsedResponse_1,
|
|
238
|
+
context: context,
|
|
237
239
|
});
|
|
238
240
|
}
|
|
239
241
|
// transform arrayBuffer to json
|
|
@@ -243,14 +245,15 @@ var parseResponse = function (context, response, error) { return __awaiter(void
|
|
|
243
245
|
data = response.data;
|
|
244
246
|
if (((_a = data.constructor) === null || _a === void 0 ? void 0 : _a.name) === "ArrayBuffer") {
|
|
245
247
|
try {
|
|
246
|
-
decodedData = (response.data = TextDecoding_1.textDecode(data));
|
|
248
|
+
decodedData = (response.data = (0, TextDecoding_1.textDecode)(data));
|
|
247
249
|
response.data = JSON.parse(decodedData);
|
|
248
250
|
}
|
|
249
251
|
catch (e) {
|
|
250
|
-
throw RequestError_1.convertToRequestError({
|
|
251
|
-
error: new Error("[api-def] Expected '"
|
|
252
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
253
|
+
error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
|
|
252
254
|
code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
|
|
253
255
|
response: parsedResponse_1,
|
|
256
|
+
context: context,
|
|
254
257
|
});
|
|
255
258
|
}
|
|
256
259
|
}
|
|
@@ -267,7 +270,7 @@ var parseError = function (context, rawError) { return __awaiter(void 0, void 0,
|
|
|
267
270
|
return __generator(this, function (_a) {
|
|
268
271
|
switch (_a.label) {
|
|
269
272
|
case 0:
|
|
270
|
-
if (!RequestError_1.isRequestError(rawError)) return [3 /*break*/, 1];
|
|
273
|
+
if (!(0, RequestError_1.isRequestError)(rawError)) return [3 /*break*/, 1];
|
|
271
274
|
error = rawError;
|
|
272
275
|
return [3 /*break*/, 5];
|
|
273
276
|
case 1: return [4 /*yield*/, context.backend.extractResponseFromError(rawError)];
|
|
@@ -280,14 +283,14 @@ var parseError = function (context, rawError) { return __awaiter(void 0, void 0,
|
|
|
280
283
|
errorResponse = _a.sent();
|
|
281
284
|
_a.label = 4;
|
|
282
285
|
case 4:
|
|
283
|
-
code = ApiUtils_1.isNetworkError(rawError) ? RequestError_1.RequestErrorCode.REQUEST_NETWORK_ERROR : RequestError_1.RequestErrorCode.MISC_UNKNOWN_ERROR;
|
|
286
|
+
code = (0, ApiUtils_1.isNetworkError)(rawError) ? RequestError_1.RequestErrorCode.REQUEST_NETWORK_ERROR : RequestError_1.RequestErrorCode.MISC_UNKNOWN_ERROR;
|
|
284
287
|
if (errorResponse) {
|
|
285
|
-
if (!ApiUtils_1.isAcceptableStatus(errorResponse.status, context.computedConfig.acceptableStatus)) {
|
|
288
|
+
if (!(0, ApiUtils_1.isAcceptableStatus)(errorResponse.status, context.computedConfig.acceptableStatus)) {
|
|
286
289
|
code = RequestError_1.RequestErrorCode.REQUEST_INVALID_STATUS;
|
|
287
290
|
}
|
|
288
291
|
}
|
|
289
292
|
errorInfo = context.backend.getErrorInfo(rawError, errorResponse);
|
|
290
|
-
error = RequestError_1.convertToRequestError(__assign({ error: rawError, response: errorResponse, code: code }, errorInfo));
|
|
293
|
+
error = (0, RequestError_1.convertToRequestError)(__assign({ error: rawError, response: errorResponse, code: code, context: context }, errorInfo));
|
|
291
294
|
_a.label = 5;
|
|
292
295
|
case 5: return [2 /*return*/, error];
|
|
293
296
|
}
|
|
@@ -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);
|
|
@@ -51,7 +51,7 @@ var AxiosRequestBackend = /** @class */ (function () {
|
|
|
51
51
|
AxiosRequestBackend.prototype.extractResponseFromError = function (error) {
|
|
52
52
|
return __awaiter(this, void 0, void 0, function () {
|
|
53
53
|
return __generator(this, function (_a) {
|
|
54
|
-
if (exports.isAxiosError(error)) {
|
|
54
|
+
if ((0, exports.isAxiosError)(error)) {
|
|
55
55
|
return [2 /*return*/, error.response ? error.response : null];
|
|
56
56
|
}
|
|
57
57
|
return [2 /*return*/, undefined];
|
|
@@ -77,7 +77,7 @@ var AxiosRequestBackend = /** @class */ (function () {
|
|
|
77
77
|
method: context.method,
|
|
78
78
|
baseURL: context.baseUrl,
|
|
79
79
|
url: context.computedPath,
|
|
80
|
-
data:
|
|
80
|
+
data: context.getParsedBody() || {},
|
|
81
81
|
params: computedConfig.query || {},
|
|
82
82
|
headers: computedConfig.headers || {},
|
|
83
83
|
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>;
|
|
@@ -64,7 +64,7 @@ var FetchError = /** @class */ (function (_super) {
|
|
|
64
64
|
}(Error));
|
|
65
65
|
var FetchRequestBackend = /** @class */ (function () {
|
|
66
66
|
function FetchRequestBackend(fetchLibrary) {
|
|
67
|
-
this.fetch = Utils_1.getGlobalFetch();
|
|
67
|
+
this.fetch = (0, Utils_1.getGlobalFetch)();
|
|
68
68
|
this.id = "fetch";
|
|
69
69
|
if (fetchLibrary !== undefined) {
|
|
70
70
|
this.fetch = fetchLibrary;
|
|
@@ -89,7 +89,7 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
89
89
|
switch (_b.label) {
|
|
90
90
|
case 0:
|
|
91
91
|
contentType = response.headers.get("Content-Type");
|
|
92
|
-
responseType = ApiUtils_1.inferResponseType(contentType);
|
|
92
|
+
responseType = (0, ApiUtils_1.inferResponseType)(contentType);
|
|
93
93
|
if (!!response.__text) return [3 /*break*/, 2];
|
|
94
94
|
_a = response;
|
|
95
95
|
return [4 /*yield*/, response.clone().text()];
|
|
@@ -115,7 +115,7 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
115
115
|
case 6: return [3 /*break*/, 8];
|
|
116
116
|
case 7:
|
|
117
117
|
error_1 = _b.sent();
|
|
118
|
-
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, "'")), {
|
|
119
119
|
response: response,
|
|
120
120
|
});
|
|
121
121
|
case 8: return [2 /*return*/, {
|
|
@@ -128,40 +128,17 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
128
128
|
});
|
|
129
129
|
};
|
|
130
130
|
FetchRequestBackend.prototype.makeRequest = function (context) {
|
|
131
|
-
var _a;
|
|
132
131
|
if (!this.fetch) {
|
|
133
132
|
throw new Error("[api-def] No fetch impl was provided to FetchRequestBackend");
|
|
134
133
|
}
|
|
135
134
|
var computedConfig = context.computedConfig;
|
|
136
|
-
var path = !context.baseUrl.endsWith("/")
|
|
137
|
-
? context.baseUrl + "/"
|
|
138
|
-
: context.baseUrl;
|
|
139
|
-
path += context.computedPath.startsWith("/")
|
|
140
|
-
? context.computedPath.substring(1)
|
|
141
|
-
: context.computedPath;
|
|
142
|
-
var origin = undefined;
|
|
143
|
-
if (typeof window !== "undefined") {
|
|
144
|
-
origin = window.origin;
|
|
145
|
-
}
|
|
146
|
-
var url = new URL(path, origin);
|
|
147
|
-
if (computedConfig.query) {
|
|
148
|
-
if (context.computedConfig.queryParser) {
|
|
149
|
-
url.search = context.computedConfig.queryParser(computedConfig.query);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
var queryKeys = Object.keys(computedConfig.query);
|
|
153
|
-
for (var i = 0; i < queryKeys.length; i++) {
|
|
154
|
-
var key = queryKeys[i];
|
|
155
|
-
url.searchParams.append(key, ((_a = computedConfig.query[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "");
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
135
|
// abort controller is a newer feature than fetch
|
|
160
136
|
var abortController = AbortController && new AbortController();
|
|
161
137
|
var abortSignal = abortController ? abortController.signal : undefined;
|
|
162
138
|
var softAbort = false;
|
|
163
139
|
var responded = false;
|
|
164
|
-
var
|
|
140
|
+
var body = context.getParsedBody();
|
|
141
|
+
var bodyJsonify = body !== null && typeof body === "object";
|
|
165
142
|
var headers = Utils.assign({
|
|
166
143
|
// logic from axios
|
|
167
144
|
"Content-Type": bodyJsonify ? "application/json;charset=utf-8" : "application/x-www-form-urlencoded",
|
|
@@ -173,9 +150,10 @@ var FetchRequestBackend = /** @class */ (function () {
|
|
|
173
150
|
}
|
|
174
151
|
return parsedHeaders;
|
|
175
152
|
}, {});
|
|
153
|
+
var url = context.getRequestUrl();
|
|
176
154
|
var promise = this.fetch(url.href, {
|
|
177
155
|
method: context.method,
|
|
178
|
-
body: bodyJsonify ? JSON.stringify(
|
|
156
|
+
body: bodyJsonify ? JSON.stringify(body) : body,
|
|
179
157
|
headers: parsedHeaders,
|
|
180
158
|
mode: "cors",
|
|
181
159
|
signal: abortSignal,
|
|
@@ -65,25 +65,27 @@ 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
|
+
context: context,
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
req = {
|
|
80
|
-
body: context.
|
|
81
|
+
body: context.getParsedBody(),
|
|
81
82
|
params: (_b = context.computedConfig.params) !== null && _b !== void 0 ? _b : {},
|
|
82
83
|
query: context.computedConfig.query,
|
|
83
84
|
headers: (_c = context.computedConfig.headers) !== null && _c !== void 0 ? _c : {},
|
|
84
85
|
};
|
|
85
86
|
res = {
|
|
86
87
|
statusCode: -1,
|
|
88
|
+
headers: {},
|
|
87
89
|
response: undefined,
|
|
88
90
|
status: function (statusCode) {
|
|
89
91
|
res.statusCode = statusCode;
|
|
@@ -91,6 +93,9 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
91
93
|
},
|
|
92
94
|
send: function (response) {
|
|
93
95
|
res.response = response;
|
|
96
|
+
if (response && typeof response === "object") {
|
|
97
|
+
res.headers["Content-Type"] = "application/json";
|
|
98
|
+
}
|
|
94
99
|
return res;
|
|
95
100
|
},
|
|
96
101
|
};
|
|
@@ -103,12 +108,13 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
103
108
|
else {
|
|
104
109
|
min = delay[0], max = delay[1];
|
|
105
110
|
if (min > max) {
|
|
106
|
-
throw RequestError_1.convertToRequestError({
|
|
111
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
107
112
|
error: new Error("[api-def] Min delay cannot be greater than max delay"),
|
|
108
113
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
114
|
+
context: context,
|
|
109
115
|
});
|
|
110
116
|
}
|
|
111
|
-
delayMs = Utils_1.randInt(min, max);
|
|
117
|
+
delayMs = (0, Utils_1.randInt)(min, max);
|
|
112
118
|
}
|
|
113
119
|
_e = Utils_1.delayThenReturn;
|
|
114
120
|
return [4 /*yield*/, mockingFunc(req, res)];
|
|
@@ -122,13 +128,18 @@ var MockRequestBackend = /** @class */ (function () {
|
|
|
122
128
|
_f.label = 5;
|
|
123
129
|
case 5:
|
|
124
130
|
if (res.response === undefined) {
|
|
125
|
-
throw RequestError_1.convertToRequestError({
|
|
131
|
+
throw (0, RequestError_1.convertToRequestError)({
|
|
126
132
|
error: new Error("[api-def] Mocked API did not respond"),
|
|
127
133
|
code: RequestError_1.RequestErrorCode.REQUEST_INVALID_CONFIG,
|
|
134
|
+
context: context,
|
|
128
135
|
});
|
|
129
136
|
}
|
|
137
|
+
parsedHeaders = Object.keys(res.headers).reduce(function (parsedHeaders, key) {
|
|
138
|
+
parsedHeaders[key] = res.headers[key].toString();
|
|
139
|
+
return parsedHeaders;
|
|
140
|
+
}, {});
|
|
130
141
|
return [2 /*return*/, {
|
|
131
|
-
headers:
|
|
142
|
+
headers: parsedHeaders,
|
|
132
143
|
data: res.response,
|
|
133
144
|
status: res.statusCode,
|
|
134
145
|
}];
|
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>;
|