@compassdigital/sdk.typescript 3.0.0-beta.8 → 3.0.0-rc.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/README.md +121 -8
- package/bin/gen.js +484 -0
- package/bin/index.js +3 -0
- package/gen.ts +99 -41
- package/lib/base.d.ts +134 -9
- package/lib/base.d.ts.map +1 -1
- package/lib/base.js +293 -48
- package/lib/base.js.map +1 -1
- package/lib/index.d.ts +592 -337
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +544 -245
- package/lib/index.js.map +1 -1
- package/lib/interface/announcement.d.ts.map +1 -0
- package/lib/interface/announcement.js +4 -0
- package/lib/interface/announcement.js.map +1 -0
- package/lib/interface/brand.d.ts.map +1 -0
- package/lib/interface/brand.js +4 -0
- package/lib/interface/brand.js.map +1 -0
- package/lib/{calendar.d.ts → interface/calendar.d.ts} +4 -1
- package/lib/interface/calendar.d.ts.map +1 -0
- package/lib/interface/calendar.js +4 -0
- package/lib/interface/calendar.js.map +1 -0
- package/lib/interface/config.d.ts.map +1 -0
- package/lib/interface/config.js +4 -0
- package/lib/interface/config.js.map +1 -0
- package/lib/interface/datalake.d.ts.map +1 -0
- package/lib/interface/datalake.js +4 -0
- package/lib/interface/datalake.js.map +1 -0
- package/lib/interface/delivery.d.ts.map +1 -0
- package/lib/interface/delivery.js +4 -0
- package/lib/interface/delivery.js.map +1 -0
- package/lib/interface/dh.d.ts.map +1 -0
- package/lib/interface/dh.js +4 -0
- package/lib/interface/dh.js.map +1 -0
- package/lib/interface/email.d.ts +21 -0
- package/lib/interface/email.d.ts.map +1 -0
- package/lib/interface/email.js +4 -0
- package/lib/interface/email.js.map +1 -0
- package/lib/interface/file.d.ts.map +1 -0
- package/lib/interface/file.js +4 -0
- package/lib/interface/file.js.map +1 -0
- package/lib/{kds.d.ts → interface/kds.d.ts} +1 -0
- package/lib/interface/kds.d.ts.map +1 -0
- package/lib/interface/kds.js +4 -0
- package/lib/interface/kds.js.map +1 -0
- package/lib/{location.d.ts → interface/location.d.ts} +50 -20
- package/lib/interface/location.d.ts.map +1 -0
- package/lib/interface/location.js +4 -0
- package/lib/interface/location.js.map +1 -0
- package/lib/interface/logger.d.ts.map +1 -0
- package/lib/interface/logger.js +4 -0
- package/lib/interface/logger.js.map +1 -0
- package/lib/interface/loyalty.d.ts.map +1 -0
- package/lib/interface/loyalty.js +4 -0
- package/lib/interface/loyalty.js.map +1 -0
- package/lib/interface/mealplan.d.ts.map +1 -0
- package/lib/interface/mealplan.js +4 -0
- package/lib/interface/mealplan.js.map +1 -0
- package/lib/interface/menu.d.ts +448 -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/lib/interface/message.d.ts.map +1 -0
- package/lib/interface/message.js +4 -0
- package/lib/interface/message.js.map +1 -0
- package/lib/{order.d.ts → interface/order.d.ts} +11 -4
- package/lib/interface/order.d.ts.map +1 -0
- package/lib/interface/order.js +4 -0
- package/lib/interface/order.js.map +1 -0
- package/lib/{partner.d.ts → interface/partner.d.ts} +243 -4
- package/lib/interface/partner.d.ts.map +1 -0
- package/lib/interface/partner.js +4 -0
- package/lib/interface/partner.js.map +1 -0
- package/lib/{payment.d.ts → interface/payment.d.ts} +1 -0
- package/lib/interface/payment.d.ts.map +1 -0
- package/lib/interface/payment.js +4 -0
- package/lib/interface/payment.js.map +1 -0
- package/lib/{promo.d.ts → interface/promo.d.ts} +1 -0
- package/lib/interface/promo.d.ts.map +1 -0
- package/lib/interface/promo.js +4 -0
- package/lib/interface/promo.js.map +1 -0
- package/lib/{report.d.ts → interface/report.d.ts} +2 -0
- package/lib/interface/report.d.ts.map +1 -0
- package/lib/interface/report.js +4 -0
- package/lib/interface/report.js.map +1 -0
- package/lib/interface/schedule.d.ts.map +1 -0
- package/lib/interface/schedule.js +4 -0
- package/lib/interface/schedule.js.map +1 -0
- package/lib/{shoppingcart.d.ts → interface/shoppingcart.d.ts} +10 -1
- package/lib/interface/shoppingcart.d.ts.map +1 -0
- package/lib/interface/shoppingcart.js +4 -0
- package/lib/interface/shoppingcart.js.map +1 -0
- package/lib/interface/task.d.ts.map +1 -0
- package/lib/interface/task.js +4 -0
- package/lib/interface/task.js.map +1 -0
- package/lib/{user.d.ts → interface/user.d.ts} +19 -0
- package/lib/interface/user.d.ts.map +1 -0
- package/lib/interface/user.js +4 -0
- package/lib/interface/user.js.map +1 -0
- package/lib/interface/vote.d.ts.map +1 -0
- package/lib/interface/vote.js +4 -0
- package/lib/interface/vote.js.map +1 -0
- package/manifest.json +4 -0
- package/package.json +15 -5
- package/src/base.ts +315 -35
- package/src/index.ts +2630 -988
- package/src/{announcement.ts → interface/announcement.ts} +2 -0
- package/src/{brand.ts → interface/brand.ts} +2 -0
- package/src/{calendar.ts → interface/calendar.ts} +7 -1
- package/src/{config.ts → interface/config.ts} +2 -0
- package/src/{datalake.ts → interface/datalake.ts} +2 -0
- package/src/{delivery.ts → interface/delivery.ts} +2 -0
- package/src/{dh.ts → interface/dh.ts} +2 -0
- package/src/interface/email.ts +30 -0
- package/src/{file.ts → interface/file.ts} +2 -0
- package/src/{kds.ts → interface/kds.ts} +4 -0
- package/src/{location.ts → interface/location.ts} +76 -35
- package/src/{logger.ts → interface/logger.ts} +2 -0
- package/src/{loyalty.ts → interface/loyalty.ts} +2 -0
- package/src/{mealplan.ts → interface/mealplan.ts} +2 -0
- package/src/interface/menu.ts +649 -0
- package/src/{message.ts → interface/message.ts} +2 -0
- package/src/{order.ts → interface/order.ts} +21 -6
- package/src/{partner.ts → interface/partner.ts} +291 -5
- package/src/{payment.ts → interface/payment.ts} +4 -0
- package/src/{promo.ts → interface/promo.ts} +3 -0
- package/src/{report.ts → interface/report.ts} +4 -0
- package/src/{schedule.ts → interface/schedule.ts} +2 -0
- package/src/{shoppingcart.ts → interface/shoppingcart.ts} +14 -1
- package/src/{task.ts → interface/task.ts} +2 -0
- package/src/{user.ts → interface/user.ts} +34 -1
- package/src/{vote.ts → interface/vote.ts} +2 -0
- package/template.ejs +3 -3
- package/test/client.test.ts +192 -0
- package/test/gen.test.ts +22 -0
- package/lib/announcement.d.ts.map +0 -1
- package/lib/announcement.js +0 -3
- package/lib/announcement.js.map +0 -1
- package/lib/brand.d.ts.map +0 -1
- package/lib/brand.js +0 -3
- package/lib/brand.js.map +0 -1
- package/lib/calendar.d.ts.map +0 -1
- package/lib/calendar.js +0 -3
- package/lib/calendar.js.map +0 -1
- package/lib/config.d.ts.map +0 -1
- package/lib/config.js +0 -3
- package/lib/config.js.map +0 -1
- package/lib/datalake.d.ts.map +0 -1
- package/lib/datalake.js +0 -3
- package/lib/datalake.js.map +0 -1
- package/lib/delivery.d.ts.map +0 -1
- package/lib/delivery.js +0 -3
- package/lib/delivery.js.map +0 -1
- package/lib/dh.d.ts.map +0 -1
- package/lib/dh.js +0 -3
- package/lib/dh.js.map +0 -1
- package/lib/email.d.ts +0 -5
- package/lib/email.d.ts.map +0 -1
- package/lib/email.js +0 -3
- package/lib/email.js.map +0 -1
- package/lib/file.d.ts.map +0 -1
- package/lib/file.js +0 -3
- package/lib/file.js.map +0 -1
- package/lib/kds.d.ts.map +0 -1
- package/lib/kds.js +0 -3
- package/lib/kds.js.map +0 -1
- package/lib/location.d.ts.map +0 -1
- package/lib/location.js +0 -3
- package/lib/location.js.map +0 -1
- package/lib/logger.d.ts.map +0 -1
- package/lib/logger.js +0 -3
- package/lib/logger.js.map +0 -1
- package/lib/loyalty.d.ts.map +0 -1
- package/lib/loyalty.js +0 -3
- package/lib/loyalty.js.map +0 -1
- package/lib/mealplan.d.ts.map +0 -1
- package/lib/mealplan.js +0 -3
- package/lib/mealplan.js.map +0 -1
- package/lib/message.d.ts.map +0 -1
- package/lib/message.js +0 -3
- package/lib/message.js.map +0 -1
- package/lib/order.d.ts.map +0 -1
- package/lib/order.js +0 -3
- package/lib/order.js.map +0 -1
- package/lib/partner.d.ts.map +0 -1
- package/lib/partner.js +0 -3
- package/lib/partner.js.map +0 -1
- package/lib/payment.d.ts.map +0 -1
- package/lib/payment.js +0 -3
- package/lib/payment.js.map +0 -1
- package/lib/promo.d.ts.map +0 -1
- package/lib/promo.js +0 -3
- package/lib/promo.js.map +0 -1
- package/lib/report.d.ts.map +0 -1
- package/lib/report.js +0 -3
- package/lib/report.js.map +0 -1
- package/lib/schedule.d.ts.map +0 -1
- package/lib/schedule.js +0 -3
- package/lib/schedule.js.map +0 -1
- package/lib/shoppingcart.d.ts.map +0 -1
- package/lib/shoppingcart.js +0 -3
- package/lib/shoppingcart.js.map +0 -1
- package/lib/task.d.ts.map +0 -1
- package/lib/task.js +0 -3
- package/lib/task.js.map +0 -1
- package/lib/user.d.ts.map +0 -1
- package/lib/user.js +0 -3
- package/lib/user.js.map +0 -1
- package/lib/vote.d.ts.map +0 -1
- package/lib/vote.js +0 -3
- package/lib/vote.js.map +0 -1
- package/src/email.ts +0 -4
- /package/lib/{announcement.d.ts → interface/announcement.d.ts} +0 -0
- /package/lib/{brand.d.ts → interface/brand.d.ts} +0 -0
- /package/lib/{config.d.ts → interface/config.d.ts} +0 -0
- /package/lib/{datalake.d.ts → interface/datalake.d.ts} +0 -0
- /package/lib/{delivery.d.ts → interface/delivery.d.ts} +0 -0
- /package/lib/{dh.d.ts → interface/dh.d.ts} +0 -0
- /package/lib/{file.d.ts → interface/file.d.ts} +0 -0
- /package/lib/{logger.d.ts → interface/logger.d.ts} +0 -0
- /package/lib/{loyalty.d.ts → interface/loyalty.d.ts} +0 -0
- /package/lib/{mealplan.d.ts → interface/mealplan.d.ts} +0 -0
- /package/lib/{message.d.ts → interface/message.d.ts} +0 -0
- /package/lib/{schedule.d.ts → interface/schedule.d.ts} +0 -0
- /package/lib/{task.d.ts → interface/task.d.ts} +0 -0
- /package/lib/{vote.d.ts → interface/vote.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -8,33 +8,146 @@ Compass Digital Labs TypeScript SDK
|
|
|
8
8
|
$ npm install --save @compassdigital/sdk.typescript@latest
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Example Server Usage
|
|
12
|
+
|
|
13
|
+
``` typescript
|
|
14
|
+
import Provider from "@compassdigital/provider";
|
|
15
|
+
import { GetTaskRequest, GetTaskResponse } from "@compassdigital/sdk.typescript/interface/task";
|
|
16
|
+
|
|
17
|
+
const provider = new Provider({ type: "payment" });
|
|
18
|
+
|
|
19
|
+
provider.on<GetTaskRequest, GetTaskResponse>("get_task", function (req, next): void {
|
|
20
|
+
// ...
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
11
24
|
## Example Client Usage
|
|
12
25
|
|
|
26
|
+
**Instanciate Client:**
|
|
27
|
+
|
|
13
28
|
``` typescript
|
|
14
29
|
import { ServiceClient } from "@compassdigital/sdk.typescript";
|
|
15
30
|
|
|
16
31
|
const api = new ServiceClient({ stage: "dev" });
|
|
32
|
+
```
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
|
|
34
|
+
**Basic Request:**
|
|
35
|
+
|
|
36
|
+
``` typescript
|
|
37
|
+
const task = await api.get_task(id);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Request Options:**
|
|
41
|
+
|
|
42
|
+
* These options may be passed to any request.
|
|
43
|
+
|
|
44
|
+
``` typescript
|
|
45
|
+
interface RequestOptions {
|
|
46
|
+
// environment to make requests to
|
|
47
|
+
stage?: string;
|
|
48
|
+
// authentication token
|
|
49
|
+
token?: string;
|
|
50
|
+
// additional headers
|
|
51
|
+
headers?: Record<string, string>;
|
|
52
|
+
// log all requests and responses
|
|
53
|
+
debug?: boolean;
|
|
54
|
+
// the number of times to retry a request
|
|
55
|
+
retry?: number;
|
|
56
|
+
// make requests against this base url
|
|
57
|
+
// note: the stage property is ignored if base_url is set
|
|
58
|
+
base_url?: string;
|
|
59
|
+
// intercept outgoing http requests
|
|
60
|
+
intercept?: InterceptFn;
|
|
20
61
|
}
|
|
21
62
|
```
|
|
22
63
|
|
|
23
|
-
|
|
64
|
+
* The `RequestOptions` can be provided to the `ServiceClient` constructor or at the request call site.
|
|
65
|
+
* The options provided at the call site will overide options passed to the constructor.
|
|
24
66
|
|
|
25
67
|
``` typescript
|
|
26
|
-
import Provider from "@compassdigital/provider";
|
|
27
|
-
import { GetTaskRequest, GetTaskResponse } from "@compassdigital/sdk.typescript/task";
|
|
28
68
|
|
|
29
|
-
const
|
|
69
|
+
const api = new ServiceClient({
|
|
70
|
+
token: "<token>",
|
|
71
|
+
retry: 2,
|
|
72
|
+
})
|
|
30
73
|
|
|
31
|
-
|
|
32
|
-
|
|
74
|
+
const location = await api.get_location(id, {
|
|
75
|
+
token: "<token>",
|
|
76
|
+
retry: 2,
|
|
33
77
|
})
|
|
34
78
|
```
|
|
35
79
|
|
|
80
|
+
**Error Handling:**
|
|
81
|
+
|
|
82
|
+
* non-200 responses are rejected with a `ServiceError`.
|
|
83
|
+
|
|
84
|
+
``` typescript
|
|
85
|
+
try {
|
|
86
|
+
const shoppingcart = await api.get_shoppingcart(id);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// Since the error type is `unknown` we must type assert before
|
|
89
|
+
// accessing the properties.
|
|
90
|
+
if (err instanceof ServiceError) {
|
|
91
|
+
console.log(err.status, err.code, err.message);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// There are helpers for accessing the status and code
|
|
95
|
+
if (ServiceError.code(err) === 400.31) {
|
|
96
|
+
console.log("Failed to get menu");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
* There is a `ignore` convenience method for ignoring specific status & error codes.
|
|
102
|
+
|
|
103
|
+
``` typescript
|
|
104
|
+
const issue: OrderIssue = { items: [] };
|
|
105
|
+
await api.post_order_issue(id, issue).ignore(400.18, 400.21);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
* There is a `combine` convenience method for returning an object which contains the response or error.
|
|
109
|
+
|
|
110
|
+
``` typescript
|
|
111
|
+
const res = await api.get_task(id).combine();
|
|
112
|
+
|
|
113
|
+
if (res.ok) {
|
|
114
|
+
console.log("task", res.data);
|
|
115
|
+
} else {
|
|
116
|
+
console.log("error", res.err);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Testing:**
|
|
121
|
+
|
|
122
|
+
* You can register an `intercept` function which will recieve all request.
|
|
123
|
+
|
|
124
|
+
``` typescript
|
|
125
|
+
|
|
126
|
+
import {
|
|
127
|
+
ServiceClient,
|
|
128
|
+
RequestData,
|
|
129
|
+
ResponseData,
|
|
130
|
+
FetchFn,
|
|
131
|
+
} from "@compassdigital/sdk.typescript";
|
|
132
|
+
|
|
133
|
+
async function intercept(req: RequestData, fetch: FetchFn): Promise<ResponseData> {
|
|
134
|
+
expect(req.name).toBe("get_shoppingcart");
|
|
135
|
+
return { ok: true, status: 200, body: JSON.stringify({}) }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const api = new ServiceClient({ intercept });
|
|
139
|
+
```
|
|
140
|
+
|
|
36
141
|
## Code Gen
|
|
37
142
|
|
|
38
143
|
1. Add new services to `manifest.json`.
|
|
39
144
|
2. Run `npm run gen`.
|
|
40
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,484 @@
|
|
|
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
|
+
// add nocache query parameter if x-cache-control is specified
|
|
224
|
+
if (this.hasCacheControl(op) && !params.query.properties["nocache"]) {
|
|
225
|
+
params.query.setProperty("nocache", new openapi_ts_1.Schema("boolean"));
|
|
226
|
+
}
|
|
227
|
+
var name_3 = this.inferName(op, service);
|
|
228
|
+
var comment = op.method.toUpperCase() + " " + path_3;
|
|
229
|
+
if (op.obj.summary) {
|
|
230
|
+
comment += " - " + op.obj.summary;
|
|
231
|
+
}
|
|
232
|
+
print.comment(comment);
|
|
233
|
+
print.blank();
|
|
234
|
+
// path parameters
|
|
235
|
+
if (!params.path.isEmpty()) {
|
|
236
|
+
var pathT = name_3.pascal + "Path";
|
|
237
|
+
print.schema(params.path, pathT);
|
|
238
|
+
print.blank();
|
|
239
|
+
}
|
|
240
|
+
// query parameters
|
|
241
|
+
var queryT = name_3.pascal + "Query";
|
|
242
|
+
if (!params.query.isEmpty()) {
|
|
243
|
+
this.addImport(service, queryT);
|
|
244
|
+
print.schema(params.query, queryT);
|
|
245
|
+
print.blank();
|
|
246
|
+
}
|
|
247
|
+
// body
|
|
248
|
+
var bodyT = name_3.pascal + "Body";
|
|
249
|
+
if (!params.body.isEmpty()) {
|
|
250
|
+
this.addImport(service, bodyT);
|
|
251
|
+
print.schema(params.body, bodyT);
|
|
252
|
+
print.blank();
|
|
253
|
+
}
|
|
254
|
+
// response
|
|
255
|
+
var responseT = name_3.pascal + "Response";
|
|
256
|
+
this.addImport(service, responseT);
|
|
257
|
+
print.schema(params.response, responseT);
|
|
258
|
+
print.blank();
|
|
259
|
+
// server request
|
|
260
|
+
var requestT = name_3.pascal + "Request";
|
|
261
|
+
print.schema(this.toRequestSchema(name_3, op), requestT);
|
|
262
|
+
print.blank();
|
|
263
|
+
// method parameters
|
|
264
|
+
var method = {
|
|
265
|
+
comment: comment,
|
|
266
|
+
name: name_3.snake,
|
|
267
|
+
params: [],
|
|
268
|
+
args: ["\"" + service.name + "\"", "\"" + name_3.snake + "\"", "\"" + op.method + "\""],
|
|
269
|
+
response: responseT
|
|
270
|
+
};
|
|
271
|
+
// turn the path into a template string and add the
|
|
272
|
+
// corresponding method parameters.
|
|
273
|
+
var pathexpr = "`" + path_3 + "`";
|
|
274
|
+
for (var _l = 0, _m = this.findPathParams(path_3); _l < _m.length; _l++) {
|
|
275
|
+
var name_4 = _m[_l];
|
|
276
|
+
var schema = params.path.properties[name_4];
|
|
277
|
+
method.params.push({
|
|
278
|
+
name: name_4,
|
|
279
|
+
type: openapi_ts_1.Printer.type(schema),
|
|
280
|
+
required: true,
|
|
281
|
+
description: schema.description
|
|
282
|
+
});
|
|
283
|
+
pathexpr = pathexpr.replace("{" + name_4 + "}", "${" + name_4 + "}");
|
|
284
|
+
}
|
|
285
|
+
method.args.push(pathexpr);
|
|
286
|
+
// if there's a body, make that a parameter too.
|
|
287
|
+
if (!params.body.isEmpty()) {
|
|
288
|
+
method.params.push({
|
|
289
|
+
name: "body",
|
|
290
|
+
type: bodyT,
|
|
291
|
+
required: true,
|
|
292
|
+
description: params.body.description
|
|
293
|
+
});
|
|
294
|
+
method.args.push("body");
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
method.args.push("null");
|
|
298
|
+
}
|
|
299
|
+
// build the options type.
|
|
300
|
+
var options = new openapi_ts_1.Schema("empty");
|
|
301
|
+
if (!params.query.isEmpty()) {
|
|
302
|
+
var query = new openapi_ts_1.Schema(queryT);
|
|
303
|
+
if (params.query.hasRequired()) {
|
|
304
|
+
query.required = true;
|
|
305
|
+
options.required = true;
|
|
306
|
+
}
|
|
307
|
+
options.setProperty("query", query);
|
|
308
|
+
}
|
|
309
|
+
options.merge(new openapi_ts_1.Schema("RequestOptions"));
|
|
310
|
+
method.params.push({
|
|
311
|
+
name: "options",
|
|
312
|
+
type: openapi_ts_1.Printer.type(options),
|
|
313
|
+
required: options.required,
|
|
314
|
+
description: "additional request options"
|
|
315
|
+
});
|
|
316
|
+
method.args.push("options");
|
|
317
|
+
this.methods.push(method);
|
|
318
|
+
}
|
|
319
|
+
// close declaration
|
|
320
|
+
if (ambient) {
|
|
321
|
+
print.raw("}");
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* Infer the operation name from the method and parameter.
|
|
326
|
+
* These are a bunch of dirty hacks to make the generated names consistent.
|
|
327
|
+
*/
|
|
328
|
+
CodeGenerator.prototype.inferName = function (op, service) {
|
|
329
|
+
var method = op.method, path = op.path;
|
|
330
|
+
var path_segments = [];
|
|
331
|
+
// use the operationId from our collection if we have one.
|
|
332
|
+
// TODO: update the swagger.json definitions so we don't need to do this.
|
|
333
|
+
var operationID = operationIDs[op.method + " " + op.path];
|
|
334
|
+
if (!operationID) {
|
|
335
|
+
operationID = op.obj.operationId;
|
|
336
|
+
}
|
|
337
|
+
if (operationID) {
|
|
338
|
+
var parts_1 = operationID.split("_");
|
|
339
|
+
if (parts_1.length > 1) {
|
|
340
|
+
// replace common operationId values with the canonical ones.
|
|
341
|
+
if (parts_1[0] === "create") {
|
|
342
|
+
parts_1[0] = "post";
|
|
343
|
+
}
|
|
344
|
+
if (parts_1[0] === "update") {
|
|
345
|
+
parts_1[0] = "put";
|
|
346
|
+
}
|
|
347
|
+
if (parts_1[0] === "remove") {
|
|
348
|
+
parts_1[0] = "delete";
|
|
349
|
+
}
|
|
350
|
+
if (parts_1[0] === "find") {
|
|
351
|
+
parts_1[0] = "get";
|
|
352
|
+
}
|
|
353
|
+
if (!(0, openapi_ts_1.isMethod)(parts_1[0])) {
|
|
354
|
+
parts_1.unshift(method);
|
|
355
|
+
}
|
|
356
|
+
if (parts_1[0] === method) {
|
|
357
|
+
parts_1.shift(); // remove the method
|
|
358
|
+
if (!parts_1[0].startsWith(service.name)) {
|
|
359
|
+
parts_1.unshift(service.name);
|
|
360
|
+
}
|
|
361
|
+
path_segments = parts_1;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (parts_1.length > 1 && parts_1[0] === method) {
|
|
365
|
+
parts_1.shift(); // remove the method
|
|
366
|
+
if (!parts_1[0].startsWith(service.name)) {
|
|
367
|
+
parts_1.unshift(service.name);
|
|
368
|
+
}
|
|
369
|
+
path_segments = parts_1;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// combined the path & method into a name.
|
|
373
|
+
if (path_segments.length === 0) {
|
|
374
|
+
if (path.endsWith(".json")) {
|
|
375
|
+
path = path.slice(0, -5);
|
|
376
|
+
}
|
|
377
|
+
path_segments = path.split("/").filter(function (segment) {
|
|
378
|
+
return segment != "" && !segment.includes("{");
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
var parts = __spreadArray([method.toLowerCase()], path_segments, true);
|
|
382
|
+
return {
|
|
383
|
+
snake: parts.join("_"),
|
|
384
|
+
pascal: parts.map(function (s) { return s.charAt(0).toUpperCase() + s.substr(1); }).join('')
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Check if the any response has caching enabled.
|
|
389
|
+
*/
|
|
390
|
+
CodeGenerator.prototype.hasCacheControl = function (op) {
|
|
391
|
+
var _a;
|
|
392
|
+
var responses = Object.values((_a = op.obj.responses) !== null && _a !== void 0 ? _a : {});
|
|
393
|
+
return responses.some(function (response) { return "x-cache-control" in response; });
|
|
394
|
+
};
|
|
395
|
+
/**
|
|
396
|
+
* Find all the path parameter names.
|
|
397
|
+
*/
|
|
398
|
+
CodeGenerator.prototype.findPathParams = function (path) {
|
|
399
|
+
var matches = path.matchAll(/{[^}]*}/g);
|
|
400
|
+
return Array.from(matches).map(function (match) {
|
|
401
|
+
return match[0].slice(1, -1);
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Create a Response type by combining the Query, Path, and Body types.
|
|
406
|
+
*/
|
|
407
|
+
CodeGenerator.prototype.toRequestSchema = function (name, details) {
|
|
408
|
+
var request = new openapi_ts_1.Schema("empty");
|
|
409
|
+
if (!details.params.body.isEmpty()) {
|
|
410
|
+
var body = new openapi_ts_1.Schema(name.pascal + "Body");
|
|
411
|
+
body.required = true;
|
|
412
|
+
request.setProperty("body", body);
|
|
413
|
+
}
|
|
414
|
+
if (!details.params.query.isEmpty()) {
|
|
415
|
+
request.merge(new openapi_ts_1.Schema(name.pascal + "Query"));
|
|
416
|
+
}
|
|
417
|
+
if (!details.params.path.isEmpty()) {
|
|
418
|
+
request.merge(new openapi_ts_1.Schema(name.pascal + "Path"));
|
|
419
|
+
}
|
|
420
|
+
return request;
|
|
421
|
+
};
|
|
422
|
+
return CodeGenerator;
|
|
423
|
+
}());
|
|
424
|
+
exports.CodeGenerator = CodeGenerator;
|
|
425
|
+
/**
|
|
426
|
+
* Main entry point.
|
|
427
|
+
*/
|
|
428
|
+
function main() {
|
|
429
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
430
|
+
var argv, data, manifest, gen, gen, code;
|
|
431
|
+
return __generator(this, function (_a) {
|
|
432
|
+
switch (_a.label) {
|
|
433
|
+
case 0:
|
|
434
|
+
argv = (0, yargs_1["default"])((0, helpers_1.hideBin)(process.argv))
|
|
435
|
+
.options("manifest", {
|
|
436
|
+
type: "string",
|
|
437
|
+
description: "manifest.json file to generate sdk from"
|
|
438
|
+
})
|
|
439
|
+
.options("swagger", {
|
|
440
|
+
type: "string",
|
|
441
|
+
description: "swagger.json file to generate interfaces from"
|
|
442
|
+
})
|
|
443
|
+
.options("service", {
|
|
444
|
+
type: "string",
|
|
445
|
+
description: "service name for generated interfaces"
|
|
446
|
+
})
|
|
447
|
+
.options("ambient", {
|
|
448
|
+
type: "boolean",
|
|
449
|
+
description: "wrap the types in a declare module directive",
|
|
450
|
+
"default": true
|
|
451
|
+
}).argv;
|
|
452
|
+
if (!argv.manifest) return [3 /*break*/, 3];
|
|
453
|
+
return [4 /*yield*/, fs_1["default"].promises.readFile(argv.manifest, "utf-8")];
|
|
454
|
+
case 1:
|
|
455
|
+
data = _a.sent();
|
|
456
|
+
manifest = JSON.parse(data);
|
|
457
|
+
gen = new CodeGenerator();
|
|
458
|
+
return [4 /*yield*/, gen.manifest(manifest)];
|
|
459
|
+
case 2:
|
|
460
|
+
_a.sent();
|
|
461
|
+
return [2 /*return*/];
|
|
462
|
+
case 3:
|
|
463
|
+
if (!(argv.swagger || argv.service)) return [3 /*break*/, 5];
|
|
464
|
+
if (!argv.swagger) {
|
|
465
|
+
throw new Error("--swagger must be provided with --service");
|
|
466
|
+
}
|
|
467
|
+
if (!argv.service) {
|
|
468
|
+
throw new Error("--service must be provided with --swagger");
|
|
469
|
+
}
|
|
470
|
+
gen = new CodeGenerator();
|
|
471
|
+
return [4 /*yield*/, gen.service({
|
|
472
|
+
name: argv.service,
|
|
473
|
+
swagger: argv.swagger
|
|
474
|
+
}, argv.ambient)];
|
|
475
|
+
case 4:
|
|
476
|
+
code = _a.sent();
|
|
477
|
+
console.log(code);
|
|
478
|
+
return [2 /*return*/];
|
|
479
|
+
case 5: return [2 /*return*/];
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
main()["catch"](function (err) { return console.error(err.message); });
|
package/bin/index.js
ADDED