@nymphjs/client 1.0.0-beta.1 → 1.0.0-beta.100
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/CHANGELOG.md +456 -0
- package/README.md +7 -7
- package/asyncitertest.js +53 -0
- package/dist/Entity.d.ts +156 -0
- package/dist/Entity.js +598 -0
- package/dist/Entity.js.map +1 -0
- package/dist/Entity.types.d.ts +218 -0
- package/dist/Entity.types.js +2 -0
- package/dist/Entity.types.js.map +1 -0
- package/dist/EntityWeakCache.d.ts +6 -0
- package/dist/EntityWeakCache.js +27 -0
- package/dist/EntityWeakCache.js.map +1 -0
- package/dist/HttpRequester.d.ts +78 -0
- package/dist/HttpRequester.js +365 -0
- package/dist/HttpRequester.js.map +1 -0
- package/dist/Nymph.d.ts +116 -0
- package/dist/Nymph.js +459 -0
- package/dist/Nymph.js.map +1 -0
- package/dist/Nymph.types.d.ts +177 -0
- package/dist/Nymph.types.js +2 -0
- package/dist/Nymph.types.js.map +1 -0
- package/dist/PubSub.d.ts +63 -0
- package/dist/PubSub.js +599 -0
- package/dist/PubSub.js.map +1 -0
- package/dist/PubSub.types.d.ts +31 -0
- package/dist/PubSub.types.js +2 -0
- package/dist/PubSub.types.js.map +1 -0
- package/dist/entityRefresh.d.ts +5 -0
- package/dist/entityRefresh.js +75 -0
- package/dist/entityRefresh.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +93 -0
- package/dist/utils.js.map +1 -0
- package/jest.config.js +11 -2
- package/lib/Entity.d.ts +112 -8
- package/lib/Entity.js +159 -77
- package/lib/Entity.js.map +1 -1
- package/lib/Entity.types.d.ts +144 -9
- package/lib/EntityWeakCache.js +3 -2
- package/lib/EntityWeakCache.js.map +1 -1
- package/lib/HttpRequester.d.ts +44 -8
- package/lib/HttpRequester.js +236 -21
- package/lib/HttpRequester.js.map +1 -1
- package/lib/Nymph.d.ts +43 -11
- package/lib/Nymph.js +102 -19
- package/lib/Nymph.js.map +1 -1
- package/lib/Nymph.types.d.ts +73 -1
- package/lib/PubSub.d.ts +15 -9
- package/lib/PubSub.js +148 -87
- package/lib/PubSub.js.map +1 -1
- package/lib/PubSub.types.d.ts +6 -1
- package/lib/entityRefresh.js +16 -0
- package/lib/entityRefresh.js.map +1 -1
- package/lib/utils.js +11 -0
- package/lib/utils.js.map +1 -1
- package/package.json +23 -27
- package/src/Entity.ts +171 -108
- package/src/Entity.types.ts +29 -47
- package/src/EntityWeakCache.ts +8 -6
- package/src/HttpRequester.ts +308 -35
- package/src/Nymph.ts +212 -96
- package/src/Nymph.types.ts +51 -2
- package/src/PubSub.ts +214 -141
- package/src/PubSub.types.ts +10 -5
- package/src/entityRefresh.ts +6 -6
- package/src/index.ts +10 -10
- package/src/utils.ts +12 -5
- package/tsconfig.json +6 -4
- package/typedoc.json +4 -0
- package/dist/index.js.LICENSE.txt +0 -8
- package/webpack.config.js +0 -28
package/src/EntityWeakCache.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { EntityConstructor, EntityInterface } from './Entity.types';
|
|
1
|
+
import { EntityConstructor, EntityInterface } from './Entity.types.js';
|
|
2
2
|
|
|
3
3
|
export default class EntityWeakCache {
|
|
4
|
-
private references: WeakMap<
|
|
5
|
-
|
|
4
|
+
private references: WeakMap<
|
|
5
|
+
EntityConstructor,
|
|
6
|
+
{ [k: string]: WeakRef<EntityInterface> }
|
|
7
|
+
> = new WeakMap();
|
|
6
8
|
|
|
7
9
|
get(EntityClass: EntityConstructor, guid: string): EntityInterface | null {
|
|
8
10
|
const classMap = this.references.get(EntityClass);
|
|
9
11
|
if (classMap && guid in classMap) {
|
|
10
12
|
const weakRef = classMap[guid];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const deref = weakRef && weakRef.deref();
|
|
14
|
+
if (deref != null) {
|
|
15
|
+
return deref;
|
|
13
16
|
} else {
|
|
14
17
|
delete classMap[guid];
|
|
15
18
|
}
|
|
@@ -22,7 +25,6 @@ export default class EntityWeakCache {
|
|
|
22
25
|
return;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
// @ts-ignore TS doesn't know about WeakRef.
|
|
26
28
|
const weakRef = new WeakRef(entity);
|
|
27
29
|
|
|
28
30
|
const classMap = this.references.get(EntityClass) || {};
|
package/src/HttpRequester.ts
CHANGED
|
@@ -1,25 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchEventSource,
|
|
3
|
+
EventStreamContentType,
|
|
4
|
+
} from 'fetch-event-source-hperrin';
|
|
5
|
+
|
|
1
6
|
export type HttpRequesterEventType = 'request' | 'response';
|
|
2
7
|
export type HttpRequesterRequestCallback = (
|
|
3
8
|
requester: HttpRequester,
|
|
4
9
|
url: string,
|
|
5
|
-
options: RequestInit
|
|
10
|
+
options: RequestInit,
|
|
6
11
|
) => void;
|
|
7
12
|
export type HttpRequesterResponseCallback = (
|
|
8
13
|
requester: HttpRequester,
|
|
9
14
|
response: Response,
|
|
10
|
-
text: string
|
|
15
|
+
text: string,
|
|
16
|
+
) => void;
|
|
17
|
+
export type HttpRequesterIteratorCallback = (
|
|
18
|
+
requester: HttpRequester,
|
|
19
|
+
url: string,
|
|
20
|
+
headers: Record<string, string>,
|
|
11
21
|
) => void;
|
|
12
22
|
export type HttpRequesterRequestOptions = {
|
|
13
23
|
url: string;
|
|
24
|
+
headers?: { [k: string]: any };
|
|
14
25
|
data: { [k: string]: any };
|
|
15
26
|
dataType: string;
|
|
16
27
|
};
|
|
17
28
|
|
|
29
|
+
export interface AbortableAsyncIterator<T extends any = any>
|
|
30
|
+
extends AsyncIterable<T> {
|
|
31
|
+
abortController: AbortController;
|
|
32
|
+
}
|
|
33
|
+
|
|
18
34
|
export default class HttpRequester {
|
|
19
35
|
private fetch: WindowOrWorkerGlobalScope['fetch'];
|
|
20
|
-
private xsrfToken: string | null = null;
|
|
21
36
|
private requestCallbacks: HttpRequesterRequestCallback[] = [];
|
|
22
37
|
private responseCallbacks: HttpRequesterResponseCallback[] = [];
|
|
38
|
+
private iteratorCallbacks: HttpRequesterIteratorCallback[] = [];
|
|
23
39
|
|
|
24
40
|
static makeUrl(url: string, data: { [k: string]: any }) {
|
|
25
41
|
if (!data) {
|
|
@@ -45,14 +61,18 @@ export default class HttpRequester {
|
|
|
45
61
|
callback: T extends 'request'
|
|
46
62
|
? HttpRequesterRequestCallback
|
|
47
63
|
: T extends 'response'
|
|
48
|
-
|
|
49
|
-
|
|
64
|
+
? HttpRequesterResponseCallback
|
|
65
|
+
: T extends 'iterator'
|
|
66
|
+
? HttpRequesterIteratorCallback
|
|
67
|
+
: never,
|
|
50
68
|
) {
|
|
51
69
|
const prop = (event + 'Callbacks') as T extends 'request'
|
|
52
70
|
? 'requestCallbacks'
|
|
53
71
|
: T extends 'response'
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
? 'responseCallbacks'
|
|
73
|
+
: T extends 'iterator'
|
|
74
|
+
? 'iteratorCallbacks'
|
|
75
|
+
: never;
|
|
56
76
|
if (!(prop in this)) {
|
|
57
77
|
throw new Error('Invalid event type.');
|
|
58
78
|
}
|
|
@@ -66,14 +86,18 @@ export default class HttpRequester {
|
|
|
66
86
|
callback: T extends 'request'
|
|
67
87
|
? HttpRequesterRequestCallback
|
|
68
88
|
: T extends 'response'
|
|
69
|
-
|
|
70
|
-
|
|
89
|
+
? HttpRequesterResponseCallback
|
|
90
|
+
: T extends 'iterator'
|
|
91
|
+
? HttpRequesterIteratorCallback
|
|
92
|
+
: never,
|
|
71
93
|
) {
|
|
72
94
|
const prop = (event + 'Callbacks') as T extends 'request'
|
|
73
95
|
? 'requestCallbacks'
|
|
74
96
|
: T extends 'response'
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
? 'responseCallbacks'
|
|
98
|
+
: T extends 'iterator'
|
|
99
|
+
? 'iteratorCallbacks'
|
|
100
|
+
: never;
|
|
77
101
|
if (!(prop in this)) {
|
|
78
102
|
return false;
|
|
79
103
|
}
|
|
@@ -86,10 +110,6 @@ export default class HttpRequester {
|
|
|
86
110
|
return true;
|
|
87
111
|
}
|
|
88
112
|
|
|
89
|
-
setXsrfToken(xsrfToken: string | null) {
|
|
90
|
-
this.xsrfToken = xsrfToken;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
113
|
async GET(opt: HttpRequesterRequestOptions) {
|
|
94
114
|
return await this._httpRequest('GET', opt);
|
|
95
115
|
}
|
|
@@ -98,6 +118,10 @@ export default class HttpRequester {
|
|
|
98
118
|
return await this._httpRequest('POST', opt);
|
|
99
119
|
}
|
|
100
120
|
|
|
121
|
+
async POST_ITERATOR(opt: HttpRequesterRequestOptions) {
|
|
122
|
+
return await this._iteratorRequest('POST', opt);
|
|
123
|
+
}
|
|
124
|
+
|
|
101
125
|
async PUT(opt: HttpRequesterRequestOptions) {
|
|
102
126
|
return await this._httpRequest('PUT', opt);
|
|
103
127
|
}
|
|
@@ -112,7 +136,7 @@ export default class HttpRequester {
|
|
|
112
136
|
|
|
113
137
|
async _httpRequest(
|
|
114
138
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
115
|
-
opt: HttpRequesterRequestOptions
|
|
139
|
+
opt: HttpRequesterRequestOptions,
|
|
116
140
|
) {
|
|
117
141
|
const dataString = JSON.stringify(opt.data);
|
|
118
142
|
let url = opt.url;
|
|
@@ -123,7 +147,7 @@ export default class HttpRequester {
|
|
|
123
147
|
}
|
|
124
148
|
const options: RequestInit = {
|
|
125
149
|
method,
|
|
126
|
-
headers: {},
|
|
150
|
+
headers: opt.headers ?? {},
|
|
127
151
|
credentials: 'include',
|
|
128
152
|
};
|
|
129
153
|
|
|
@@ -137,18 +161,13 @@ export default class HttpRequester {
|
|
|
137
161
|
this.requestCallbacks[i] && this.requestCallbacks[i](this, url, options);
|
|
138
162
|
}
|
|
139
163
|
|
|
140
|
-
if (this.xsrfToken !== null) {
|
|
141
|
-
(options.headers as Record<string, string>)['X-Xsrf-Token'] =
|
|
142
|
-
this.xsrfToken;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
164
|
const response = await this.fetch(url, options);
|
|
146
165
|
let text: string;
|
|
147
166
|
try {
|
|
148
167
|
text = await response.text();
|
|
149
168
|
} catch (e: any) {
|
|
150
169
|
throw new InvalidResponseError(
|
|
151
|
-
'Server response did not contain valid text body.'
|
|
170
|
+
'Server response did not contain valid text body.',
|
|
152
171
|
);
|
|
153
172
|
}
|
|
154
173
|
if (!response.ok) {
|
|
@@ -167,9 +186,15 @@ export default class HttpRequester {
|
|
|
167
186
|
};
|
|
168
187
|
}
|
|
169
188
|
errObj.status = response.status;
|
|
170
|
-
throw response.status <
|
|
171
|
-
? new
|
|
172
|
-
:
|
|
189
|
+
throw response.status < 200
|
|
190
|
+
? new InformationalError(response, errObj)
|
|
191
|
+
: response.status < 300
|
|
192
|
+
? new SuccessError(response, errObj)
|
|
193
|
+
: response.status < 400
|
|
194
|
+
? new RedirectError(response, errObj)
|
|
195
|
+
: response.status < 500
|
|
196
|
+
? new ClientError(response, errObj)
|
|
197
|
+
: new ServerError(response, errObj);
|
|
173
198
|
}
|
|
174
199
|
for (let i = 0; i < this.responseCallbacks.length; i++) {
|
|
175
200
|
this.responseCallbacks[i] &&
|
|
@@ -186,13 +211,216 @@ export default class HttpRequester {
|
|
|
186
211
|
throw e;
|
|
187
212
|
}
|
|
188
213
|
throw new InvalidResponseError(
|
|
189
|
-
'Server response was invalid: ' + JSON.stringify(text)
|
|
214
|
+
'Server response was invalid: ' + JSON.stringify(text),
|
|
190
215
|
);
|
|
191
216
|
}
|
|
192
217
|
} else {
|
|
193
218
|
return text;
|
|
194
219
|
}
|
|
195
220
|
}
|
|
221
|
+
|
|
222
|
+
async _iteratorRequest(
|
|
223
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
224
|
+
opt: HttpRequesterRequestOptions,
|
|
225
|
+
): Promise<AbortableAsyncIterator> {
|
|
226
|
+
const dataString = JSON.stringify(opt.data);
|
|
227
|
+
let url = opt.url;
|
|
228
|
+
if (method === 'GET') {
|
|
229
|
+
// TODO: what should this size be?
|
|
230
|
+
// && dataString.length < 1) {
|
|
231
|
+
url = HttpRequester.makeUrl(opt.url, opt.data);
|
|
232
|
+
}
|
|
233
|
+
const hasBody = method !== 'GET' && opt.data;
|
|
234
|
+
const headers: Record<string, string> = opt.headers ?? {};
|
|
235
|
+
|
|
236
|
+
if (hasBody) {
|
|
237
|
+
headers['Content-Type'] = 'application/json';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (let i = 0; i < this.iteratorCallbacks.length; i++) {
|
|
241
|
+
this.iteratorCallbacks[i] &&
|
|
242
|
+
this.iteratorCallbacks[i](this, url, headers);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const responses: any[] = [];
|
|
246
|
+
let nextResponseResolve: (value: void) => void;
|
|
247
|
+
let nextResponseReadyPromise = new Promise<void>((res) => {
|
|
248
|
+
nextResponseResolve = res;
|
|
249
|
+
});
|
|
250
|
+
let responsesDone = false;
|
|
251
|
+
let serverResponse: Response;
|
|
252
|
+
|
|
253
|
+
const ctrl = new AbortController();
|
|
254
|
+
|
|
255
|
+
fetchEventSource(url, {
|
|
256
|
+
openWhenHidden: true,
|
|
257
|
+
fetch: this.fetch,
|
|
258
|
+
|
|
259
|
+
method,
|
|
260
|
+
headers,
|
|
261
|
+
credentials: 'include',
|
|
262
|
+
body: hasBody ? dataString : undefined,
|
|
263
|
+
signal: ctrl.signal,
|
|
264
|
+
|
|
265
|
+
async onopen(response) {
|
|
266
|
+
serverResponse = response;
|
|
267
|
+
if (response.ok) {
|
|
268
|
+
if (response.headers.get('content-type') === EventStreamContentType) {
|
|
269
|
+
throw new InvalidResponseError(
|
|
270
|
+
'Server response is not an event stream.',
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Response is ok, wait for messages.
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let text: string = '';
|
|
279
|
+
try {
|
|
280
|
+
text = await response.text();
|
|
281
|
+
} catch (e: any) {
|
|
282
|
+
// Ignore error here.
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let errObj;
|
|
286
|
+
try {
|
|
287
|
+
errObj = JSON.parse(text);
|
|
288
|
+
} catch (e: any) {
|
|
289
|
+
if (!(e instanceof SyntaxError)) {
|
|
290
|
+
throw e;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (typeof errObj !== 'object') {
|
|
295
|
+
errObj = {
|
|
296
|
+
textStatus: response.statusText,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
errObj.status = response.status;
|
|
300
|
+
throw response.status < 200
|
|
301
|
+
? new InformationalError(response, errObj)
|
|
302
|
+
: response.status < 300
|
|
303
|
+
? new SuccessError(response, errObj)
|
|
304
|
+
: response.status < 400
|
|
305
|
+
? new RedirectError(response, errObj)
|
|
306
|
+
: response.status < 500
|
|
307
|
+
? new ClientError(response, errObj)
|
|
308
|
+
: new ServerError(response, errObj);
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
onmessage(event) {
|
|
312
|
+
if (event.event === 'next') {
|
|
313
|
+
let text = event.data;
|
|
314
|
+
|
|
315
|
+
if (opt.dataType === 'json') {
|
|
316
|
+
if (!text.length) {
|
|
317
|
+
responses.push(
|
|
318
|
+
new InvalidResponseError('Server response was empty.'),
|
|
319
|
+
);
|
|
320
|
+
} else {
|
|
321
|
+
try {
|
|
322
|
+
responses.push(JSON.parse(text));
|
|
323
|
+
} catch (e: any) {
|
|
324
|
+
if (!(e instanceof SyntaxError)) {
|
|
325
|
+
responses.push(e);
|
|
326
|
+
} else {
|
|
327
|
+
responses.push(
|
|
328
|
+
new InvalidResponseError(
|
|
329
|
+
'Server response was invalid: ' + JSON.stringify(text),
|
|
330
|
+
),
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
responses.push(text);
|
|
337
|
+
}
|
|
338
|
+
} else if (event.event === 'error') {
|
|
339
|
+
let text = event.data;
|
|
340
|
+
|
|
341
|
+
let errObj;
|
|
342
|
+
try {
|
|
343
|
+
errObj = JSON.parse(text);
|
|
344
|
+
} catch (e: any) {
|
|
345
|
+
if (!(e instanceof SyntaxError)) {
|
|
346
|
+
throw e;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (typeof errObj !== 'object') {
|
|
351
|
+
errObj = {
|
|
352
|
+
status: 500,
|
|
353
|
+
textStatus: 'Iterator Error',
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
responses.push(
|
|
357
|
+
errObj.status < 200
|
|
358
|
+
? new InformationalError(serverResponse, errObj)
|
|
359
|
+
: errObj.status < 300
|
|
360
|
+
? new SuccessError(serverResponse, errObj)
|
|
361
|
+
: errObj.status < 400
|
|
362
|
+
? new RedirectError(serverResponse, errObj)
|
|
363
|
+
: errObj.status < 500
|
|
364
|
+
? new ClientError(serverResponse, errObj)
|
|
365
|
+
: new ServerError(serverResponse, errObj),
|
|
366
|
+
);
|
|
367
|
+
} else if (event.event === 'finished') {
|
|
368
|
+
responsesDone = true;
|
|
369
|
+
} else if (event.event === 'ping') {
|
|
370
|
+
// Ignore keep-alive pings.
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const resolve = nextResponseResolve;
|
|
375
|
+
if (!responsesDone) {
|
|
376
|
+
nextResponseReadyPromise = new Promise<void>((res) => {
|
|
377
|
+
nextResponseResolve = res;
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Resolve the promise to continue any waiting iterator.
|
|
382
|
+
resolve();
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
onclose() {
|
|
386
|
+
responses.push(
|
|
387
|
+
new ConnectionClosedUnexpectedlyError(
|
|
388
|
+
'The connection to the server was closed unexpectedly.',
|
|
389
|
+
),
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
responsesDone = true;
|
|
393
|
+
nextResponseResolve();
|
|
394
|
+
},
|
|
395
|
+
|
|
396
|
+
onerror(err) {
|
|
397
|
+
// Rethrow to stop the operation.
|
|
398
|
+
throw err;
|
|
399
|
+
},
|
|
400
|
+
}).catch((err) => {
|
|
401
|
+
responses.push(
|
|
402
|
+
new ConnectionError('The connection could not be established: ' + err),
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
responsesDone = true;
|
|
406
|
+
nextResponseResolve();
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
const iterator: AbortableAsyncIterator = {
|
|
410
|
+
abortController: ctrl,
|
|
411
|
+
async *[Symbol.asyncIterator]() {
|
|
412
|
+
do {
|
|
413
|
+
await nextResponseReadyPromise;
|
|
414
|
+
|
|
415
|
+
while (responses.length) {
|
|
416
|
+
yield responses.shift();
|
|
417
|
+
}
|
|
418
|
+
} while (!responsesDone);
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
return iterator;
|
|
423
|
+
}
|
|
196
424
|
}
|
|
197
425
|
|
|
198
426
|
export class InvalidResponseError extends Error {
|
|
@@ -202,18 +430,63 @@ export class InvalidResponseError extends Error {
|
|
|
202
430
|
}
|
|
203
431
|
}
|
|
204
432
|
|
|
205
|
-
export class
|
|
206
|
-
constructor(
|
|
207
|
-
super(
|
|
208
|
-
this.name = '
|
|
209
|
-
|
|
433
|
+
export class ConnectionClosedUnexpectedlyError extends Error {
|
|
434
|
+
constructor(message: string) {
|
|
435
|
+
super(message);
|
|
436
|
+
this.name = 'ConnectionClosedUnexpectedlyError';
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export class ConnectionError extends Error {
|
|
441
|
+
constructor(message: string) {
|
|
442
|
+
super(message);
|
|
443
|
+
this.name = 'ConnectionError';
|
|
210
444
|
}
|
|
211
445
|
}
|
|
212
446
|
|
|
213
|
-
export class
|
|
214
|
-
|
|
447
|
+
export class HttpError extends Error {
|
|
448
|
+
status: number;
|
|
449
|
+
statusText: string;
|
|
450
|
+
|
|
451
|
+
constructor(
|
|
452
|
+
name: string,
|
|
453
|
+
response: Response,
|
|
454
|
+
errObj: { textStatus: string },
|
|
455
|
+
) {
|
|
215
456
|
super(errObj.textStatus);
|
|
216
|
-
this.name =
|
|
457
|
+
this.name = name;
|
|
458
|
+
this.status = response.status;
|
|
459
|
+
this.statusText = response.statusText;
|
|
217
460
|
Object.assign(this, errObj);
|
|
218
461
|
}
|
|
219
462
|
}
|
|
463
|
+
|
|
464
|
+
export class InformationalError extends HttpError {
|
|
465
|
+
constructor(response: Response, errObj: { textStatus: string }) {
|
|
466
|
+
super('InformationalError', response, errObj);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export class SuccessError extends HttpError {
|
|
471
|
+
constructor(response: Response, errObj: { textStatus: string }) {
|
|
472
|
+
super('SuccessError', response, errObj);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export class RedirectError extends HttpError {
|
|
477
|
+
constructor(response: Response, errObj: { textStatus: string }) {
|
|
478
|
+
super('RedirectError', response, errObj);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export class ClientError extends HttpError {
|
|
483
|
+
constructor(response: Response, errObj: { textStatus: string }) {
|
|
484
|
+
super('ClientError', response, errObj);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export class ServerError extends HttpError {
|
|
489
|
+
constructor(response: Response, errObj: { textStatus: string }) {
|
|
490
|
+
super('ServerError', response, errObj);
|
|
491
|
+
}
|
|
492
|
+
}
|