api 5.0.0-beta.2 → 5.0.0
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/README.md +7 -8
- package/dist/bin.js +1 -1
- package/dist/cache.d.ts +38 -3
- package/dist/cache.js +7 -26
- package/dist/cli/codegen/index.d.ts +1 -1
- package/dist/cli/codegen/language.d.ts +1 -1
- package/dist/cli/codegen/language.js +13 -0
- package/dist/cli/codegen/languages/typescript/util.d.ts +21 -0
- package/dist/cli/codegen/languages/typescript/util.js +185 -0
- package/dist/cli/codegen/languages/typescript.d.ts +36 -41
- package/dist/cli/codegen/languages/typescript.js +394 -414
- package/dist/cli/commands/install.js +6 -6
- package/dist/cli/storage.d.ts +1 -1
- package/dist/cli/storage.js +2 -2
- package/dist/core/errors/fetchError.d.ts +12 -0
- package/dist/core/errors/fetchError.js +36 -0
- package/dist/core/getJSONSchemaDefaults.d.ts +1 -1
- package/dist/core/index.d.ts +12 -4
- package/dist/core/index.js +36 -11
- package/dist/core/parseResponse.d.ts +6 -1
- package/dist/core/parseResponse.js +9 -3
- package/dist/core/prepareAuth.js +47 -18
- package/dist/core/prepareParams.d.ts +0 -3
- package/dist/core/prepareParams.js +102 -41
- package/dist/fetcher.d.ts +1 -1
- package/dist/fetcher.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -40
- package/dist/packageInfo.d.ts +1 -1
- package/dist/packageInfo.js +1 -1
- package/package.json +31 -17
- package/src/bin.ts +2 -1
- package/src/cache.ts +9 -31
- package/src/cli/codegen/index.ts +1 -1
- package/src/cli/codegen/language.ts +18 -1
- package/src/cli/codegen/languages/typescript/util.ts +183 -0
- package/src/cli/codegen/languages/typescript.ts +348 -340
- package/src/cli/commands/install.ts +6 -8
- package/src/cli/storage.ts +4 -4
- package/src/core/errors/fetchError.ts +31 -0
- package/src/core/getJSONSchemaDefaults.ts +3 -2
- package/src/core/index.ts +53 -18
- package/src/core/parseResponse.ts +8 -2
- package/src/core/prepareAuth.ts +55 -31
- package/src/core/prepareParams.ts +112 -41
- package/src/fetcher.ts +5 -4
- package/src/index.ts +24 -32
- package/src/packageInfo.ts +1 -1
- package/src/typings.d.ts +0 -1
- package/tsconfig.json +1 -1
|
@@ -40,15 +40,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
40
40
|
};
|
|
41
41
|
exports.__esModule = true;
|
|
42
42
|
var commander_1 = require("commander");
|
|
43
|
-
var
|
|
43
|
+
var figures_1 = __importDefault(require("figures"));
|
|
44
44
|
var oas_1 = __importDefault(require("oas"));
|
|
45
|
-
var
|
|
45
|
+
var ora_1 = __importDefault(require("ora"));
|
|
46
|
+
var validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
46
47
|
var fetcher_1 = __importDefault(require("../../fetcher"));
|
|
47
|
-
var
|
|
48
|
-
var logger_1 = __importDefault(require("../logger"));
|
|
48
|
+
var codegen_1 = __importDefault(require("../codegen"));
|
|
49
49
|
var prompt_1 = __importDefault(require("../lib/prompt"));
|
|
50
|
-
var
|
|
51
|
-
var
|
|
50
|
+
var logger_1 = __importDefault(require("../logger"));
|
|
51
|
+
var storage_1 = __importDefault(require("../storage"));
|
|
52
52
|
// @todo log logs to `.api/.logs` and have `.logs` ignored
|
|
53
53
|
var cmd = new commander_1.Command();
|
|
54
54
|
cmd
|
package/dist/cli/storage.d.ts
CHANGED
package/dist/cli/storage.js
CHANGED
|
@@ -39,12 +39,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
40
|
};
|
|
41
41
|
exports.__esModule = true;
|
|
42
|
-
var ssri_1 = __importDefault(require("ssri"));
|
|
43
42
|
var fs_1 = __importDefault(require("fs"));
|
|
44
43
|
var path_1 = __importDefault(require("path"));
|
|
45
44
|
var make_dir_1 = __importDefault(require("make-dir"));
|
|
46
|
-
var
|
|
45
|
+
var ssri_1 = __importDefault(require("ssri"));
|
|
47
46
|
var fetcher_1 = __importDefault(require("../fetcher"));
|
|
47
|
+
var packageInfo_1 = require("../packageInfo");
|
|
48
48
|
var Storage = /** @class */ (function () {
|
|
49
49
|
function Storage(source, identifier) {
|
|
50
50
|
Storage.setStorageDir();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare class FetchError extends Error {
|
|
2
|
+
/** HTTP Status */
|
|
3
|
+
status: number;
|
|
4
|
+
/** The content of the response. */
|
|
5
|
+
data: unknown;
|
|
6
|
+
/** The Headers of the response. */
|
|
7
|
+
headers: Headers;
|
|
8
|
+
/** The raw `Response` object. */
|
|
9
|
+
res: Response;
|
|
10
|
+
constructor(status: number, data: unknown, headers: Headers, res: Response);
|
|
11
|
+
}
|
|
12
|
+
export default FetchError;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
exports.__esModule = true;
|
|
18
|
+
var FetchError = /** @class */ (function (_super) {
|
|
19
|
+
__extends(FetchError, _super);
|
|
20
|
+
function FetchError(status, data, headers, res) {
|
|
21
|
+
var _this = _super.call(this, res.statusText) || this;
|
|
22
|
+
_this.name = 'FetchError';
|
|
23
|
+
_this.status = status;
|
|
24
|
+
_this.data = data;
|
|
25
|
+
_this.headers = headers;
|
|
26
|
+
_this.res = res;
|
|
27
|
+
// We could fix this by updating our target to ES2015 but because we support exporting to CJS
|
|
28
|
+
// we can't.
|
|
29
|
+
//
|
|
30
|
+
// https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript/
|
|
31
|
+
Object.setPrototypeOf(_this, FetchError.prototype);
|
|
32
|
+
return _this;
|
|
33
|
+
}
|
|
34
|
+
return FetchError;
|
|
35
|
+
}(Error));
|
|
36
|
+
exports["default"] = FetchError;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SchemaWrapper } from 'oas
|
|
1
|
+
import type { SchemaWrapper } from 'oas/dist/operation/get-parameters-as-json-schema';
|
|
2
2
|
/**
|
|
3
3
|
* Run through a JSON Schema object and compose up an object containing default data for any schema
|
|
4
4
|
* property that is required and also has a defined default.
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type Oas from 'oas';
|
|
2
2
|
import type { Operation } from 'oas';
|
|
3
|
-
import type { HttpMethods } from 'oas
|
|
3
|
+
import type { HttpMethods } from 'oas/dist/rmoas.types';
|
|
4
4
|
import 'isomorphic-fetch';
|
|
5
5
|
import getJSONSchemaDefaults from './getJSONSchemaDefaults';
|
|
6
6
|
import parseResponse from './parseResponse';
|
|
@@ -9,11 +9,19 @@ import prepareParams from './prepareParams';
|
|
|
9
9
|
import prepareServer from './prepareServer';
|
|
10
10
|
export interface ConfigOptions {
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Override the default `fetch` request timeout of 30 seconds. This number should be represented
|
|
13
|
+
* in milliseconds.
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
timeout?: number;
|
|
16
16
|
}
|
|
17
|
+
export declare type FetchResponse<status, data> = {
|
|
18
|
+
data: data;
|
|
19
|
+
status: status;
|
|
20
|
+
headers: Headers;
|
|
21
|
+
res: Response;
|
|
22
|
+
};
|
|
23
|
+
declare type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : Enumerate<N, [...Acc, Acc['length']]>;
|
|
24
|
+
export declare type HTTPMethodRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
|
|
17
25
|
export { getJSONSchemaDefaults, parseResponse, prepareAuth, prepareParams, prepareServer };
|
|
18
26
|
export default class APICore {
|
|
19
27
|
spec: Oas;
|
package/dist/core/index.js
CHANGED
|
@@ -51,10 +51,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
51
51
|
};
|
|
52
52
|
exports.__esModule = true;
|
|
53
53
|
exports.prepareServer = exports.prepareParams = exports.prepareAuth = exports.parseResponse = exports.getJSONSchemaDefaults = void 0;
|
|
54
|
-
require("isomorphic-fetch");
|
|
55
|
-
var fetch_har_1 = __importDefault(require("fetch-har"));
|
|
56
54
|
var oas_to_har_1 = __importDefault(require("@readme/oas-to-har"));
|
|
55
|
+
var fetch_har_1 = __importDefault(require("fetch-har"));
|
|
57
56
|
var form_data_encoder_1 = require("form-data-encoder");
|
|
57
|
+
require("isomorphic-fetch");
|
|
58
|
+
// `AbortController` was shipped in Node 15 so when Node 14 is EOL'd we can drop this dependency.
|
|
59
|
+
var node_abort_controller_1 = require("node-abort-controller");
|
|
60
|
+
var fetchError_1 = __importDefault(require("./errors/fetchError"));
|
|
58
61
|
var getJSONSchemaDefaults_1 = __importDefault(require("./getJSONSchemaDefaults"));
|
|
59
62
|
exports.getJSONSchemaDefaults = getJSONSchemaDefaults_1["default"];
|
|
60
63
|
var parseResponse_1 = __importDefault(require("./parseResponse"));
|
|
@@ -69,7 +72,7 @@ var APICore = /** @class */ (function () {
|
|
|
69
72
|
function APICore(spec, userAgent) {
|
|
70
73
|
this.auth = [];
|
|
71
74
|
this.server = false;
|
|
72
|
-
this.config = {
|
|
75
|
+
this.config = {};
|
|
73
76
|
this.spec = spec;
|
|
74
77
|
this.userAgent = userAgent;
|
|
75
78
|
}
|
|
@@ -121,18 +124,40 @@ var APICore = /** @class */ (function () {
|
|
|
121
124
|
data.server = preparedServer;
|
|
122
125
|
}
|
|
123
126
|
}
|
|
127
|
+
// @ts-expect-error `this.auth` typing is off. FIXME
|
|
124
128
|
var har = (0, oas_to_har_1["default"])(_this.spec, operation, data, (0, prepareAuth_1["default"])(_this.auth, operation));
|
|
129
|
+
var timeoutSignal;
|
|
130
|
+
var init = {};
|
|
131
|
+
if (_this.config.timeout) {
|
|
132
|
+
var controller_1 = new node_abort_controller_1.AbortController();
|
|
133
|
+
timeoutSignal = setTimeout(function () { return controller_1.abort(); }, _this.config.timeout);
|
|
134
|
+
// @todo Typing on `AbortController` coming out of `node-abort-controler` isn't right so when
|
|
135
|
+
// we eventually drop that dependency we can remove the `as any` here.
|
|
136
|
+
init.signal = controller_1.signal;
|
|
137
|
+
}
|
|
125
138
|
return (0, fetch_har_1["default"])(har, {
|
|
126
|
-
userAgent: _this.userAgent,
|
|
127
139
|
files: data.files || {},
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
init: init,
|
|
141
|
+
multipartEncoder: form_data_encoder_1.FormDataEncoder,
|
|
142
|
+
userAgent: _this.userAgent
|
|
143
|
+
})
|
|
144
|
+
.then(function (res) { return __awaiter(_this, void 0, void 0, function () {
|
|
145
|
+
var parsed;
|
|
146
|
+
return __generator(this, function (_a) {
|
|
147
|
+
switch (_a.label) {
|
|
148
|
+
case 0: return [4 /*yield*/, (0, parseResponse_1["default"])(res)];
|
|
149
|
+
case 1:
|
|
150
|
+
parsed = _a.sent();
|
|
151
|
+
if (res.status >= 400 && res.status <= 599) {
|
|
152
|
+
throw new fetchError_1["default"](parsed.status, parsed.data, parsed.headers, parsed.res);
|
|
153
|
+
}
|
|
154
|
+
return [2 /*return*/, parsed];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}); })["finally"](function () {
|
|
158
|
+
if (_this.config.timeout) {
|
|
159
|
+
clearTimeout(timeoutSignal);
|
|
132
160
|
}
|
|
133
|
-
if (_this.config.parseResponse === false)
|
|
134
|
-
return res;
|
|
135
|
-
return (0, parseResponse_1["default"])(res);
|
|
136
161
|
});
|
|
137
162
|
})];
|
|
138
163
|
});
|
|
@@ -40,7 +40,7 @@ var oas_1 = require("oas");
|
|
|
40
40
|
var matchesMimeType = oas_1.utils.matchesMimeType;
|
|
41
41
|
function getResponseBody(response) {
|
|
42
42
|
return __awaiter(this, void 0, void 0, function () {
|
|
43
|
-
var contentType, isJSON, responseBody;
|
|
43
|
+
var contentType, isJSON, responseBody, data;
|
|
44
44
|
return __generator(this, function (_a) {
|
|
45
45
|
switch (_a.label) {
|
|
46
46
|
case 0:
|
|
@@ -49,15 +49,21 @@ function getResponseBody(response) {
|
|
|
49
49
|
return [4 /*yield*/, response.text()];
|
|
50
50
|
case 1:
|
|
51
51
|
responseBody = _a.sent();
|
|
52
|
+
data = responseBody;
|
|
52
53
|
if (isJSON) {
|
|
53
54
|
try {
|
|
54
|
-
|
|
55
|
+
data = JSON.parse(responseBody);
|
|
55
56
|
}
|
|
56
57
|
catch (e) {
|
|
57
58
|
// If our JSON parsing failed then we can just return plaintext instead.
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
|
-
return [2 /*return*/,
|
|
61
|
+
return [2 /*return*/, {
|
|
62
|
+
data: data,
|
|
63
|
+
status: response.status,
|
|
64
|
+
headers: response.headers,
|
|
65
|
+
res: response
|
|
66
|
+
}];
|
|
61
67
|
}
|
|
62
68
|
});
|
|
63
69
|
});
|
package/dist/core/prepareAuth.js
CHANGED
|
@@ -5,19 +5,57 @@ function prepareAuth(authKey, operation) {
|
|
|
5
5
|
return {};
|
|
6
6
|
}
|
|
7
7
|
var preparedAuth = {};
|
|
8
|
-
var security = operation.
|
|
9
|
-
|
|
10
|
-
if (securitySchemes.length === 0) {
|
|
8
|
+
var security = operation.getSecurity();
|
|
9
|
+
if (security.length === 0) {
|
|
11
10
|
// If there's no auth configured on this operation, don't prepare anything (even if it was
|
|
12
11
|
// supplied by the user).
|
|
13
12
|
return {};
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
throw new Error("Sorry, this API currently requires multiple forms of authentication which we don't yet support.");
|
|
14
|
+
// Does this operation require multiple forms of auth?
|
|
15
|
+
if (security.every(function (s) { return Object.keys(s).length > 1; })) {
|
|
16
|
+
throw new Error("Sorry, this operation currently requires multiple forms of authentication which this library doesn't yet support.");
|
|
19
17
|
}
|
|
20
|
-
|
|
18
|
+
// Since we can only handle single auth security configurations, let's pull those out. This code
|
|
19
|
+
// is a bit opaque but `security` here may look like `[{ basic: [] }, { oauth2: [], basic: []}]`
|
|
20
|
+
// and are filtering it down to only single-auth requirements of `[{ basic: [] }]`.
|
|
21
|
+
var usableSecurity = security
|
|
22
|
+
.map(function (s) {
|
|
23
|
+
return Object.keys(s).length === 1 ? s : false;
|
|
24
|
+
})
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
var usableSecuritySchemes = usableSecurity.map(function (s) { return Object.keys(s); }).reduce(function (prev, next) { return prev.concat(next); }, []);
|
|
27
|
+
var preparedSecurity = operation.prepareSecurity();
|
|
28
|
+
// If we have two auth tokens present let's look for Basic Auth in their configuration.
|
|
29
|
+
if (authKey.length >= 2) {
|
|
30
|
+
// If this operation doesn't support HTTP Basic auth but we have two tokens, that's a paddlin.
|
|
31
|
+
if (!('Basic' in preparedSecurity)) {
|
|
32
|
+
throw new Error('Multiple auth tokens were supplied for this endpoint but only a single token is needed.');
|
|
33
|
+
}
|
|
34
|
+
// If we have two auth keys for Basic Auth but Basic isn't a usable security scheme (maybe it's
|
|
35
|
+
// part of an AND or auth configuration -- which we don't support) then we need to error out.
|
|
36
|
+
var schemes_1 = preparedSecurity.Basic.filter(function (s) { return usableSecuritySchemes.includes(s._key); });
|
|
37
|
+
if (!schemes_1.length) {
|
|
38
|
+
throw new Error('Credentials for Basic Authentication were supplied but this operation requires another form of auth in that case, which this library does not yet support. This operation does, however, allow supplying a single auth token.');
|
|
39
|
+
}
|
|
40
|
+
var scheme_1 = schemes_1.shift();
|
|
41
|
+
preparedAuth[scheme_1._key] = {
|
|
42
|
+
user: authKey[0],
|
|
43
|
+
pass: authKey.length === 2 ? authKey[1] : ''
|
|
44
|
+
};
|
|
45
|
+
return preparedAuth;
|
|
46
|
+
}
|
|
47
|
+
// If we know we don't need to use HTTP Basic auth because we have a username+password then we
|
|
48
|
+
// can pick the first usable security scheme available and try to use that. This might not always
|
|
49
|
+
// be the auth scheme that the user wants, but we don't have any other way for the user to tell
|
|
50
|
+
// us what they want with the current `sdk.auth()` API.
|
|
51
|
+
var usableScheme = usableSecuritySchemes[0];
|
|
52
|
+
var schemes = Object.entries(preparedSecurity)
|
|
53
|
+
.map(function (_a) {
|
|
54
|
+
var ps = _a[1];
|
|
55
|
+
return ps.filter(function (s) { return usableScheme === s._key; });
|
|
56
|
+
})
|
|
57
|
+
.reduce(function (prev, next) { return prev.concat(next); }, []);
|
|
58
|
+
var scheme = schemes.shift();
|
|
21
59
|
switch (scheme.type) {
|
|
22
60
|
case 'http':
|
|
23
61
|
if (scheme.scheme === 'basic') {
|
|
@@ -27,28 +65,19 @@ function prepareAuth(authKey, operation) {
|
|
|
27
65
|
};
|
|
28
66
|
}
|
|
29
67
|
else if (scheme.scheme === 'bearer') {
|
|
30
|
-
if (authKey.length > 1) {
|
|
31
|
-
throw new Error('Multiple auth tokens were supplied for the auth on this endpoint, but only a single token is needed.');
|
|
32
|
-
}
|
|
33
68
|
preparedAuth[scheme._key] = authKey[0];
|
|
34
69
|
}
|
|
35
70
|
break;
|
|
36
71
|
case 'oauth2':
|
|
37
|
-
if (authKey.length > 1) {
|
|
38
|
-
throw new Error('Multiple auth tokens were supplied for the auth on this endpoint, but only a single token is needed.');
|
|
39
|
-
}
|
|
40
72
|
preparedAuth[scheme._key] = authKey[0];
|
|
41
73
|
break;
|
|
42
74
|
case 'apiKey':
|
|
43
|
-
if (authKey.length > 1) {
|
|
44
|
-
throw new Error('Multiple auth keys were supplied for the auth on this endpoint, but only a single key is needed.');
|
|
45
|
-
}
|
|
46
75
|
if (scheme["in"] === 'query' || scheme["in"] === 'header' || scheme["in"] === 'cookie') {
|
|
47
76
|
preparedAuth[scheme._key] = authKey[0];
|
|
48
77
|
}
|
|
49
78
|
break;
|
|
50
79
|
default:
|
|
51
|
-
throw new Error("Sorry, this API currently
|
|
80
|
+
throw new Error("Sorry, this API currently uses a security scheme, ".concat(scheme.type, ", which this library doesn't yet support."));
|
|
52
81
|
}
|
|
53
82
|
return preparedAuth;
|
|
54
83
|
}
|
|
@@ -5,9 +5,6 @@ import type { Operation } from 'oas';
|
|
|
5
5
|
* operation to see what's what and prepare any available parameters to be used in an API request
|
|
6
6
|
* with `@readme/oas-to-har`.
|
|
7
7
|
*
|
|
8
|
-
* @param operation
|
|
9
|
-
* @param body
|
|
10
|
-
* @param metadata
|
|
11
8
|
*/
|
|
12
9
|
export default function prepareParams(operation: Operation, body?: unknown, metadata?: Record<string, unknown>): Promise<{
|
|
13
10
|
body?: any;
|
|
@@ -39,21 +39,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
40
|
};
|
|
41
41
|
exports.__esModule = true;
|
|
42
|
-
var lodash_merge_1 = __importDefault(require("lodash.merge"));
|
|
43
42
|
var promises_1 = __importDefault(require("fs/promises"));
|
|
44
43
|
var path_1 = __importDefault(require("path"));
|
|
45
44
|
var stream_1 = __importDefault(require("stream"));
|
|
46
|
-
var
|
|
47
|
-
var sync_1 = __importDefault(require("datauri/sync"));
|
|
45
|
+
var caseless_1 = __importDefault(require("caseless"));
|
|
48
46
|
var parser_1 = __importDefault(require("datauri/parser"));
|
|
47
|
+
var sync_1 = __importDefault(require("datauri/sync"));
|
|
48
|
+
var get_stream_1 = __importDefault(require("get-stream"));
|
|
49
|
+
var lodash_merge_1 = __importDefault(require("lodash.merge"));
|
|
50
|
+
var remove_undefined_objects_1 = __importDefault(require("remove-undefined-objects"));
|
|
49
51
|
var getJSONSchemaDefaults_1 = __importDefault(require("./getJSONSchemaDefaults"));
|
|
52
|
+
// These headers are normally only defined by the OpenAPI definition but we allow the user to
|
|
53
|
+
// manually supply them in their `metadata` parameter if they wish.
|
|
54
|
+
var specialHeaders = ['accept', 'authorization'];
|
|
50
55
|
/**
|
|
51
56
|
* Extract all available parameters from an operations Parameter Object into a digestable array
|
|
52
57
|
* that we can use to apply to the request.
|
|
53
58
|
*
|
|
54
59
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameterObject}
|
|
55
60
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameterObject}
|
|
56
|
-
* @param parameters
|
|
57
61
|
*/
|
|
58
62
|
function digestParameters(parameters) {
|
|
59
63
|
return parameters.reduce(function (prev, param) {
|
|
@@ -94,8 +98,6 @@ function merge(src, target) {
|
|
|
94
98
|
* Ingest a file path or readable stream into a common object that we can later use to process it
|
|
95
99
|
* into a parameters object for making an API request.
|
|
96
100
|
*
|
|
97
|
-
* @param paramName
|
|
98
|
-
* @param file
|
|
99
101
|
*/
|
|
100
102
|
function processFile(paramName, file) {
|
|
101
103
|
if (typeof file === 'string') {
|
|
@@ -149,23 +151,48 @@ function processFile(paramName, file) {
|
|
|
149
151
|
* operation to see what's what and prepare any available parameters to be used in an API request
|
|
150
152
|
* with `@readme/oas-to-har`.
|
|
151
153
|
*
|
|
152
|
-
* @param operation
|
|
153
|
-
* @param body
|
|
154
|
-
* @param metadata
|
|
155
154
|
*/
|
|
156
155
|
function prepareParams(operation, body, metadata) {
|
|
157
156
|
var _a, _b, _c, _d;
|
|
158
157
|
return __awaiter(this, void 0, void 0, function () {
|
|
159
|
-
var metadataIntersected, digestedParameters,
|
|
158
|
+
var metadataIntersected, digestedParameters, jsonSchema, throwNoParamsError, bodyParams_1, jsonSchemaDefaults, params, headerParams_1, intersection, payloadJsonSchema, conversions_1;
|
|
160
159
|
return __generator(this, function (_e) {
|
|
161
160
|
switch (_e.label) {
|
|
162
161
|
case 0:
|
|
163
162
|
metadataIntersected = false;
|
|
164
163
|
digestedParameters = digestParameters(operation.getParameters());
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
jsonSchema = operation.getParametersAsJSONSchema();
|
|
165
|
+
/**
|
|
166
|
+
* It might be common for somebody to run `sdk.findPetsByStatus({ status: 'available' }, {})`, in
|
|
167
|
+
* which case we want to filter out the second (metadata) parameter and treat the first parameter
|
|
168
|
+
* as the metadata instead. If we don't do this, their supplied `status` metadata will be treated
|
|
169
|
+
* as a body parameter, and because there's no `status` body parameter, and no supplied metadata
|
|
170
|
+
* (because it's an empty object), the request won't send a payload.
|
|
171
|
+
*
|
|
172
|
+
* @see {@link https://github.com/readmeio/api/issues/449}
|
|
173
|
+
*/
|
|
174
|
+
// eslint-disable-next-line no-param-reassign
|
|
175
|
+
metadata = (0, remove_undefined_objects_1["default"])(metadata);
|
|
167
176
|
if (!jsonSchema && (body !== undefined || metadata !== undefined)) {
|
|
168
|
-
|
|
177
|
+
throwNoParamsError = true;
|
|
178
|
+
// If this operation doesn't have any parameters for us to transform to JSON Schema but they've
|
|
179
|
+
// sent us either an `Accept` or `Authorization` header (or both) we should let them do that.
|
|
180
|
+
// We should, however, only do this check for the `body` parameter as if they've sent this
|
|
181
|
+
// request both `body` and `metadata` we can reject it outright as the operation won't have any
|
|
182
|
+
// body data.
|
|
183
|
+
if (body !== undefined) {
|
|
184
|
+
if (typeof body === 'object' && body !== null && !Array.isArray(body)) {
|
|
185
|
+
if (Object.keys(body).length <= 2) {
|
|
186
|
+
bodyParams_1 = (0, caseless_1["default"])(body);
|
|
187
|
+
if (specialHeaders.some(function (header) { return bodyParams_1.has(header); })) {
|
|
188
|
+
throwNoParamsError = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (throwNoParamsError) {
|
|
194
|
+
throw new Error("You supplied metadata and/or body data for this operation but it doesn't have any documented parameters or request payloads. If you think this is an error please contact support for the API you're using.");
|
|
195
|
+
}
|
|
169
196
|
}
|
|
170
197
|
jsonSchemaDefaults = jsonSchema ? (0, getJSONSchemaDefaults_1["default"])(jsonSchema) : {};
|
|
171
198
|
params = jsonSchemaDefaults;
|
|
@@ -179,31 +206,43 @@ function prepareParams(operation, body, metadata) {
|
|
|
179
206
|
params.body = merge(params.body, body);
|
|
180
207
|
}
|
|
181
208
|
else if (typeof metadata === 'undefined') {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// isn't anything we can do about it.
|
|
190
|
-
params.body = merge(params.body, body);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
intersection = Object.keys(body).filter(function (value) { return Object.keys(digestedParameters).includes(value); }).length;
|
|
194
|
-
if (intersection && intersection / Object.keys(body).length > 0.25) {
|
|
195
|
-
/* eslint-disable no-param-reassign */
|
|
196
|
-
// If more than 25% of the body intersects with the parameters that we've got on hand,
|
|
197
|
-
// then we should treat it as a metadata object and organize into parameters.
|
|
198
|
-
metadataIntersected = true;
|
|
199
|
-
metadata = merge(params.body, body);
|
|
200
|
-
body = undefined;
|
|
201
|
-
/* eslint-enable no-param-reassign */
|
|
209
|
+
headerParams_1 = (0, caseless_1["default"])({});
|
|
210
|
+
Object.entries(digestedParameters).forEach(function (_a) {
|
|
211
|
+
var paramName = _a[0], param = _a[1];
|
|
212
|
+
// Headers are sent case-insensitive so we need to make sure that we're properly
|
|
213
|
+
// matching them when detecting what our incoming payload looks like.
|
|
214
|
+
if (param["in"] === 'header') {
|
|
215
|
+
headerParams_1.set(paramName, '');
|
|
202
216
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
217
|
+
});
|
|
218
|
+
// `Accept` and `Authorization` headers can't be defined as normal parameters but we should
|
|
219
|
+
// always allow the user to supply them if they wish.
|
|
220
|
+
specialHeaders.forEach(function (header) {
|
|
221
|
+
if (!headerParams_1.has(header)) {
|
|
222
|
+
headerParams_1.set(header, '');
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
intersection = Object.keys(body).filter(function (value) {
|
|
226
|
+
if (Object.keys(digestedParameters).includes(value)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
else if (headerParams_1.has(value)) {
|
|
230
|
+
return true;
|
|
206
231
|
}
|
|
232
|
+
return false;
|
|
233
|
+
}).length;
|
|
234
|
+
if (intersection && intersection / Object.keys(body).length > 0.25) {
|
|
235
|
+
/* eslint-disable no-param-reassign */
|
|
236
|
+
// If more than 25% of the body intersects with the parameters that we've got on hand,
|
|
237
|
+
// then we should treat it as a metadata object and organize into parameters.
|
|
238
|
+
metadataIntersected = true;
|
|
239
|
+
metadata = merge(params.body, body);
|
|
240
|
+
body = undefined;
|
|
241
|
+
/* eslint-enable no-param-reassign */
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// For all other cases, we should just treat the supplied body as a body.
|
|
245
|
+
params.body = merge(params.body, body);
|
|
207
246
|
}
|
|
208
247
|
}
|
|
209
248
|
else {
|
|
@@ -278,7 +317,7 @@ function prepareParams(operation, body, metadata) {
|
|
|
278
317
|
// Only spend time trying to organize metadata into parameters if we were able to digest
|
|
279
318
|
// parameters out of the operation schema. If we couldn't digest anything, but metadata was
|
|
280
319
|
// supplied then we wouldn't know how to send it in the request!
|
|
281
|
-
if (
|
|
320
|
+
if (typeof metadata !== 'undefined') {
|
|
282
321
|
if (!('cookie' in params))
|
|
283
322
|
params.cookie = {};
|
|
284
323
|
if (!('header' in params))
|
|
@@ -290,8 +329,17 @@ function prepareParams(operation, body, metadata) {
|
|
|
290
329
|
Object.entries(digestedParameters).forEach(function (_a) {
|
|
291
330
|
var paramName = _a[0], param = _a[1];
|
|
292
331
|
var value;
|
|
293
|
-
|
|
294
|
-
|
|
332
|
+
var metadataHeaderParam;
|
|
333
|
+
if (typeof metadata === 'object' && !isEmpty(metadata)) {
|
|
334
|
+
if (paramName in metadata) {
|
|
335
|
+
value = metadata[paramName];
|
|
336
|
+
}
|
|
337
|
+
else if (param["in"] === 'header') {
|
|
338
|
+
// Headers are sent case-insensitive so we need to make sure that we're properly
|
|
339
|
+
// matching them when detecting what our incoming payload looks like.
|
|
340
|
+
metadataHeaderParam = Object.keys(metadata).find(function (k) { return k.toLowerCase() === paramName.toLowerCase(); });
|
|
341
|
+
value = metadata[metadataHeaderParam];
|
|
342
|
+
}
|
|
295
343
|
}
|
|
296
344
|
if (value === undefined) {
|
|
297
345
|
return;
|
|
@@ -307,8 +355,8 @@ function prepareParams(operation, body, metadata) {
|
|
|
307
355
|
delete metadata[paramName];
|
|
308
356
|
break;
|
|
309
357
|
case 'header':
|
|
310
|
-
params.header[paramName] = value;
|
|
311
|
-
delete metadata[
|
|
358
|
+
params.header[paramName.toLowerCase()] = value;
|
|
359
|
+
delete metadata[metadataHeaderParam];
|
|
312
360
|
break;
|
|
313
361
|
case 'cookie':
|
|
314
362
|
params.cookie[paramName] = value;
|
|
@@ -332,6 +380,19 @@ function prepareParams(operation, body, metadata) {
|
|
|
332
380
|
if (operation.isFormUrlEncoded()) {
|
|
333
381
|
params.formData = merge(params.formData, metadata);
|
|
334
382
|
}
|
|
383
|
+
else if (typeof metadata === 'object') {
|
|
384
|
+
// If the user supplied an `accept` or `authorization` header themselves we should allow it
|
|
385
|
+
// through. Normally these headers are automatically handled by `@readme/oas-to-har` but in
|
|
386
|
+
// the event that maybe the user wants to return XML for an API that normally returns JSON
|
|
387
|
+
// or specify a custom auth header (maybe we can't handle their auth case right) this is the
|
|
388
|
+
// only way with this library that they can do that.
|
|
389
|
+
specialHeaders.forEach(function (headerName) {
|
|
390
|
+
var headerParam = Object.keys(metadata).find(function (m) { return m.toLowerCase() === headerName; });
|
|
391
|
+
if (headerParam) {
|
|
392
|
+
params.header[headerName] = metadata[headerParam];
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
335
396
|
else {
|
|
336
397
|
// Any other remaining unused metadata will be unused because we don't know where to place
|
|
337
398
|
// it in the request.
|
package/dist/fetcher.d.ts
CHANGED
package/dist/fetcher.js
CHANGED
|
@@ -39,11 +39,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
40
|
};
|
|
41
41
|
exports.__esModule = true;
|
|
42
|
-
require("isomorphic-fetch");
|
|
43
|
-
var openapi_parser_1 = __importDefault(require("@readme/openapi-parser"));
|
|
44
|
-
var js_yaml_1 = __importDefault(require("js-yaml"));
|
|
45
42
|
var fs_1 = __importDefault(require("fs"));
|
|
46
43
|
var path_1 = __importDefault(require("path"));
|
|
44
|
+
var openapi_parser_1 = __importDefault(require("@readme/openapi-parser"));
|
|
45
|
+
require("isomorphic-fetch");
|
|
46
|
+
var js_yaml_1 = __importDefault(require("js-yaml"));
|
|
47
47
|
var Fetcher = /** @class */ (function () {
|
|
48
48
|
function Fetcher(uri) {
|
|
49
49
|
if (typeof uri === 'string') {
|
package/dist/index.d.ts
CHANGED