api 7.0.0-alpha.1 → 7.0.0-alpha.3
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/dist/bin.js +16 -62
- package/dist/codegen/index.js +2 -2
- package/dist/codegen/language.js +13 -9
- package/dist/codegen/languages/typescript/util.js +15 -20
- package/dist/codegen/languages/typescript.d.ts +3 -3
- package/dist/codegen/languages/typescript.js +324 -397
- package/dist/commands/index.js +1 -1
- package/dist/commands/install.js +155 -215
- package/dist/fetcher.d.ts +3 -3
- package/dist/fetcher.js +54 -95
- package/dist/lib/prompt.js +15 -67
- package/dist/logger.js +1 -1
- package/dist/packageInfo.d.ts +1 -1
- package/dist/packageInfo.js +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +79 -133
- package/package.json +9 -8
- package/src/codegen/languages/typescript.ts +2 -2
- package/src/fetcher.ts +1 -1
- package/src/packageInfo.ts +1 -1
- package/src/storage.ts +1 -1
- package/tsconfig.json +2 -0
package/dist/commands/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
6
|
+
const install_1 = __importDefault(require("./install"));
|
|
7
7
|
exports.default = {
|
|
8
8
|
install: install_1.default,
|
|
9
9
|
};
|
package/dist/commands/install.js
CHANGED
|
@@ -1,55 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
4
|
};
|
|
41
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const figures_1 = __importDefault(require("figures"));
|
|
8
|
+
const oas_1 = __importDefault(require("oas"));
|
|
9
|
+
const ora_1 = __importDefault(require("ora"));
|
|
10
|
+
const codegen_1 = __importDefault(require("../codegen"));
|
|
11
|
+
const fetcher_1 = __importDefault(require("../fetcher"));
|
|
12
|
+
const prompt_1 = __importDefault(require("../lib/prompt"));
|
|
13
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
14
|
+
const storage_1 = __importDefault(require("../storage"));
|
|
51
15
|
// @todo log logs to `.api/.logs` and have `.logs` ignored
|
|
52
|
-
|
|
16
|
+
const cmd = new commander_1.Command();
|
|
53
17
|
cmd
|
|
54
18
|
.name('install')
|
|
55
19
|
.description('install an API SDK into your codebase')
|
|
@@ -62,178 +26,154 @@ cmd
|
|
|
62
26
|
'ts',
|
|
63
27
|
]))
|
|
64
28
|
.addOption(new commander_1.Option('-y, --yes', 'Automatically answer "yes" to any prompts printed'))
|
|
65
|
-
.action(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
29
|
+
.action(async (uri, options) => {
|
|
30
|
+
let language;
|
|
31
|
+
if (options.lang) {
|
|
32
|
+
language = options.lang;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
({ value: language } = await (0, prompt_1.default)({
|
|
36
|
+
type: 'select',
|
|
37
|
+
name: 'value',
|
|
38
|
+
message: 'What language would you like to generate an SDK for?',
|
|
39
|
+
choices: [
|
|
40
|
+
{ title: 'TypeScript', value: 'ts' },
|
|
41
|
+
{ title: 'JavaScript', value: 'js' },
|
|
42
|
+
],
|
|
43
|
+
initial: 1,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
// Because our TS generation outputs raw TS source files we don't need to worry about CJS/ESM.
|
|
47
|
+
if (language === 'js') {
|
|
48
|
+
({ value: language } = await (0, prompt_1.default)({
|
|
49
|
+
type: 'select',
|
|
50
|
+
name: 'value',
|
|
51
|
+
message: 'How are your project imports and exports structured?',
|
|
52
|
+
choices: [
|
|
53
|
+
{ title: 'CommonJS', description: 'require/exports', value: 'cjs' },
|
|
54
|
+
{ title: 'ECMAScript Modules', description: 'import/export', value: 'esm' },
|
|
55
|
+
],
|
|
56
|
+
initial: 0,
|
|
57
|
+
format: sel => (sel === 'cjs' ? 'js-cjs' : 'js-esm'),
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
// @todo let them know that we're going to be creating a `.api/ directory
|
|
61
|
+
// @todo detect if they have a gitigore and .npmignore and if .api woudl be ignored by that
|
|
62
|
+
// @todo don't support swagger files without upconverting them
|
|
63
|
+
if (storage_1.default.isInLockFile({ source: uri })) {
|
|
64
|
+
// @todo
|
|
65
|
+
// logger(`It looks like you already have this API installed. Would you like to update it?`);
|
|
66
|
+
}
|
|
67
|
+
let identifier;
|
|
68
|
+
if (options.identifier) {
|
|
69
|
+
// `Storage.isIdentifierValid` will throw an exception if an identifier is invalid.
|
|
70
|
+
if (storage_1.default.isIdentifierValid(options.identifier)) {
|
|
71
|
+
identifier = options.identifier;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (fetcher_1.default.isAPIRegistryUUID(uri)) {
|
|
75
|
+
identifier = fetcher_1.default.getProjectPrefixFromRegistryUUID(uri);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
({ value: identifier } = await (0, prompt_1.default)({
|
|
79
|
+
type: 'text',
|
|
80
|
+
name: 'value',
|
|
81
|
+
message: 'What would you like to identify this API as? This will be how you import the SDK. (e.g. entering `petstore` would result in `@api/petstore`)',
|
|
82
|
+
validate: value => {
|
|
83
|
+
if (!value) {
|
|
84
|
+
return false;
|
|
109
85
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (storage_1.default.isIdentifierValid(options.identifier)) {
|
|
113
|
-
identifier = options.identifier;
|
|
86
|
+
try {
|
|
87
|
+
return storage_1.default.isIdentifierValid(value, true);
|
|
114
88
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
89
|
+
catch (err) {
|
|
90
|
+
return err.message;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
if (!identifier) {
|
|
96
|
+
(0, logger_1.default)('You must tell us what you would like to identify this API as in order to install it.', true);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
let spinner = (0, ora_1.default)('Fetching your API').start();
|
|
100
|
+
const storage = new storage_1.default(uri, identifier);
|
|
101
|
+
const oas = await storage
|
|
102
|
+
.load()
|
|
103
|
+
.then(res => {
|
|
104
|
+
spinner.succeed(spinner.text);
|
|
105
|
+
return res;
|
|
106
|
+
})
|
|
107
|
+
.then(oas_1.default.init)
|
|
108
|
+
.catch(err => {
|
|
109
|
+
// @todo cleanup installed files
|
|
110
|
+
spinner.fail(spinner.text);
|
|
111
|
+
(0, logger_1.default)(err.message, true);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
});
|
|
114
|
+
// @todo look for a prettier config and if we find one ask them if we should use it
|
|
115
|
+
spinner = (0, ora_1.default)('Generating your SDK').start();
|
|
116
|
+
const generator = (0, codegen_1.default)(language, oas, './openapi.json', identifier);
|
|
117
|
+
const sdkSource = await generator
|
|
118
|
+
.generator()
|
|
119
|
+
.then(res => {
|
|
120
|
+
spinner.succeed(spinner.text);
|
|
121
|
+
return res;
|
|
122
|
+
})
|
|
123
|
+
.catch(err => {
|
|
124
|
+
// @todo cleanup installed files
|
|
125
|
+
spinner.fail(spinner.text);
|
|
126
|
+
(0, logger_1.default)(err.message, true);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
});
|
|
129
|
+
spinner = (0, ora_1.default)('Saving your SDK into your codebase').start();
|
|
130
|
+
await storage
|
|
131
|
+
.saveSourceFiles(sdkSource)
|
|
132
|
+
.then(() => {
|
|
133
|
+
spinner.succeed(spinner.text);
|
|
134
|
+
})
|
|
135
|
+
.catch(err => {
|
|
136
|
+
// @todo cleanup installed files
|
|
137
|
+
spinner.fail(spinner.text);
|
|
138
|
+
(0, logger_1.default)(err.message, true);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
});
|
|
141
|
+
if (generator.hasRequiredPackages()) {
|
|
142
|
+
(0, logger_1.default)(`${figures_1.default.warning} This generator requires some packages to be installed alongside it:`);
|
|
143
|
+
Object.entries(generator.requiredPackages).forEach(([pkg, pkgInfo]) => {
|
|
144
|
+
(0, logger_1.default)(` ${figures_1.default.pointerSmall} ${pkg}: ${pkgInfo.reason} ${pkgInfo.url}`);
|
|
145
|
+
});
|
|
146
|
+
if (!options.yes) {
|
|
147
|
+
await (0, prompt_1.default)({
|
|
148
|
+
type: 'confirm',
|
|
149
|
+
name: 'value',
|
|
150
|
+
message: 'OK to proceed with package installation?',
|
|
151
|
+
initial: true,
|
|
152
|
+
}).then(({ value }) => {
|
|
153
|
+
if (!value) {
|
|
154
|
+
// @todo cleanup installed files
|
|
155
|
+
(0, logger_1.default)('Installation cancelled.', true);
|
|
142
156
|
process.exit(1);
|
|
143
157
|
}
|
|
144
|
-
|
|
145
|
-
storage = new storage_1.default(uri, identifier);
|
|
146
|
-
return [4 /*yield*/, storage
|
|
147
|
-
.load()
|
|
148
|
-
.then(function (res) {
|
|
149
|
-
spinner.succeed(spinner.text);
|
|
150
|
-
return res;
|
|
151
|
-
})
|
|
152
|
-
.then(oas_1.default.init)
|
|
153
|
-
.catch(function (err) {
|
|
154
|
-
// @todo cleanup installed files
|
|
155
|
-
spinner.fail(spinner.text);
|
|
156
|
-
(0, logger_1.default)(err.message, true);
|
|
157
|
-
process.exit(1);
|
|
158
|
-
})];
|
|
159
|
-
case 10:
|
|
160
|
-
oas = _a.sent();
|
|
161
|
-
// @todo look for a prettier config and if we find one ask them if we should use it
|
|
162
|
-
spinner = (0, ora_1.default)('Generating your SDK').start();
|
|
163
|
-
generator = (0, codegen_1.default)(language, oas, './openapi.json', identifier);
|
|
164
|
-
return [4 /*yield*/, generator
|
|
165
|
-
.generator()
|
|
166
|
-
.then(function (res) {
|
|
167
|
-
spinner.succeed(spinner.text);
|
|
168
|
-
return res;
|
|
169
|
-
})
|
|
170
|
-
.catch(function (err) {
|
|
171
|
-
// @todo cleanup installed files
|
|
172
|
-
spinner.fail(spinner.text);
|
|
173
|
-
(0, logger_1.default)(err.message, true);
|
|
174
|
-
process.exit(1);
|
|
175
|
-
})];
|
|
176
|
-
case 11:
|
|
177
|
-
sdkSource = _a.sent();
|
|
178
|
-
spinner = (0, ora_1.default)('Saving your SDK into your codebase').start();
|
|
179
|
-
return [4 /*yield*/, storage
|
|
180
|
-
.saveSourceFiles(sdkSource)
|
|
181
|
-
.then(function () {
|
|
182
|
-
spinner.succeed(spinner.text);
|
|
183
|
-
})
|
|
184
|
-
.catch(function (err) {
|
|
185
|
-
// @todo cleanup installed files
|
|
186
|
-
spinner.fail(spinner.text);
|
|
187
|
-
(0, logger_1.default)(err.message, true);
|
|
188
|
-
process.exit(1);
|
|
189
|
-
})];
|
|
190
|
-
case 12:
|
|
191
|
-
_a.sent();
|
|
192
|
-
if (!generator.hasRequiredPackages()) return [3 /*break*/, 18];
|
|
193
|
-
(0, logger_1.default)("".concat(figures_1.default.warning, " This generator requires some packages to be installed alongside it:"));
|
|
194
|
-
Object.entries(generator.requiredPackages).forEach(function (_a) {
|
|
195
|
-
var pkg = _a[0], pkgInfo = _a[1];
|
|
196
|
-
(0, logger_1.default)(" ".concat(figures_1.default.pointerSmall, " ").concat(pkg, ": ").concat(pkgInfo.reason, " ").concat(pkgInfo.url));
|
|
197
|
-
});
|
|
198
|
-
if (!!options.yes) return [3 /*break*/, 14];
|
|
199
|
-
return [4 /*yield*/, (0, prompt_1.default)({
|
|
200
|
-
type: 'confirm',
|
|
201
|
-
name: 'value',
|
|
202
|
-
message: 'OK to proceed with package installation?',
|
|
203
|
-
initial: true,
|
|
204
|
-
}).then(function (_a) {
|
|
205
|
-
var value = _a.value;
|
|
206
|
-
if (!value) {
|
|
207
|
-
// @todo cleanup installed files
|
|
208
|
-
(0, logger_1.default)('Installation cancelled.', true);
|
|
209
|
-
process.exit(1);
|
|
210
|
-
}
|
|
211
|
-
})];
|
|
212
|
-
case 13:
|
|
213
|
-
_a.sent();
|
|
214
|
-
_a.label = 14;
|
|
215
|
-
case 14:
|
|
216
|
-
spinner = (0, ora_1.default)('Installing required packages').start();
|
|
217
|
-
_a.label = 15;
|
|
218
|
-
case 15:
|
|
219
|
-
_a.trys.push([15, 17, , 18]);
|
|
220
|
-
return [4 /*yield*/, generator.installer(storage)];
|
|
221
|
-
case 16:
|
|
222
|
-
_a.sent();
|
|
223
|
-
spinner.succeed(spinner.text);
|
|
224
|
-
return [3 /*break*/, 18];
|
|
225
|
-
case 17:
|
|
226
|
-
err_1 = _a.sent();
|
|
227
|
-
// @todo cleanup installed files
|
|
228
|
-
spinner.fail(spinner.text);
|
|
229
|
-
(0, logger_1.default)(err_1.message, true);
|
|
230
|
-
process.exit(1);
|
|
231
|
-
return [3 /*break*/, 18];
|
|
232
|
-
case 18:
|
|
233
|
-
(0, logger_1.default)('🚀 All done!');
|
|
234
|
-
return [2 /*return*/];
|
|
158
|
+
});
|
|
235
159
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
160
|
+
spinner = (0, ora_1.default)('Installing required packages').start();
|
|
161
|
+
try {
|
|
162
|
+
await generator.installer(storage);
|
|
163
|
+
spinner.succeed(spinner.text);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
// @todo cleanup installed files
|
|
167
|
+
spinner.fail(spinner.text);
|
|
168
|
+
(0, logger_1.default)(err.message, true);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
(0, logger_1.default)('🚀 All done!');
|
|
173
|
+
})
|
|
174
|
+
.addHelpText('after', `
|
|
175
|
+
Examples:
|
|
176
|
+
$ api install @developers/v2.0#nysezql0wwo236
|
|
177
|
+
$ api install https://raw.githubusercontent.com/readmeio/oas-examples/main/3.0/json/petstore-simple.json
|
|
178
|
+
$ api install ./petstore.json`);
|
|
239
179
|
exports.default = cmd;
|
package/dist/fetcher.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OASDocument } from 'oas/
|
|
1
|
+
import type { OASDocument } from 'oas/rmoas.types';
|
|
2
2
|
export default class Fetcher {
|
|
3
3
|
uri: string | OASDocument;
|
|
4
4
|
/**
|
|
@@ -10,7 +10,7 @@ export default class Fetcher {
|
|
|
10
10
|
static isAPIRegistryUUID(uri: string): boolean;
|
|
11
11
|
static isGitHubBlobURL(uri: string): boolean;
|
|
12
12
|
static getProjectPrefixFromRegistryUUID(uri: string): string | undefined;
|
|
13
|
-
load(): Promise<(Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
13
|
+
load(): Promise<(import("openapi-types").OpenAPIV3.Document<{}> & Record<string, unknown>) | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
14
14
|
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
15
15
|
jsonSchemaDialect?: string | undefined;
|
|
16
16
|
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[] | undefined;
|
|
@@ -46,7 +46,7 @@ export default class Fetcher {
|
|
|
46
46
|
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
47
47
|
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
48
48
|
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
49
|
-
}>, "components"> & Record<string, unknown>)
|
|
49
|
+
}>, "components"> & Record<string, unknown>)>;
|
|
50
50
|
static getURL(url: string): Promise<any>;
|
|
51
51
|
static getFile(uri: string): Promise<any>;
|
|
52
52
|
static validate(json: OASDocument): Promise<import("openapi-types").OpenAPI.Document<{}>>;
|
package/dist/fetcher.js
CHANGED
|
@@ -1,50 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
4
|
};
|
|
41
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const openapi_parser_1 = __importDefault(require("@readme/openapi-parser"));
|
|
9
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
10
|
+
class Fetcher {
|
|
11
|
+
uri;
|
|
12
|
+
/**
|
|
13
|
+
* @example @petstore/v1.0#n6kvf10vakpemvplx
|
|
14
|
+
* @example @petstore#n6kvf10vakpemvplx
|
|
15
|
+
*/
|
|
16
|
+
static registryUUIDRegex = /^@(?<project>[a-zA-Z0-9-_]+)(\/?(?<version>.+))?#(?<uuid>[a-z0-9]+)$/;
|
|
17
|
+
constructor(uri) {
|
|
48
18
|
if (typeof uri === 'string') {
|
|
49
19
|
if (Fetcher.isAPIRegistryUUID(uri)) {
|
|
50
20
|
// Resolve OpenAPI definition shorthand accessors from within the ReadMe API Registry.
|
|
@@ -68,72 +38,67 @@ var Fetcher = /** @class */ (function () {
|
|
|
68
38
|
this.uri = uri;
|
|
69
39
|
}
|
|
70
40
|
}
|
|
71
|
-
|
|
41
|
+
static isAPIRegistryUUID(uri) {
|
|
72
42
|
return Fetcher.registryUUIDRegex.test(uri);
|
|
73
|
-
}
|
|
74
|
-
|
|
43
|
+
}
|
|
44
|
+
static isGitHubBlobURL(uri) {
|
|
75
45
|
return /\/\/github.com\/[-_a-zA-Z0-9]+\/[-_a-zA-Z0-9]+\/blob\/(.*).(yaml|json|yml)/.test(uri);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
var matches = uri.match(Fetcher.registryUUIDRegex);
|
|
46
|
+
}
|
|
47
|
+
static getProjectPrefixFromRegistryUUID(uri) {
|
|
48
|
+
const matches = uri.match(Fetcher.registryUUIDRegex);
|
|
80
49
|
if (!matches) {
|
|
81
50
|
return undefined;
|
|
82
51
|
}
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
Fetcher.getURL = function (url) {
|
|
52
|
+
return matches.groups?.project;
|
|
53
|
+
}
|
|
54
|
+
async load() {
|
|
55
|
+
if (typeof this.uri !== 'string') {
|
|
56
|
+
throw new TypeError("Something disastrous occurred and a non-string URI was supplied to the Fetcher library. This shouldn't have happened!");
|
|
57
|
+
}
|
|
58
|
+
return Promise.resolve(this.uri)
|
|
59
|
+
.then(uri => {
|
|
60
|
+
let url;
|
|
61
|
+
try {
|
|
62
|
+
url = new URL(uri);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
// If that try fails for whatever reason than the URI that we have isn't a real URL and
|
|
66
|
+
// we can safely attempt to look for it on the filesystem.
|
|
67
|
+
return Fetcher.getFile(uri);
|
|
68
|
+
}
|
|
69
|
+
return Fetcher.getURL(url.href);
|
|
70
|
+
})
|
|
71
|
+
.then(res => Fetcher.validate(res))
|
|
72
|
+
.then(res => res);
|
|
73
|
+
}
|
|
74
|
+
static getURL(url) {
|
|
110
75
|
// @todo maybe include our user-agent here to identify our request
|
|
111
|
-
return fetch(url).then(
|
|
76
|
+
return fetch(url).then(res => {
|
|
112
77
|
if (!res.ok) {
|
|
113
|
-
throw new Error(
|
|
78
|
+
throw new Error(`Unable to retrieve URL (${url}). Reason: ${res.statusText}`);
|
|
114
79
|
}
|
|
115
80
|
if (res.headers.get('content-type') === 'application/yaml' || /\.(yaml|yml)/.test(url)) {
|
|
116
|
-
return res.text().then(
|
|
81
|
+
return res.text().then(text => {
|
|
117
82
|
return js_yaml_1.default.load(text);
|
|
118
83
|
});
|
|
119
84
|
}
|
|
120
85
|
return res.json();
|
|
121
86
|
});
|
|
122
|
-
}
|
|
123
|
-
|
|
87
|
+
}
|
|
88
|
+
static getFile(uri) {
|
|
124
89
|
// Support relative paths by resolving them against the cwd.
|
|
125
|
-
|
|
90
|
+
const file = node_path_1.default.resolve(process.cwd(), uri);
|
|
126
91
|
if (!node_fs_1.default.existsSync(file)) {
|
|
127
|
-
throw new Error(
|
|
92
|
+
throw new Error(`Sorry, we were unable to load an API definition from ${file}. Please either supply a URL or a path on your filesystem.`);
|
|
128
93
|
}
|
|
129
|
-
return Promise.resolve(node_fs_1.default.readFileSync(file, 'utf8')).then(
|
|
94
|
+
return Promise.resolve(node_fs_1.default.readFileSync(file, 'utf8')).then((res) => {
|
|
130
95
|
if (/\.(yaml|yml)/.test(file)) {
|
|
131
96
|
return js_yaml_1.default.load(res);
|
|
132
97
|
}
|
|
133
98
|
return JSON.parse(res);
|
|
134
99
|
});
|
|
135
|
-
}
|
|
136
|
-
|
|
100
|
+
}
|
|
101
|
+
static validate(json) {
|
|
137
102
|
if (json.swagger) {
|
|
138
103
|
throw new Error('Sorry, this module only supports OpenAPI definitions.');
|
|
139
104
|
}
|
|
@@ -147,18 +112,12 @@ var Fetcher = /** @class */ (function () {
|
|
|
147
112
|
*/
|
|
148
113
|
circular: 'ignore',
|
|
149
114
|
},
|
|
150
|
-
}).catch(
|
|
115
|
+
}).catch(err => {
|
|
151
116
|
if (/is not a valid openapi definition/i.test(err.message)) {
|
|
152
117
|
throw new Error("Sorry, that doesn't look like a valid OpenAPI definition.");
|
|
153
118
|
}
|
|
154
119
|
throw err;
|
|
155
120
|
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
* @example @petstore/v1.0#n6kvf10vakpemvplx
|
|
159
|
-
* @example @petstore#n6kvf10vakpemvplx
|
|
160
|
-
*/
|
|
161
|
-
Fetcher.registryUUIDRegex = /^@(?<project>[a-zA-Z0-9-_]+)(\/?(?<version>.+))?#(?<uuid>[a-z0-9]+)$/;
|
|
162
|
-
return Fetcher;
|
|
163
|
-
}());
|
|
121
|
+
}
|
|
122
|
+
}
|
|
164
123
|
exports.default = Fetcher;
|