@compassdigital/sdk.typescript 3.0.0-beta.10 → 3.0.0-beta.11
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/gen.ts +11 -4
- package/lib/base.d.ts +86 -6
- package/lib/base.d.ts.map +1 -1
- package/lib/base.js +120 -28
- package/lib/base.js.map +1 -1
- package/lib/index.d.ts +236 -236
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/order.d.ts +4 -4
- package/lib/order.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/base.ts +120 -15
- package/src/index.ts +273 -238
- package/src/order.ts +6 -6
- package/template.ejs +2 -2
- package/test/client.test.ts +3 -3
- package/test/gen.test.ts +22 -0
package/src/base.ts
CHANGED
|
@@ -19,6 +19,10 @@ export interface RequestOptions {
|
|
|
19
19
|
intercept?: InterceptFn;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The request data provided to intercept
|
|
24
|
+
* functions.
|
|
25
|
+
*/
|
|
22
26
|
export interface RequestData {
|
|
23
27
|
name: string;
|
|
24
28
|
service: string;
|
|
@@ -28,23 +32,78 @@ export interface RequestData {
|
|
|
28
32
|
body?: string;
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
/**
|
|
36
|
+
* The response data expected from
|
|
37
|
+
* intercept functions.
|
|
38
|
+
*/
|
|
31
39
|
export interface ResponseData {
|
|
32
40
|
ok: boolean;
|
|
33
41
|
status: number;
|
|
34
42
|
body: string;
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
/**
|
|
46
|
+
* A function that performs an https request.
|
|
47
|
+
*/
|
|
37
48
|
export type FetchFn = (req: RequestData) => Promise<ResponseData>;
|
|
38
49
|
|
|
50
|
+
/**
|
|
51
|
+
* A function that intercepts an http request and returns a response.
|
|
52
|
+
*/
|
|
39
53
|
export type InterceptFn = (req: RequestData, fetch: FetchFn) => Promise<ResponseData>;
|
|
40
54
|
|
|
41
|
-
|
|
55
|
+
/**
|
|
56
|
+
* We have to re-implement the promise methods instead of just existing
|
|
57
|
+
* the existing Promise class due to: https://github.com/microsoft/TypeScript/issues/15202
|
|
58
|
+
*/
|
|
59
|
+
export class ResponsePromise<T> implements Promise<T> {
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Implements Promise interface.
|
|
63
|
+
*/
|
|
64
|
+
[Symbol.toStringTag] = "[object ResponsePromise]";
|
|
65
|
+
|
|
66
|
+
constructor(private promise: Promise<T>) {}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Implements Promise interface.
|
|
70
|
+
*/
|
|
71
|
+
then<TResult1 = T, TResult2 = never>(
|
|
72
|
+
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
|
|
73
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
74
|
+
): ResponsePromise<TResult1 | TResult2> {
|
|
75
|
+
return new ResponsePromise(this.promise.then(onfulfilled, onrejected));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Implements Promise interface.
|
|
80
|
+
*/
|
|
81
|
+
catch<TResult = never>(
|
|
82
|
+
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
83
|
+
): ResponsePromise<T | TResult> {
|
|
84
|
+
return new ResponsePromise(this.promise.catch(onrejected));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Implements Promise interface.
|
|
89
|
+
*/
|
|
90
|
+
finally(onfinally?: (() => void) | null): ResponsePromise<T> {
|
|
91
|
+
return new ResponsePromise(this.promise.finally(onfinally));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns a promise that resolves to null if http status code
|
|
96
|
+
* or service error code matches one of the provided codes.
|
|
97
|
+
* If no codes are specified, all codes are ignored.
|
|
98
|
+
*/
|
|
99
|
+
ignore(...codes: number[]): ResponsePromise<T | null> {
|
|
100
|
+
return new ResponsePromise(ServiceError.ignore(codes, this.promise));
|
|
101
|
+
}
|
|
46
102
|
}
|
|
47
103
|
|
|
104
|
+
/**
|
|
105
|
+
* An error returned from an api service.
|
|
106
|
+
*/
|
|
48
107
|
export class ServiceError extends Error {
|
|
49
108
|
constructor(
|
|
50
109
|
public status: number, // http status
|
|
@@ -58,6 +117,10 @@ export class ServiceError extends Error {
|
|
|
58
117
|
Object.setPrototypeOf(this, ServiceError.prototype);
|
|
59
118
|
}
|
|
60
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Returns the http status code from err.
|
|
122
|
+
* If err isn't an instance of ServiceError, -1 is returned.
|
|
123
|
+
*/
|
|
61
124
|
static status(err: any): number {
|
|
62
125
|
if (err instanceof ServiceError) {
|
|
63
126
|
return err.status;
|
|
@@ -65,6 +128,10 @@ export class ServiceError extends Error {
|
|
|
65
128
|
return -1;
|
|
66
129
|
}
|
|
67
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Returns the service error code from err.
|
|
133
|
+
* If err isn't an instance of ServiceError, -1 is returned.
|
|
134
|
+
*/
|
|
68
135
|
static code(err: any): number {
|
|
69
136
|
if (err instanceof ServiceError) {
|
|
70
137
|
return err.code;
|
|
@@ -72,11 +139,19 @@ export class ServiceError extends Error {
|
|
|
72
139
|
return -1;
|
|
73
140
|
}
|
|
74
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Returns a promise that resolves to null if http status code
|
|
144
|
+
* or service error code matches one of the provided codes.
|
|
145
|
+
* If no codes are specified, all codes are ignored.
|
|
146
|
+
*/
|
|
75
147
|
static async ignore<T>(codes: number[], response: Promise<T>): Promise<T | null> {
|
|
76
148
|
try {
|
|
77
149
|
return await response;
|
|
78
150
|
} catch (err) {
|
|
79
151
|
if (err instanceof ServiceError) {
|
|
152
|
+
if (codes.length === 0) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
80
155
|
for (const code of codes) {
|
|
81
156
|
if (err.status === code || err.code === code) {
|
|
82
157
|
return null;
|
|
@@ -87,6 +162,9 @@ export class ServiceError extends Error {
|
|
|
87
162
|
}
|
|
88
163
|
}
|
|
89
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Constructs a ServiceError from the provided response data.
|
|
167
|
+
*/
|
|
90
168
|
static from_res(res: ResponseData): ServiceError {
|
|
91
169
|
let message = res.body;
|
|
92
170
|
let code = res.status;
|
|
@@ -101,10 +179,14 @@ export class ServiceError extends Error {
|
|
|
101
179
|
}
|
|
102
180
|
}
|
|
103
181
|
|
|
182
|
+
/**
|
|
183
|
+
* BaseServiceClient contains the logic for executing http requests.
|
|
184
|
+
* This class is meant to be extended by the generated code.
|
|
185
|
+
*/
|
|
104
186
|
export abstract class BaseServiceClient {
|
|
105
|
-
private options:
|
|
187
|
+
private options: RequestOptions;
|
|
106
188
|
|
|
107
|
-
constructor(options?:
|
|
189
|
+
constructor(options?: RequestOptions) {
|
|
108
190
|
this.options = options ?? {};
|
|
109
191
|
}
|
|
110
192
|
|
|
@@ -131,6 +213,10 @@ export abstract class BaseServiceClient {
|
|
|
131
213
|
return url;
|
|
132
214
|
}
|
|
133
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Perform the http request or pass it to the intercept function
|
|
218
|
+
* if one was configured.
|
|
219
|
+
*/
|
|
134
220
|
private async fetch(req: RequestData, options?: RequestOptions): Promise<ResponseData> {
|
|
135
221
|
if (options?.intercept) {
|
|
136
222
|
return options.intercept(req, this.fetch.bind(this));
|
|
@@ -147,28 +233,47 @@ export abstract class BaseServiceClient {
|
|
|
147
233
|
};
|
|
148
234
|
}
|
|
149
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Returns true if the response status was a 4xx error.
|
|
238
|
+
*/
|
|
150
239
|
private is_4xx(res: ResponseData): boolean {
|
|
151
240
|
return 400 <= res.status && res.status < 500;
|
|
152
241
|
}
|
|
153
242
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Returns the merged options.
|
|
245
|
+
*/
|
|
246
|
+
private get_options(options: RequestOptions): RequestOptions {
|
|
157
247
|
return {
|
|
158
248
|
...this.options,
|
|
159
|
-
...service_options,
|
|
160
|
-
...method_options,
|
|
161
249
|
...options,
|
|
162
250
|
headers: {
|
|
163
251
|
...this.options.headers,
|
|
164
|
-
...method_options?.headers,
|
|
165
|
-
...service_options?.headers,
|
|
166
252
|
...options.headers,
|
|
167
253
|
}
|
|
168
254
|
};
|
|
169
255
|
}
|
|
170
256
|
|
|
171
|
-
|
|
257
|
+
/**
|
|
258
|
+
* A delegate to _request that wraps the response in a ResponsePromise.
|
|
259
|
+
*/
|
|
260
|
+
protected request(
|
|
261
|
+
service: string,
|
|
262
|
+
name: string,
|
|
263
|
+
method: string,
|
|
264
|
+
route: string,
|
|
265
|
+
body: any,
|
|
266
|
+
options: { query?: any } & RequestOptions = {}
|
|
267
|
+
): ResponsePromise<any> {
|
|
268
|
+
const promise = this._request(service, name, method, route, body, options);
|
|
269
|
+
return new ResponsePromise(promise);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* The main logic for fulfilling a request as perscribed by
|
|
274
|
+
* the request options.
|
|
275
|
+
*/
|
|
276
|
+
private async _request(
|
|
172
277
|
service: string,
|
|
173
278
|
name: string,
|
|
174
279
|
method: string,
|
|
@@ -176,7 +281,7 @@ export abstract class BaseServiceClient {
|
|
|
176
281
|
body: any,
|
|
177
282
|
options: { query?: any } & RequestOptions = {}
|
|
178
283
|
): Promise<any> {
|
|
179
|
-
options = this.get_options(
|
|
284
|
+
options = this.get_options(options);
|
|
180
285
|
const url = this.build_url(route, options, options.query ?? {});
|
|
181
286
|
const headers = Object.assign({
|
|
182
287
|
"User-Agent": "CDL/ServiceClient"
|