api 7.0.0-alpha.0 → 7.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +91 -0
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.js +23 -0
- package/dist/codegen/language.d.ts +27 -0
- package/dist/codegen/language.js +33 -0
- package/dist/codegen/languages/typescript/util.d.ts +10 -0
- package/dist/codegen/languages/typescript/util.js +175 -0
- package/dist/codegen/languages/typescript.d.ts +111 -0
- package/dist/codegen/languages/typescript.js +821 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +9 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.js +239 -0
- package/dist/fetcher.d.ts +53 -0
- package/dist/fetcher.js +164 -0
- package/dist/lib/prompt.d.ts +9 -0
- package/dist/lib/prompt.js +81 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +16 -0
- package/dist/packageInfo.d.ts +2 -0
- package/dist/packageInfo.js +6 -0
- package/dist/storage.d.ts +106 -0
- package/dist/storage.js +280 -0
- package/package.json +2 -2
- package/src/codegen/languages/typescript.ts +6 -6
- package/src/packageInfo.ts +1 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { OASDocument } from 'oas/dist/rmoas.types';
|
|
2
|
+
import Fetcher from './fetcher';
|
|
3
|
+
export default class Storage {
|
|
4
|
+
static dir: string;
|
|
5
|
+
static lockfile: false | Lockfile;
|
|
6
|
+
/**
|
|
7
|
+
* This is the original source that the file came from (relative/absolute file path, URL, ReadMe
|
|
8
|
+
* registry UUID, etc.).
|
|
9
|
+
*/
|
|
10
|
+
source: string;
|
|
11
|
+
identifier: string;
|
|
12
|
+
fetcher: Fetcher;
|
|
13
|
+
constructor(source: string, identifier?: string);
|
|
14
|
+
static getLockfilePath(): string;
|
|
15
|
+
static getAPIsDir(): string;
|
|
16
|
+
static setStorageDir(dir?: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Reset the state of the entire storage system.
|
|
19
|
+
*
|
|
20
|
+
* This will completely destroy the contents of the `.api/` directory!
|
|
21
|
+
*/
|
|
22
|
+
static reset(): Promise<void>;
|
|
23
|
+
static getDefaultLockfile(): Lockfile;
|
|
24
|
+
static generateIntegrityHash(definition: OASDocument): string;
|
|
25
|
+
static getLockfile(): Lockfile;
|
|
26
|
+
static isIdentifierValid(identifier: string, prefixWithAPINamespace?: boolean): boolean;
|
|
27
|
+
static isInLockFile(search: {
|
|
28
|
+
identifier?: string;
|
|
29
|
+
source?: string;
|
|
30
|
+
}): false | LockfileAPI;
|
|
31
|
+
setIdentifier(identifier: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Determine if the current spec + identifier we're working with is already in the lockfile.
|
|
34
|
+
*/
|
|
35
|
+
isInLockfile(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Retrieve the lockfile record for the current spec + identifier if it exists in the lockfile.
|
|
38
|
+
*/
|
|
39
|
+
getFromLockfile(): LockfileAPI | undefined;
|
|
40
|
+
getIdentifierStorageDir(): string;
|
|
41
|
+
getAPIDefinition(): any;
|
|
42
|
+
saveSourceFiles(files: Record<string, string>): Promise<unknown>;
|
|
43
|
+
load(): Promise<OASDocument>;
|
|
44
|
+
/**
|
|
45
|
+
* @example <caption>Storage directory structure</caption>
|
|
46
|
+
* .api/
|
|
47
|
+
* ├── api.json // The `package-lock.json` equivalent that records everything that's
|
|
48
|
+
* | // installed, when it was installed, what the original source was,
|
|
49
|
+
* | // and what version of `api` was used.
|
|
50
|
+
* └── apis/
|
|
51
|
+
* ├── readme/
|
|
52
|
+
* | ├── node_modules/
|
|
53
|
+
* │ ├── index.js // We may offer the option to export a raw TS file for folks who want
|
|
54
|
+
* | | // that, but for now it'll be a compiled JS file.
|
|
55
|
+
* │ ├── index.d.ts // All types for their SDK, ready to use in an IDE.
|
|
56
|
+
* │ |── openapi.json
|
|
57
|
+
* │ └── package.json
|
|
58
|
+
* └── petstore/
|
|
59
|
+
* ├── node_modules/
|
|
60
|
+
* ├── index.js
|
|
61
|
+
* ├── index.d.ts
|
|
62
|
+
* ├── openapi.json
|
|
63
|
+
* └── package.json
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
save(spec: OASDocument): OASDocument;
|
|
67
|
+
}
|
|
68
|
+
interface Lockfile {
|
|
69
|
+
apis: LockfileAPI[];
|
|
70
|
+
/**
|
|
71
|
+
* The `api.json` schema version. This will only ever change if we introduce breaking changes to
|
|
72
|
+
* this store.
|
|
73
|
+
*/
|
|
74
|
+
version: '1.0';
|
|
75
|
+
}
|
|
76
|
+
interface LockfileAPI {
|
|
77
|
+
/**
|
|
78
|
+
* A unique identifier of the API. This'll be used to do requires on `@api/<identifier>` and also
|
|
79
|
+
* where the SDK code will be located in `.api/apis/<identifier>`.
|
|
80
|
+
*
|
|
81
|
+
* @example petstore
|
|
82
|
+
*/
|
|
83
|
+
identifier: string;
|
|
84
|
+
/**
|
|
85
|
+
* The version of `api` that was used to install this SDK.
|
|
86
|
+
*
|
|
87
|
+
* @example 5.0.0
|
|
88
|
+
*/
|
|
89
|
+
installerVersion: string;
|
|
90
|
+
/**
|
|
91
|
+
* An integrity hash that will be used to determine on `npx api update` calls if the API has
|
|
92
|
+
* changed since the SDK was last generated.
|
|
93
|
+
*
|
|
94
|
+
* @example sha512-ld+djZk8uRWmzXC+JYla1PTBScg0NjP/8x9vOOKRW+DuJ3NNMRjrpfbY7T77Jgnc87dZZsU49robbQfYe3ukug==
|
|
95
|
+
*/
|
|
96
|
+
integrity: string;
|
|
97
|
+
/**
|
|
98
|
+
* The original source that was used to generate the SDK with.
|
|
99
|
+
*
|
|
100
|
+
* @example https://raw.githubusercontent.com/readmeio/oas-examples/main/3.0/json/petstore-simple.json
|
|
101
|
+
* @example ./petstore.json
|
|
102
|
+
* @example @developers/v2.0#nysezql0wwo236
|
|
103
|
+
*/
|
|
104
|
+
source: string;
|
|
105
|
+
}
|
|
106
|
+
export {};
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
var node_fs_1 = __importDefault(require("node:fs"));
|
|
43
|
+
var node_path_1 = __importDefault(require("node:path"));
|
|
44
|
+
var make_dir_1 = __importDefault(require("make-dir"));
|
|
45
|
+
var ssri_1 = __importDefault(require("ssri"));
|
|
46
|
+
var validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
47
|
+
var fetcher_1 = __importDefault(require("./fetcher"));
|
|
48
|
+
var packageInfo_1 = require("./packageInfo");
|
|
49
|
+
var Storage = /** @class */ (function () {
|
|
50
|
+
function Storage(source, identifier) {
|
|
51
|
+
Storage.setStorageDir();
|
|
52
|
+
this.fetcher = new fetcher_1.default(source);
|
|
53
|
+
this.source = source;
|
|
54
|
+
if (identifier) {
|
|
55
|
+
this.identifier = identifier;
|
|
56
|
+
}
|
|
57
|
+
// This should default to false so we have awareness if we've looked at the lockfile yet.
|
|
58
|
+
Storage.lockfile = false;
|
|
59
|
+
}
|
|
60
|
+
Storage.getLockfilePath = function () {
|
|
61
|
+
return node_path_1.default.join(Storage.dir, 'api.json');
|
|
62
|
+
};
|
|
63
|
+
Storage.getAPIsDir = function () {
|
|
64
|
+
return node_path_1.default.join(Storage.dir, 'apis');
|
|
65
|
+
};
|
|
66
|
+
Storage.setStorageDir = function (dir) {
|
|
67
|
+
if (dir) {
|
|
68
|
+
Storage.dir = dir;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
else if (Storage.dir) {
|
|
72
|
+
// If we already have a storage dir set and aren't explicitly it to something new then we
|
|
73
|
+
// shouldn't overwrite what we've already got.
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
Storage.dir = make_dir_1.default.sync(node_path_1.default.join(process.cwd(), '.api'));
|
|
77
|
+
make_dir_1.default.sync(Storage.getAPIsDir());
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Reset the state of the entire storage system.
|
|
81
|
+
*
|
|
82
|
+
* This will completely destroy the contents of the `.api/` directory!
|
|
83
|
+
*/
|
|
84
|
+
Storage.reset = function () {
|
|
85
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
86
|
+
return __generator(this, function (_a) {
|
|
87
|
+
switch (_a.label) {
|
|
88
|
+
case 0:
|
|
89
|
+
if (!Storage.getLockfilePath()) return [3 /*break*/, 2];
|
|
90
|
+
return [4 /*yield*/, node_fs_1.default.promises.writeFile(Storage.getLockfilePath(), JSON.stringify(Storage.getDefaultLockfile(), null, 2))];
|
|
91
|
+
case 1:
|
|
92
|
+
_a.sent();
|
|
93
|
+
_a.label = 2;
|
|
94
|
+
case 2:
|
|
95
|
+
if (!Storage.getAPIsDir()) return [3 /*break*/, 5];
|
|
96
|
+
return [4 /*yield*/, node_fs_1.default.promises.rm(Storage.getAPIsDir(), { recursive: true })];
|
|
97
|
+
case 3:
|
|
98
|
+
_a.sent();
|
|
99
|
+
return [4 /*yield*/, node_fs_1.default.promises.mkdir(Storage.getAPIsDir(), { recursive: true })];
|
|
100
|
+
case 4:
|
|
101
|
+
_a.sent();
|
|
102
|
+
_a.label = 5;
|
|
103
|
+
case 5: return [2 /*return*/];
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
Storage.getDefaultLockfile = function () {
|
|
109
|
+
return {
|
|
110
|
+
version: '1.0',
|
|
111
|
+
apis: [],
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
Storage.generateIntegrityHash = function (definition) {
|
|
115
|
+
return ssri_1.default
|
|
116
|
+
.fromData(JSON.stringify(definition), {
|
|
117
|
+
algorithms: ['sha512'],
|
|
118
|
+
})
|
|
119
|
+
.toString();
|
|
120
|
+
};
|
|
121
|
+
Storage.getLockfile = function () {
|
|
122
|
+
if (typeof Storage.lockfile === 'object') {
|
|
123
|
+
return Storage.lockfile;
|
|
124
|
+
}
|
|
125
|
+
if (node_fs_1.default.existsSync(Storage.getLockfilePath())) {
|
|
126
|
+
var file = node_fs_1.default.readFileSync(Storage.getLockfilePath(), 'utf8');
|
|
127
|
+
Storage.lockfile = JSON.parse(file);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
Storage.lockfile = Storage.getDefaultLockfile();
|
|
131
|
+
}
|
|
132
|
+
return Storage.lockfile;
|
|
133
|
+
};
|
|
134
|
+
Storage.isIdentifierValid = function (identifier, prefixWithAPINamespace) {
|
|
135
|
+
var _a;
|
|
136
|
+
// Is this identifier already in storage?
|
|
137
|
+
if (Storage.isInLockFile({ identifier: identifier })) {
|
|
138
|
+
throw new Error("\"".concat(identifier, "\" is already taken in your `.api/` directory. Please try another identifier."));
|
|
139
|
+
}
|
|
140
|
+
var isValidForNPM = (0, validate_npm_package_name_1.default)(prefixWithAPINamespace ? "@api/".concat(identifier) : identifier);
|
|
141
|
+
if (!isValidForNPM.validForNewPackages) {
|
|
142
|
+
// `prompts` doesn't support surfacing multiple errors in a `validate` call so we can only
|
|
143
|
+
// surface the first to the user.
|
|
144
|
+
throw new Error("Identifier cannot be used for an NPM package: ".concat(((_a = isValidForNPM === null || isValidForNPM === void 0 ? void 0 : isValidForNPM.errors) === null || _a === void 0 ? void 0 : _a[0]) || '[error unavailable]'));
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
};
|
|
148
|
+
Storage.isInLockFile = function (search) {
|
|
149
|
+
// Because this method may run before we initialize a new storage object we should make sure
|
|
150
|
+
// that we have a storage directory present.
|
|
151
|
+
Storage.setStorageDir();
|
|
152
|
+
if (!search.identifier && !search.source) {
|
|
153
|
+
throw new TypeError('An `identifier` or `source` must be supplied to this method to search in the lockfile.');
|
|
154
|
+
}
|
|
155
|
+
var lockfile = Storage.getLockfile();
|
|
156
|
+
if (typeof lockfile !== 'object' || lockfile === null || !lockfile.apis) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
var res = lockfile.apis.find(function (a) {
|
|
160
|
+
if (search.identifier) {
|
|
161
|
+
return a.identifier === search.identifier;
|
|
162
|
+
}
|
|
163
|
+
return a.source === search.source;
|
|
164
|
+
});
|
|
165
|
+
return res === undefined ? false : res;
|
|
166
|
+
};
|
|
167
|
+
Storage.prototype.setIdentifier = function (identifier) {
|
|
168
|
+
this.identifier = identifier;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Determine if the current spec + identifier we're working with is already in the lockfile.
|
|
172
|
+
*/
|
|
173
|
+
Storage.prototype.isInLockfile = function () {
|
|
174
|
+
return Boolean(this.getFromLockfile());
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Retrieve the lockfile record for the current spec + identifier if it exists in the lockfile.
|
|
178
|
+
*/
|
|
179
|
+
Storage.prototype.getFromLockfile = function () {
|
|
180
|
+
var _this = this;
|
|
181
|
+
var lockfile = Storage.getLockfile();
|
|
182
|
+
return lockfile.apis.find(function (a) { return a.identifier === _this.identifier; });
|
|
183
|
+
};
|
|
184
|
+
Storage.prototype.getIdentifierStorageDir = function () {
|
|
185
|
+
if (!this.isInLockfile()) {
|
|
186
|
+
throw new Error("".concat(this.source, " has not been saved to storage yet and must do so before being retrieved."));
|
|
187
|
+
}
|
|
188
|
+
return node_path_1.default.join(Storage.getAPIsDir(), this.identifier);
|
|
189
|
+
};
|
|
190
|
+
Storage.prototype.getAPIDefinition = function () {
|
|
191
|
+
var file = node_fs_1.default.readFileSync(node_path_1.default.join(this.getIdentifierStorageDir(), 'openapi.json'), 'utf8');
|
|
192
|
+
return JSON.parse(file);
|
|
193
|
+
};
|
|
194
|
+
Storage.prototype.saveSourceFiles = function (files) {
|
|
195
|
+
var _this = this;
|
|
196
|
+
if (!this.isInLockfile()) {
|
|
197
|
+
throw new Error("".concat(this.source, " has not been saved to storage yet and must do so before being retrieved."));
|
|
198
|
+
}
|
|
199
|
+
return new Promise(function (resolve) {
|
|
200
|
+
var savedSource = [];
|
|
201
|
+
Object.entries(files).forEach(function (_a) {
|
|
202
|
+
var fileName = _a[0], contents = _a[1];
|
|
203
|
+
var sourceFilePath = node_path_1.default.join(_this.getIdentifierStorageDir(), fileName);
|
|
204
|
+
node_fs_1.default.writeFileSync(sourceFilePath, contents);
|
|
205
|
+
savedSource.push(sourceFilePath);
|
|
206
|
+
});
|
|
207
|
+
resolve(savedSource);
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
Storage.prototype.load = function () {
|
|
211
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
212
|
+
var _this = this;
|
|
213
|
+
return __generator(this, function (_a) {
|
|
214
|
+
return [2 /*return*/, this.fetcher.load().then(function (spec) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
215
|
+
return [2 /*return*/, this.save(spec)];
|
|
216
|
+
}); }); })];
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* @example <caption>Storage directory structure</caption>
|
|
222
|
+
* .api/
|
|
223
|
+
* ├── api.json // The `package-lock.json` equivalent that records everything that's
|
|
224
|
+
* | // installed, when it was installed, what the original source was,
|
|
225
|
+
* | // and what version of `api` was used.
|
|
226
|
+
* └── apis/
|
|
227
|
+
* ├── readme/
|
|
228
|
+
* | ├── node_modules/
|
|
229
|
+
* │ ├── index.js // We may offer the option to export a raw TS file for folks who want
|
|
230
|
+
* | | // that, but for now it'll be a compiled JS file.
|
|
231
|
+
* │ ├── index.d.ts // All types for their SDK, ready to use in an IDE.
|
|
232
|
+
* │ |── openapi.json
|
|
233
|
+
* │ └── package.json
|
|
234
|
+
* └── petstore/
|
|
235
|
+
* ├── node_modules/
|
|
236
|
+
* ├── index.js
|
|
237
|
+
* ├── index.d.ts
|
|
238
|
+
* ├── openapi.json
|
|
239
|
+
* └── package.json
|
|
240
|
+
*
|
|
241
|
+
*/
|
|
242
|
+
Storage.prototype.save = function (spec) {
|
|
243
|
+
if (!this.identifier) {
|
|
244
|
+
throw new TypeError('An identifier must be set before saving the API definition into storage.');
|
|
245
|
+
}
|
|
246
|
+
// Create our main `.api/` directory.
|
|
247
|
+
if (!node_fs_1.default.existsSync(Storage.dir)) {
|
|
248
|
+
node_fs_1.default.mkdirSync(Storage.dir, { recursive: true });
|
|
249
|
+
}
|
|
250
|
+
// Create the `.api/apis/` diretory where we'll be storing API definitions.
|
|
251
|
+
if (!node_fs_1.default.existsSync(Storage.getAPIsDir())) {
|
|
252
|
+
node_fs_1.default.mkdirSync(Storage.getAPIsDir(), { recursive: true });
|
|
253
|
+
}
|
|
254
|
+
if (!this.isInLockfile()) {
|
|
255
|
+
// This API doesn't exist within our storage system yet so we need to record it in the
|
|
256
|
+
// lockfile.
|
|
257
|
+
var identifierStorageDir = node_path_1.default.join(Storage.getAPIsDir(), this.identifier);
|
|
258
|
+
var saved = JSON.stringify(spec, null, 2);
|
|
259
|
+
// Create the `.api/apis/<identifier>` directory where we'll be storing this API definition
|
|
260
|
+
// and eventually its codegen'd SDK.
|
|
261
|
+
if (!node_fs_1.default.existsSync(identifierStorageDir)) {
|
|
262
|
+
node_fs_1.default.mkdirSync(identifierStorageDir, { recursive: true });
|
|
263
|
+
}
|
|
264
|
+
Storage.lockfile.apis.push({
|
|
265
|
+
identifier: this.identifier,
|
|
266
|
+
source: this.source,
|
|
267
|
+
integrity: Storage.generateIntegrityHash(spec),
|
|
268
|
+
installerVersion: packageInfo_1.PACKAGE_VERSION,
|
|
269
|
+
});
|
|
270
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(identifierStorageDir, 'openapi.json'), saved);
|
|
271
|
+
node_fs_1.default.writeFileSync(Storage.getLockfilePath(), JSON.stringify(Storage.lockfile, null, 2));
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Is this the same spec that we already have? Should we update it? // @todo
|
|
275
|
+
}
|
|
276
|
+
return spec;
|
|
277
|
+
};
|
|
278
|
+
return Storage;
|
|
279
|
+
}());
|
|
280
|
+
exports.default = Storage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.1",
|
|
4
4
|
"description": "Magical SDK generation from an OpenAPI definition 🪄",
|
|
5
5
|
"bin": {
|
|
6
6
|
"api": "./bin/api"
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@api/test-utils": "file:../test-utils",
|
|
61
|
+
"@readme/api-core": "file:../core",
|
|
61
62
|
"@readme/oas-examples": "^5.12.0",
|
|
62
63
|
"@types/js-yaml": "^4.0.5",
|
|
63
64
|
"@types/lodash.camelcase": "^4.3.7",
|
|
@@ -69,7 +70,6 @@
|
|
|
69
70
|
"@types/ssri": "^7.1.1",
|
|
70
71
|
"@types/validate-npm-package-name": "^4.0.0",
|
|
71
72
|
"@vitest/coverage-v8": "^0.34.4",
|
|
72
|
-
"api.core": "file:../core",
|
|
73
73
|
"fetch-mock": "^9.11.0",
|
|
74
74
|
"oas-normalize": "^8.3.2",
|
|
75
75
|
"type-fest": "^4.3.1",
|
|
@@ -86,7 +86,7 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
86
86
|
|
|
87
87
|
this.requiredPackages = {
|
|
88
88
|
api: {
|
|
89
|
-
reason: "Required for the
|
|
89
|
+
reason: "Required for the `@readme/api-core` library that the codegen'd SDK uses for making requests.",
|
|
90
90
|
url: 'https://npm.im/api',
|
|
91
91
|
},
|
|
92
92
|
'json-schema-to-ts': {
|
|
@@ -94,7 +94,7 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
94
94
|
url: 'https://npm.im/json-schema-to-ts',
|
|
95
95
|
},
|
|
96
96
|
oas: {
|
|
97
|
-
reason: 'Used within
|
|
97
|
+
reason: 'Used within `@readme/api-core` and is also loaded for TypeScript types.',
|
|
98
98
|
url: 'https://npm.im/oas',
|
|
99
99
|
},
|
|
100
100
|
};
|
|
@@ -229,7 +229,7 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
229
229
|
sdkSource
|
|
230
230
|
.getImportDeclarations()
|
|
231
231
|
.find(id => id.getText().includes('HTTPMethodRange'))
|
|
232
|
-
?.replaceWithText("import type { ConfigOptions, FetchResponse } from 'api
|
|
232
|
+
?.replaceWithText("import type { ConfigOptions, FetchResponse } from '@readme/api-core';");
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
if (this.outputJS) {
|
|
@@ -300,10 +300,10 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
300
300
|
{
|
|
301
301
|
// `HTTPMethodRange` will be conditionally removed later if it ends up not being used.
|
|
302
302
|
defaultImport: 'type { ConfigOptions, FetchResponse, HTTPMethodRange }',
|
|
303
|
-
moduleSpecifier: 'api
|
|
303
|
+
moduleSpecifier: '@readme/api-core',
|
|
304
304
|
},
|
|
305
305
|
{ defaultImport: 'Oas', moduleSpecifier: 'oas' },
|
|
306
|
-
{ defaultImport: 'APICore', moduleSpecifier: 'api
|
|
306
|
+
{ defaultImport: 'APICore', moduleSpecifier: '@readme/api-core' },
|
|
307
307
|
{ defaultImport: 'definition', moduleSpecifier: this.specPath },
|
|
308
308
|
]);
|
|
309
309
|
|
|
@@ -710,7 +710,7 @@ sdk.server('https://eu.api.example.com/v14');`),
|
|
|
710
710
|
// our `metadata` parameter is actually required for this operation this is the only way we're
|
|
711
711
|
// able to have an optional `body` parameter be present before `metadata`.
|
|
712
712
|
//
|
|
713
|
-
// Thankfully our core fetch work in
|
|
713
|
+
// Thankfully our core fetch work in `@readme/api-core` is able to do the proper determination to
|
|
714
714
|
// see if what the user is supplying is `metadata` or `body` content when they supply one or
|
|
715
715
|
// both.
|
|
716
716
|
operationIdAccessor.addParameters([
|
package/src/packageInfo.ts
CHANGED