@compassdigital/sdk.typescript 3.0.0-beta.16 → 3.0.0-beta.19
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 +8 -0
- package/bin/gen.js +472 -0
- package/bin/index.js +3 -0
- package/gen.ts +71 -20
- package/lib/base.d.ts +5 -4
- package/lib/base.d.ts.map +1 -1
- package/lib/base.js +53 -13
- package/lib/base.js.map +1 -1
- package/lib/index.d.ts +202 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +235 -0
- package/lib/index.js.map +1 -1
- package/lib/interface/menu.d.ts +430 -0
- package/lib/interface/menu.d.ts.map +1 -0
- package/lib/interface/menu.js +4 -0
- package/lib/interface/menu.js.map +1 -0
- package/manifest.json +4 -0
- package/package.json +6 -4
- package/src/base.ts +57 -21
- package/src/index.ts +482 -0
- package/src/interface/menu.ts +622 -0
- package/test/client.test.ts +33 -5
package/README.md
CHANGED
|
@@ -143,3 +143,11 @@ const api = new ServiceClient({ intercept });
|
|
|
143
143
|
1. Add new services to `manifest.json`.
|
|
144
144
|
2. Run `npm run gen`.
|
|
145
145
|
|
|
146
|
+
## Ad-Hoc Code Gen
|
|
147
|
+
|
|
148
|
+
If you need types for a service you're working on and the sdk hasn't been updated yet, then
|
|
149
|
+
you can generate local types from your swagger.
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
$ sdk.typescript --swagger ./swagger.json --service my_service > types/my_service.d.ts
|
|
153
|
+
```
|
package/bin/gen.js
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
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 (_) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
39
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
40
|
+
if (ar || !(i in from)) {
|
|
41
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
42
|
+
ar[i] = from[i];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
46
|
+
};
|
|
47
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
48
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
|
+
};
|
|
50
|
+
exports.__esModule = true;
|
|
51
|
+
exports.CodeGenerator = void 0;
|
|
52
|
+
var fs_1 = __importDefault(require("fs"));
|
|
53
|
+
var openapi_ts_1 = require("@icholy/openapi-ts");
|
|
54
|
+
var prettier_1 = __importDefault(require("prettier"));
|
|
55
|
+
var path_1 = __importDefault(require("path"));
|
|
56
|
+
var ejs_1 = __importDefault(require("ejs"));
|
|
57
|
+
var yargs_1 = __importDefault(require("yargs/yargs"));
|
|
58
|
+
var helpers_1 = require("yargs/helpers");
|
|
59
|
+
/**
|
|
60
|
+
* This is a mapping between "${method} ${path}" and the default
|
|
61
|
+
* operationId.
|
|
62
|
+
*/
|
|
63
|
+
var operationIDs = {
|
|
64
|
+
"get /location/group/{id}/deliverydestination": "get_location_group_deliverydestinations",
|
|
65
|
+
"get /location/search": "get_location_search",
|
|
66
|
+
"get /promo": "get_promos",
|
|
67
|
+
"get /schedule": "get_schedules",
|
|
68
|
+
"get /brand": "get_brands",
|
|
69
|
+
"get /announcement/resource": "get_resources",
|
|
70
|
+
"get /order/location/brand/{id}": "get_order_location_brand"
|
|
71
|
+
};
|
|
72
|
+
var CodeGenerator = /** @class */ (function () {
|
|
73
|
+
function CodeGenerator() {
|
|
74
|
+
this.imports = [];
|
|
75
|
+
this.methods = [];
|
|
76
|
+
}
|
|
77
|
+
CodeGenerator.prototype.manifest = function (manifest) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
79
|
+
var _i, _a, service, code_1, filename_1, code, filename;
|
|
80
|
+
return __generator(this, function (_b) {
|
|
81
|
+
switch (_b.label) {
|
|
82
|
+
case 0:
|
|
83
|
+
// generate service types
|
|
84
|
+
return [4 /*yield*/, fs_1["default"].promises.mkdir(path_1["default"].join("src", "interface"), { recursive: true })];
|
|
85
|
+
case 1:
|
|
86
|
+
// generate service types
|
|
87
|
+
_b.sent();
|
|
88
|
+
_i = 0, _a = manifest.services;
|
|
89
|
+
_b.label = 2;
|
|
90
|
+
case 2:
|
|
91
|
+
if (!(_i < _a.length)) return [3 /*break*/, 6];
|
|
92
|
+
service = _a[_i];
|
|
93
|
+
console.log("reading: " + service.swagger);
|
|
94
|
+
return [4 /*yield*/, this.service(service, false)];
|
|
95
|
+
case 3:
|
|
96
|
+
code_1 = _b.sent();
|
|
97
|
+
filename_1 = path_1["default"].join("src", "interface", service.name + ".ts");
|
|
98
|
+
return [4 /*yield*/, fs_1["default"].promises.writeFile(filename_1, code_1)];
|
|
99
|
+
case 4:
|
|
100
|
+
_b.sent();
|
|
101
|
+
_b.label = 5;
|
|
102
|
+
case 5:
|
|
103
|
+
_i++;
|
|
104
|
+
return [3 /*break*/, 2];
|
|
105
|
+
case 6: return [4 /*yield*/, this.client()];
|
|
106
|
+
case 7:
|
|
107
|
+
code = _b.sent();
|
|
108
|
+
filename = path_1["default"].join("src", "index.ts");
|
|
109
|
+
return [4 /*yield*/, fs_1["default"].promises.writeFile(filename, code)];
|
|
110
|
+
case 8:
|
|
111
|
+
_b.sent();
|
|
112
|
+
return [2 /*return*/];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
CodeGenerator.prototype.client = function () {
|
|
118
|
+
var _a;
|
|
119
|
+
var _b;
|
|
120
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
121
|
+
var print, imports, _i, _c, _import, _d, _e, _f, path_2, names, template;
|
|
122
|
+
return __generator(this, function (_g) {
|
|
123
|
+
print = new openapi_ts_1.Printer();
|
|
124
|
+
// "do not modify" warning
|
|
125
|
+
print.comment("THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY");
|
|
126
|
+
print.blank();
|
|
127
|
+
imports = {};
|
|
128
|
+
for (_i = 0, _c = this.imports; _i < _c.length; _i++) {
|
|
129
|
+
_import = _c[_i];
|
|
130
|
+
(_a = imports[_b = _import.path]) !== null && _a !== void 0 ? _a : (imports[_b] = []);
|
|
131
|
+
imports[_import.path].push(_import.name);
|
|
132
|
+
}
|
|
133
|
+
for (_d = 0, _e = Object.entries(imports); _d < _e.length; _d++) {
|
|
134
|
+
_f = _e[_d], path_2 = _f[0], names = _f[1];
|
|
135
|
+
print["import"](path_2, names);
|
|
136
|
+
print.blank();
|
|
137
|
+
}
|
|
138
|
+
template = fs_1["default"].readFileSync("template.ejs", "utf-8");
|
|
139
|
+
print.raw(ejs_1["default"].render(template, { methods: this.methods }));
|
|
140
|
+
return [2 /*return*/, prettier_1["default"].format(print.code(), { parser: "typescript", printWidth: 100 })];
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
CodeGenerator.prototype.service = function (service, ambient) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
146
|
+
var print, doc, details;
|
|
147
|
+
return __generator(this, function (_a) {
|
|
148
|
+
switch (_a.label) {
|
|
149
|
+
case 0:
|
|
150
|
+
print = new openapi_ts_1.Printer();
|
|
151
|
+
return [4 /*yield*/, (0, openapi_ts_1.load)(service.swagger)];
|
|
152
|
+
case 1:
|
|
153
|
+
doc = _a.sent();
|
|
154
|
+
details = (0, openapi_ts_1.analyse)(doc);
|
|
155
|
+
this.transform(details, print, service, ambient);
|
|
156
|
+
return [2 /*return*/, prettier_1["default"].format(print.code(), { parser: "typescript", printWidth: 100 })];
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Add an import that the client will need.
|
|
163
|
+
*/
|
|
164
|
+
CodeGenerator.prototype.addImport = function (service, name) {
|
|
165
|
+
this.imports.push({
|
|
166
|
+
name: name,
|
|
167
|
+
path: "./interface/" + service.name
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Generate typescript code from the document details.
|
|
172
|
+
*/
|
|
173
|
+
CodeGenerator.prototype.transform = function (doc, print, service, ambient) {
|
|
174
|
+
// "do not modify" warning
|
|
175
|
+
print.comment("THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY");
|
|
176
|
+
print.blank();
|
|
177
|
+
// declaration if it's ambient
|
|
178
|
+
if (ambient) {
|
|
179
|
+
print.raw("declare module \"@compassdigital/sdk.typescript/interface/" + service.name + "\" {");
|
|
180
|
+
}
|
|
181
|
+
// definitions
|
|
182
|
+
for (var _i = 0, _a = Object.entries(doc.definitions); _i < _a.length; _i++) {
|
|
183
|
+
var _b = _a[_i], name_1 = _b[0], schema = _b[1];
|
|
184
|
+
print.schema(schema, name_1);
|
|
185
|
+
print.blank();
|
|
186
|
+
}
|
|
187
|
+
// routes
|
|
188
|
+
for (var _c = 0, _d = doc.operations; _c < _d.length; _c++) {
|
|
189
|
+
var op = _d[_c];
|
|
190
|
+
var params = op.params, path_3 = op.path;
|
|
191
|
+
for (var _e = 0, _f = params.skipped; _e < _f.length; _e++) {
|
|
192
|
+
var skipped = _f[_e];
|
|
193
|
+
console.warn("SKIPPED", skipped);
|
|
194
|
+
}
|
|
195
|
+
// add missing path parameters
|
|
196
|
+
for (var _g = 0, _h = this.findPathParams(path_3); _g < _h.length; _g++) {
|
|
197
|
+
var name_2 = _h[_g];
|
|
198
|
+
if (!params.path.properties[name_2]) {
|
|
199
|
+
params.path.setProperty(name_2, new openapi_ts_1.Schema("string", {
|
|
200
|
+
required: true,
|
|
201
|
+
description: "TODO: add parameter to swagger.json"
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// make all path parameters required and valid path types.
|
|
206
|
+
for (var _j = 0, _k = Object.values(params.path.properties); _j < _k.length; _j++) {
|
|
207
|
+
var param = _k[_j];
|
|
208
|
+
if (!param.required) {
|
|
209
|
+
param.required = true;
|
|
210
|
+
if (param.description) {
|
|
211
|
+
param.description += "; ";
|
|
212
|
+
}
|
|
213
|
+
param.description += "TODO: mark parameter as required in swagger";
|
|
214
|
+
}
|
|
215
|
+
if (param.isRef() || param.type === "object") {
|
|
216
|
+
if (param.description) {
|
|
217
|
+
param.description += "; ";
|
|
218
|
+
}
|
|
219
|
+
param.description += "TODO: cannot use " + param.type + " as path parameter";
|
|
220
|
+
param.type = "string";
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
var name_3 = this.inferName(op, service);
|
|
224
|
+
var comment = op.method.toUpperCase() + " " + path_3;
|
|
225
|
+
if (op.obj.summary) {
|
|
226
|
+
comment += " - " + op.obj.summary;
|
|
227
|
+
}
|
|
228
|
+
print.comment(comment);
|
|
229
|
+
print.blank();
|
|
230
|
+
// path parameters
|
|
231
|
+
if (!params.path.isEmpty()) {
|
|
232
|
+
var pathT = name_3.pascal + "Path";
|
|
233
|
+
print.schema(params.path, pathT);
|
|
234
|
+
print.blank();
|
|
235
|
+
}
|
|
236
|
+
// query parameters
|
|
237
|
+
var queryT = name_3.pascal + "Query";
|
|
238
|
+
if (!params.query.isEmpty()) {
|
|
239
|
+
this.addImport(service, queryT);
|
|
240
|
+
print.schema(params.query, queryT);
|
|
241
|
+
print.blank();
|
|
242
|
+
}
|
|
243
|
+
// body
|
|
244
|
+
var bodyT = name_3.pascal + "Body";
|
|
245
|
+
if (!params.body.isEmpty()) {
|
|
246
|
+
this.addImport(service, bodyT);
|
|
247
|
+
print.schema(params.body, bodyT);
|
|
248
|
+
print.blank();
|
|
249
|
+
}
|
|
250
|
+
// response
|
|
251
|
+
var responseT = name_3.pascal + "Response";
|
|
252
|
+
this.addImport(service, responseT);
|
|
253
|
+
print.schema(params.response, responseT);
|
|
254
|
+
print.blank();
|
|
255
|
+
// server request
|
|
256
|
+
var requestT = name_3.pascal + "Request";
|
|
257
|
+
print.schema(this.toRequestSchema(name_3, op), requestT);
|
|
258
|
+
print.blank();
|
|
259
|
+
// method parameters
|
|
260
|
+
var method = {
|
|
261
|
+
comment: comment,
|
|
262
|
+
name: name_3.snake,
|
|
263
|
+
params: [],
|
|
264
|
+
args: ["\"" + service.name + "\"", "\"" + name_3.snake + "\"", "\"" + op.method + "\""],
|
|
265
|
+
response: responseT
|
|
266
|
+
};
|
|
267
|
+
// turn the path into a template string and add the
|
|
268
|
+
// corresponding method parameters.
|
|
269
|
+
var pathexpr = "`" + path_3 + "`";
|
|
270
|
+
for (var _l = 0, _m = this.findPathParams(path_3); _l < _m.length; _l++) {
|
|
271
|
+
var name_4 = _m[_l];
|
|
272
|
+
var schema = params.path.properties[name_4];
|
|
273
|
+
method.params.push({
|
|
274
|
+
name: name_4,
|
|
275
|
+
type: openapi_ts_1.Printer.type(schema),
|
|
276
|
+
required: true,
|
|
277
|
+
description: schema.description
|
|
278
|
+
});
|
|
279
|
+
pathexpr = pathexpr.replace("{" + name_4 + "}", "${" + name_4 + "}");
|
|
280
|
+
}
|
|
281
|
+
method.args.push(pathexpr);
|
|
282
|
+
// if there's a body, make that a parameter too.
|
|
283
|
+
if (!params.body.isEmpty()) {
|
|
284
|
+
method.params.push({
|
|
285
|
+
name: "body",
|
|
286
|
+
type: bodyT,
|
|
287
|
+
required: true,
|
|
288
|
+
description: params.body.description
|
|
289
|
+
});
|
|
290
|
+
method.args.push("body");
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
method.args.push("null");
|
|
294
|
+
}
|
|
295
|
+
// build the options type.
|
|
296
|
+
var options = new openapi_ts_1.Schema("empty");
|
|
297
|
+
if (!params.query.isEmpty()) {
|
|
298
|
+
var query = new openapi_ts_1.Schema(queryT);
|
|
299
|
+
if (params.query.hasRequired()) {
|
|
300
|
+
query.required = true;
|
|
301
|
+
options.required = true;
|
|
302
|
+
}
|
|
303
|
+
options.setProperty("query", query);
|
|
304
|
+
}
|
|
305
|
+
options.merge(new openapi_ts_1.Schema("RequestOptions"));
|
|
306
|
+
method.params.push({
|
|
307
|
+
name: "options",
|
|
308
|
+
type: openapi_ts_1.Printer.type(options),
|
|
309
|
+
required: options.required,
|
|
310
|
+
description: "additional request options"
|
|
311
|
+
});
|
|
312
|
+
method.args.push("options");
|
|
313
|
+
this.methods.push(method);
|
|
314
|
+
}
|
|
315
|
+
// close declaration
|
|
316
|
+
if (ambient) {
|
|
317
|
+
print.raw("}");
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Infer the operation name from the method and parameter.
|
|
322
|
+
* These are a bunch of dirty hacks to make the generated names consistent.
|
|
323
|
+
*/
|
|
324
|
+
CodeGenerator.prototype.inferName = function (op, service) {
|
|
325
|
+
var method = op.method, path = op.path;
|
|
326
|
+
var path_segments = [];
|
|
327
|
+
// use the operationId from our collection if we have one.
|
|
328
|
+
// TODO: update the swagger.json definitions so we don't need to do this.
|
|
329
|
+
var operationID = operationIDs[op.method + " " + op.path];
|
|
330
|
+
if (!operationID) {
|
|
331
|
+
operationID = op.obj.operationId;
|
|
332
|
+
}
|
|
333
|
+
if (operationID) {
|
|
334
|
+
var parts_1 = operationID.split("_");
|
|
335
|
+
if (parts_1.length > 1) {
|
|
336
|
+
// replace common operationId values with the canonical ones.
|
|
337
|
+
if (parts_1[0] === "create") {
|
|
338
|
+
parts_1[0] = "post";
|
|
339
|
+
}
|
|
340
|
+
if (parts_1[0] === "update") {
|
|
341
|
+
parts_1[0] = "put";
|
|
342
|
+
}
|
|
343
|
+
if (parts_1[0] === "remove") {
|
|
344
|
+
parts_1[0] = "delete";
|
|
345
|
+
}
|
|
346
|
+
if (parts_1[0] === "find") {
|
|
347
|
+
parts_1[0] = "get";
|
|
348
|
+
}
|
|
349
|
+
if (!(0, openapi_ts_1.isMethod)(parts_1[0])) {
|
|
350
|
+
parts_1.unshift(method);
|
|
351
|
+
}
|
|
352
|
+
if (parts_1[0] === method) {
|
|
353
|
+
parts_1.shift(); // remove the method
|
|
354
|
+
if (!parts_1[0].startsWith(service.name)) {
|
|
355
|
+
parts_1.unshift(service.name);
|
|
356
|
+
}
|
|
357
|
+
path_segments = parts_1;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (parts_1.length > 1 && parts_1[0] === method) {
|
|
361
|
+
parts_1.shift(); // remove the method
|
|
362
|
+
if (!parts_1[0].startsWith(service.name)) {
|
|
363
|
+
parts_1.unshift(service.name);
|
|
364
|
+
}
|
|
365
|
+
path_segments = parts_1;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// combined the path & method into a name.
|
|
369
|
+
if (path_segments.length === 0) {
|
|
370
|
+
if (path.endsWith(".json")) {
|
|
371
|
+
path = path.slice(0, -5);
|
|
372
|
+
}
|
|
373
|
+
path_segments = path.split("/").filter(function (segment) {
|
|
374
|
+
return segment != "" && !segment.includes("{");
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
var parts = __spreadArray([method.toLowerCase()], path_segments, true);
|
|
378
|
+
return {
|
|
379
|
+
snake: parts.join("_"),
|
|
380
|
+
pascal: parts.map(function (s) { return s.charAt(0).toUpperCase() + s.substr(1); }).join('')
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
/**
|
|
384
|
+
* Find all the path parameter names.
|
|
385
|
+
*/
|
|
386
|
+
CodeGenerator.prototype.findPathParams = function (path) {
|
|
387
|
+
var matches = path.matchAll(/{[^}]*}/g);
|
|
388
|
+
return Array.from(matches).map(function (match) {
|
|
389
|
+
return match[0].slice(1, -1);
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Create a Response type by combining the Query, Path, and Body types.
|
|
394
|
+
*/
|
|
395
|
+
CodeGenerator.prototype.toRequestSchema = function (name, details) {
|
|
396
|
+
var request = new openapi_ts_1.Schema("empty");
|
|
397
|
+
if (!details.params.body.isEmpty()) {
|
|
398
|
+
var body = new openapi_ts_1.Schema(name.pascal + "Body");
|
|
399
|
+
body.required = true;
|
|
400
|
+
request.setProperty("body", body);
|
|
401
|
+
}
|
|
402
|
+
if (!details.params.query.isEmpty()) {
|
|
403
|
+
request.merge(new openapi_ts_1.Schema(name.pascal + "Query"));
|
|
404
|
+
}
|
|
405
|
+
if (!details.params.path.isEmpty()) {
|
|
406
|
+
request.merge(new openapi_ts_1.Schema(name.pascal + "Path"));
|
|
407
|
+
}
|
|
408
|
+
return request;
|
|
409
|
+
};
|
|
410
|
+
return CodeGenerator;
|
|
411
|
+
}());
|
|
412
|
+
exports.CodeGenerator = CodeGenerator;
|
|
413
|
+
/**
|
|
414
|
+
* Main entry point.
|
|
415
|
+
*/
|
|
416
|
+
function main() {
|
|
417
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
418
|
+
var argv, data, manifest, gen, gen, code;
|
|
419
|
+
return __generator(this, function (_a) {
|
|
420
|
+
switch (_a.label) {
|
|
421
|
+
case 0:
|
|
422
|
+
argv = (0, yargs_1["default"])((0, helpers_1.hideBin)(process.argv))
|
|
423
|
+
.options("manifest", {
|
|
424
|
+
type: "string",
|
|
425
|
+
description: "manifest.json file to generate sdk from"
|
|
426
|
+
})
|
|
427
|
+
.options("swagger", {
|
|
428
|
+
type: "string",
|
|
429
|
+
description: "swagger.json file to generate interfaces from"
|
|
430
|
+
})
|
|
431
|
+
.options("service", {
|
|
432
|
+
type: "string",
|
|
433
|
+
description: "service name for generated interfaces"
|
|
434
|
+
})
|
|
435
|
+
.options("ambient", {
|
|
436
|
+
type: "boolean",
|
|
437
|
+
description: "wrap the types in a declare module directive",
|
|
438
|
+
"default": true
|
|
439
|
+
}).argv;
|
|
440
|
+
if (!argv.manifest) return [3 /*break*/, 3];
|
|
441
|
+
return [4 /*yield*/, fs_1["default"].promises.readFile(argv.manifest, "utf-8")];
|
|
442
|
+
case 1:
|
|
443
|
+
data = _a.sent();
|
|
444
|
+
manifest = JSON.parse(data);
|
|
445
|
+
gen = new CodeGenerator();
|
|
446
|
+
return [4 /*yield*/, gen.manifest(manifest)];
|
|
447
|
+
case 2:
|
|
448
|
+
_a.sent();
|
|
449
|
+
return [2 /*return*/];
|
|
450
|
+
case 3:
|
|
451
|
+
if (!(argv.swagger || argv.service)) return [3 /*break*/, 5];
|
|
452
|
+
if (!argv.swagger) {
|
|
453
|
+
throw new Error("--swagger must be provided with --service");
|
|
454
|
+
}
|
|
455
|
+
if (!argv.service) {
|
|
456
|
+
throw new Error("--service must be provided with --swagger");
|
|
457
|
+
}
|
|
458
|
+
gen = new CodeGenerator();
|
|
459
|
+
return [4 /*yield*/, gen.service({
|
|
460
|
+
name: argv.service,
|
|
461
|
+
swagger: argv.swagger
|
|
462
|
+
}, argv.ambient)];
|
|
463
|
+
case 4:
|
|
464
|
+
code = _a.sent();
|
|
465
|
+
console.log(code);
|
|
466
|
+
return [2 /*return*/];
|
|
467
|
+
case 5: return [2 /*return*/];
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
main()["catch"](function (err) { return console.error(err.message); });
|
package/bin/index.js
ADDED
package/gen.ts
CHANGED
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
import prettier from "prettier";
|
|
13
13
|
import path from "path";
|
|
14
14
|
import ejs from "ejs";
|
|
15
|
+
import yargs from "yargs/yargs";
|
|
16
|
+
import { hideBin } from "yargs/helpers";
|
|
15
17
|
|
|
16
18
|
interface Manifest {
|
|
17
19
|
services: ManifestService[];
|
|
@@ -69,20 +71,22 @@ export class CodeGenerator {
|
|
|
69
71
|
private imports: ClientImport[] = [];
|
|
70
72
|
private methods: ClientMethod[] = [];
|
|
71
73
|
|
|
72
|
-
async
|
|
74
|
+
async manifest(manifest: Manifest): Promise<void> {
|
|
73
75
|
// generate service types
|
|
74
76
|
await fs.promises.mkdir(path.join("src", "interface"), { recursive: true });
|
|
75
77
|
for (const service of manifest.services) {
|
|
76
|
-
const print = new Printer();
|
|
77
78
|
console.log(`reading: ${service.swagger}`);
|
|
78
|
-
const
|
|
79
|
-
const details = analyse(doc);
|
|
80
|
-
this.transform(details, print, service);
|
|
81
|
-
const code = prettier.format(print.code(), { parser: "typescript", printWidth: 100 });
|
|
79
|
+
const code = await this.service(service, false);
|
|
82
80
|
const filename = path.join("src", "interface", `${service.name}.ts`);
|
|
83
81
|
await fs.promises.writeFile(filename, code);
|
|
84
82
|
}
|
|
85
83
|
// generate client
|
|
84
|
+
const code = await this.client();
|
|
85
|
+
const filename = path.join("src", "index.ts");
|
|
86
|
+
await fs.promises.writeFile(filename, code);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async client(): Promise<string> {
|
|
86
90
|
const print = new Printer();
|
|
87
91
|
// "do not modify" warning
|
|
88
92
|
print.comment("THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY");
|
|
@@ -100,9 +104,15 @@ export class CodeGenerator {
|
|
|
100
104
|
// client methods
|
|
101
105
|
const template = fs.readFileSync("template.ejs", "utf-8");
|
|
102
106
|
print.raw(ejs.render(template, { methods: this.methods }));
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
return prettier.format(print.code(), { parser: "typescript", printWidth: 100 });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async service(service: ManifestService, ambient: boolean): Promise<string> {
|
|
111
|
+
const print = new Printer();
|
|
112
|
+
const doc = await load(service.swagger);
|
|
113
|
+
const details = analyse(doc);
|
|
114
|
+
this.transform(details, print, service, ambient);
|
|
115
|
+
return prettier.format(print.code(), { parser: "typescript", printWidth: 100 });
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
/**
|
|
@@ -118,10 +128,14 @@ export class CodeGenerator {
|
|
|
118
128
|
/**
|
|
119
129
|
* Generate typescript code from the document details.
|
|
120
130
|
*/
|
|
121
|
-
private transform(doc: DocumentDetails, print: Printer, service: ManifestService): void {
|
|
131
|
+
private transform(doc: DocumentDetails, print: Printer, service: ManifestService, ambient: boolean): void {
|
|
122
132
|
// "do not modify" warning
|
|
123
133
|
print.comment("THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY");
|
|
124
134
|
print.blank();
|
|
135
|
+
// declaration if it's ambient
|
|
136
|
+
if (ambient) {
|
|
137
|
+
print.raw(`declare module "@compassdigital/sdk.typescript/interface/${service.name}" {`);
|
|
138
|
+
}
|
|
125
139
|
// definitions
|
|
126
140
|
for (const [name, schema] of Object.entries(doc.definitions)) {
|
|
127
141
|
print.schema(schema, name);
|
|
@@ -251,6 +265,10 @@ export class CodeGenerator {
|
|
|
251
265
|
method.args.push("options");
|
|
252
266
|
this.methods.push(method);
|
|
253
267
|
}
|
|
268
|
+
// close declaration
|
|
269
|
+
if (ambient) {
|
|
270
|
+
print.raw(`}`);
|
|
271
|
+
}
|
|
254
272
|
}
|
|
255
273
|
|
|
256
274
|
/**
|
|
@@ -353,15 +371,48 @@ export class CodeGenerator {
|
|
|
353
371
|
* Main entry point.
|
|
354
372
|
*/
|
|
355
373
|
async function main() {
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
374
|
+
const { argv } = yargs(hideBin(process.argv))
|
|
375
|
+
.options("manifest", {
|
|
376
|
+
type: "string",
|
|
377
|
+
description: "manifest.json file to generate sdk from",
|
|
378
|
+
})
|
|
379
|
+
.options("swagger", {
|
|
380
|
+
type: "string",
|
|
381
|
+
description: "swagger.json file to generate interfaces from",
|
|
382
|
+
})
|
|
383
|
+
.options("service", {
|
|
384
|
+
type: "string",
|
|
385
|
+
description: "service name for generated interfaces",
|
|
386
|
+
})
|
|
387
|
+
.options("ambient", {
|
|
388
|
+
type: "boolean",
|
|
389
|
+
description: "wrap the types in a declare module directive",
|
|
390
|
+
default: true,
|
|
391
|
+
})
|
|
392
|
+
// generate sdk from manifest
|
|
393
|
+
if (argv.manifest) {
|
|
394
|
+
const data = await fs.promises.readFile(argv.manifest, "utf-8");
|
|
395
|
+
const manifest: Manifest = JSON.parse(data);
|
|
396
|
+
const gen = new CodeGenerator();
|
|
397
|
+
await gen.manifest(manifest);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
// generate interfaces for a single swagger.json
|
|
401
|
+
if (argv.swagger || argv.service) {
|
|
402
|
+
if (!argv.swagger) {
|
|
403
|
+
throw new Error(`--swagger must be provided with --service`);
|
|
404
|
+
}
|
|
405
|
+
if (!argv.service) {
|
|
406
|
+
throw new Error(`--service must be provided with --swagger`);
|
|
407
|
+
}
|
|
408
|
+
const gen = new CodeGenerator();
|
|
409
|
+
const code = await gen.service({
|
|
410
|
+
name: argv.service,
|
|
411
|
+
swagger: argv.swagger,
|
|
412
|
+
}, argv.ambient);
|
|
413
|
+
console.log(code);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
359
416
|
}
|
|
360
417
|
|
|
361
|
-
|
|
362
|
-
* Only generate if --run flag was passed
|
|
363
|
-
*/
|
|
364
|
-
const args = process.argv.splice(2);
|
|
365
|
-
if (args[0] === "--run") {
|
|
366
|
-
main();
|
|
367
|
-
}
|
|
418
|
+
main().catch(err => console.error(err.message));
|
package/lib/base.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export interface ResponseData {
|
|
|
27
27
|
ok: boolean;
|
|
28
28
|
status: number;
|
|
29
29
|
body: string;
|
|
30
|
+
err?: any;
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* A function that performs an https request.
|
|
@@ -74,7 +75,7 @@ export declare class ResponsePromise<T> implements Promise<T> {
|
|
|
74
75
|
/**
|
|
75
76
|
* Either a response body or a service error.
|
|
76
77
|
*/
|
|
77
|
-
declare type EitherResponse<T> = {
|
|
78
|
+
export declare type EitherResponse<T> = {
|
|
78
79
|
ok: true;
|
|
79
80
|
data: T;
|
|
80
81
|
err: null;
|
|
@@ -134,9 +135,10 @@ export declare abstract class BaseServiceClient {
|
|
|
134
135
|
*/
|
|
135
136
|
private fetch;
|
|
136
137
|
/**
|
|
137
|
-
* Returns true if the
|
|
138
|
+
* Returns true if the status code represents a transient error
|
|
139
|
+
* or it's a network error.
|
|
138
140
|
*/
|
|
139
|
-
private
|
|
141
|
+
private should_retry;
|
|
140
142
|
/**
|
|
141
143
|
* Returns the merged options.
|
|
142
144
|
*/
|
|
@@ -153,5 +155,4 @@ export declare abstract class BaseServiceClient {
|
|
|
153
155
|
*/
|
|
154
156
|
private _request;
|
|
155
157
|
}
|
|
156
|
-
export {};
|
|
157
158
|
//# sourceMappingURL=base.d.ts.map
|
package/lib/base.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAE7B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"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"}
|