@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 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
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require("./gen");
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 generate(manifest: Manifest): Promise<void> {
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 doc = await load(service.swagger);
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
- const code = prettier.format(print.code(), { parser: "typescript", printWidth: 100 });
104
- const filename = path.join("src", "index.ts");
105
- await fs.promises.writeFile(filename, code);
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 manifest: Manifest = JSON.parse(await fs.promises.readFile("manifest.json", "utf-8"));
357
- const gen = new CodeGenerator();
358
- await gen.generate(manifest);
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 response status was a 4xx error.
138
+ * Returns true if the status code represents a transient error
139
+ * or it's a network error.
138
140
  */
139
- private is_4xx;
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":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"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"}