@nymphjs/client 1.0.0-beta.13 → 1.0.0-beta.131
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 +552 -0
- package/README.md +12 -8
- package/asyncitertest.js +53 -0
- package/dist/Entity.d.ts +158 -0
- package/dist/Entity.js +643 -0
- package/dist/Entity.js.map +1 -0
- package/dist/Entity.types.d.ts +216 -0
- package/dist/Entity.types.js +2 -0
- package/{lib → dist}/EntityWeakCache.d.ts +1 -1
- package/{lib → dist}/EntityWeakCache.js +5 -9
- package/dist/EntityWeakCache.js.map +1 -0
- package/{lib → dist}/HttpRequester.d.ts +18 -4
- package/dist/HttpRequester.js +365 -0
- package/dist/HttpRequester.js.map +1 -0
- package/{lib → dist}/Nymph.d.ts +48 -11
- package/{lib → dist}/Nymph.js +172 -56
- package/dist/Nymph.js.map +1 -0
- package/dist/Nymph.types.d.ts +227 -0
- package/dist/Nymph.types.js +45 -0
- package/dist/Nymph.types.js.map +1 -0
- package/{lib → dist}/PubSub.d.ts +16 -10
- package/{lib → dist}/PubSub.js +207 -135
- package/dist/PubSub.js.map +1 -0
- package/{lib → dist}/PubSub.types.d.ts +19 -6
- package/dist/PubSub.types.js +2 -0
- package/{lib → dist}/entityRefresh.d.ts +1 -1
- package/{lib → dist}/entityRefresh.js +21 -13
- 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/{lib → dist}/utils.d.ts +2 -1
- package/dist/utils.js +145 -0
- package/dist/utils.js.map +1 -0
- package/jest.config.js +31 -5
- package/package.json +36 -32
- package/src/Entity.ts +361 -247
- package/src/Entity.types.ts +37 -57
- package/src/EntityWeakCache.ts +8 -6
- package/src/HttpRequester.ts +268 -31
- package/src/Nymph.ts +203 -96
- package/src/Nymph.types.ts +98 -2
- package/src/PubSub.ts +264 -181
- package/src/PubSub.types.ts +33 -19
- package/src/entityRefresh.ts +6 -6
- package/src/index.ts +10 -10
- package/src/utils.ts +67 -14
- package/tsconfig.json +7 -4
- package/typedoc.json +4 -0
- package/dist/index.js.LICENSE.txt +0 -8
- package/lib/Entity.d.ts +0 -51
- package/lib/Entity.js +0 -500
- package/lib/Entity.js.map +0 -1
- package/lib/Entity.types.d.ts +0 -65
- package/lib/Entity.types.js +0 -3
- package/lib/EntityWeakCache.js.map +0 -1
- package/lib/HttpRequester.js +0 -190
- package/lib/HttpRequester.js.map +0 -1
- package/lib/Nymph.js.map +0 -1
- package/lib/Nymph.types.d.ts +0 -98
- package/lib/Nymph.types.js +0 -3
- package/lib/Nymph.types.js.map +0 -1
- package/lib/PubSub.js.map +0 -1
- package/lib/PubSub.types.js +0 -3
- package/lib/entityRefresh.js.map +0 -1
- package/lib/index.d.ts +0 -13
- package/lib/index.js +0 -34
- package/lib/index.js.map +0 -1
- package/lib/utils.js +0 -86
- package/lib/utils.js.map +0 -1
- package/webpack.config.js +0 -28
- /package/{lib → dist}/Entity.types.js.map +0 -0
- /package/{lib → dist}/PubSub.types.js.map +0 -0
package/src/Nymph.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import Entity from './Entity';
|
|
2
|
-
import {
|
|
1
|
+
import Entity, { type EntityInstanceType } from './Entity.js';
|
|
2
|
+
import type {
|
|
3
3
|
EntityConstructor,
|
|
4
|
-
EntityData,
|
|
5
4
|
EntityInterface,
|
|
6
5
|
EntityJson,
|
|
7
6
|
ServerCallResponse,
|
|
8
7
|
ServerCallStaticResponse,
|
|
9
|
-
} from './Entity.types';
|
|
10
|
-
import EntityWeakCache from './EntityWeakCache';
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
8
|
+
} from './Entity.types.js';
|
|
9
|
+
import EntityWeakCache from './EntityWeakCache.js';
|
|
10
|
+
import type { AbortableAsyncIterator } from './HttpRequester.js';
|
|
11
|
+
import HttpRequester, { ClientError } from './HttpRequester.js';
|
|
12
|
+
import type {
|
|
13
13
|
EventType,
|
|
14
14
|
NymphOptions,
|
|
15
15
|
Options,
|
|
16
16
|
RequestCallback,
|
|
17
17
|
ResponseCallback,
|
|
18
18
|
Selector,
|
|
19
|
-
} from './Nymph.types';
|
|
20
|
-
import PubSub from './PubSub';
|
|
21
|
-
import {
|
|
19
|
+
} from './Nymph.types.js';
|
|
20
|
+
import type PubSub from './PubSub.js';
|
|
21
|
+
import {
|
|
22
|
+
classNamesToEntityConstructors,
|
|
23
|
+
entitiesToReferences,
|
|
24
|
+
entityConstructorsToClassNames,
|
|
25
|
+
} from './utils.js';
|
|
22
26
|
|
|
23
27
|
let requester: HttpRequester;
|
|
24
28
|
|
|
@@ -42,19 +46,42 @@ export default class Nymph {
|
|
|
42
46
|
private responseCallbacks: ResponseCallback[] = [];
|
|
43
47
|
private restUrl: string = '';
|
|
44
48
|
private weakCache = false;
|
|
49
|
+
/**
|
|
50
|
+
* Headers that will be sent with every request.
|
|
51
|
+
*
|
|
52
|
+
* These are used by Tilmeld for authentication.
|
|
53
|
+
*/
|
|
54
|
+
public headers: { [k: string]: string } = {};
|
|
55
|
+
/**
|
|
56
|
+
* The entity cache.
|
|
57
|
+
*/
|
|
45
58
|
public cache = new EntityWeakCache();
|
|
59
|
+
/**
|
|
60
|
+
* Return `null` or empty array instead of error when entity/ies not found.
|
|
61
|
+
*/
|
|
62
|
+
public returnNullOnNotFound = false;
|
|
46
63
|
|
|
47
64
|
public constructor(NymphOptions: NymphOptions) {
|
|
48
65
|
this.restUrl = NymphOptions.restUrl;
|
|
49
66
|
// @ts-ignore TS doesn't know about WeakRef.
|
|
50
67
|
this.weakCache = !!NymphOptions.weakCache && typeof WeakRef !== 'undefined';
|
|
68
|
+
if (
|
|
69
|
+
'returnNullOnNotFound' in NymphOptions &&
|
|
70
|
+
NymphOptions.returnNullOnNotFound != null
|
|
71
|
+
) {
|
|
72
|
+
this.returnNullOnNotFound = NymphOptions.returnNullOnNotFound;
|
|
73
|
+
}
|
|
51
74
|
|
|
52
75
|
this.Entity = this.addEntityClass(Entity);
|
|
53
76
|
|
|
54
77
|
requester = new HttpRequester(
|
|
55
|
-
'fetch' in NymphOptions ? NymphOptions.fetch : undefined
|
|
78
|
+
'fetch' in NymphOptions ? NymphOptions.fetch : undefined,
|
|
56
79
|
);
|
|
57
80
|
|
|
81
|
+
if ('renewTokens' in NymphOptions && !NymphOptions.renewTokens) {
|
|
82
|
+
this.headers['X-Tilmeld-Token-Renewal'] = 'off';
|
|
83
|
+
}
|
|
84
|
+
|
|
58
85
|
requester.on('request', (_requester, url, options) => {
|
|
59
86
|
for (let i = 0; i < this.requestCallbacks.length; i++) {
|
|
60
87
|
this.requestCallbacks[i] && this.requestCallbacks[i](url, options);
|
|
@@ -75,8 +102,9 @@ export default class Nymph {
|
|
|
75
102
|
* Nymph and return it. You can then use this class's constructor and methods,
|
|
76
103
|
* which will use this instance of Nymph.
|
|
77
104
|
*
|
|
78
|
-
* Because this creates a subclass, don't use the class
|
|
79
|
-
*
|
|
105
|
+
* Because this creates a subclass, don't use the class returned from
|
|
106
|
+
* `getEntityClass` to check with `instanceof`. Instead, use the base class
|
|
107
|
+
* that you passed into this method.
|
|
80
108
|
*/
|
|
81
109
|
public addEntityClass<T extends EntityConstructor>(entityClass: T): T {
|
|
82
110
|
const nymph = this;
|
|
@@ -91,18 +119,27 @@ export default class Nymph {
|
|
|
91
119
|
return NymphEntity;
|
|
92
120
|
}
|
|
93
121
|
|
|
94
|
-
public getEntityClass(className:
|
|
95
|
-
|
|
96
|
-
|
|
122
|
+
public getEntityClass<T extends EntityConstructor>(className: T): T;
|
|
123
|
+
public getEntityClass(className: string): EntityConstructor;
|
|
124
|
+
public getEntityClass<T extends EntityConstructor = EntityConstructor>(
|
|
125
|
+
className: T | string,
|
|
126
|
+
): T | EntityConstructor {
|
|
127
|
+
let key: string | null = null;
|
|
128
|
+
if (typeof className === 'string') {
|
|
129
|
+
key = className;
|
|
130
|
+
} else {
|
|
131
|
+
key = className.class;
|
|
97
132
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
133
|
+
if (key in this.entityClasses) {
|
|
134
|
+
return this.entityClasses[key];
|
|
135
|
+
}
|
|
136
|
+
throw new ClassNotAvailableError('Tried to use class: ' + key);
|
|
101
137
|
}
|
|
102
138
|
|
|
103
139
|
public async newUID(name: string) {
|
|
104
140
|
const data = await requester.POST({
|
|
105
141
|
url: this.restUrl,
|
|
142
|
+
headers: { ...this.headers },
|
|
106
143
|
dataType: 'text',
|
|
107
144
|
data: { action: 'uid', data: name },
|
|
108
145
|
});
|
|
@@ -112,6 +149,7 @@ export default class Nymph {
|
|
|
112
149
|
public async setUID(name: string, value: number) {
|
|
113
150
|
return await requester.PUT({
|
|
114
151
|
url: this.restUrl,
|
|
152
|
+
headers: { ...this.headers },
|
|
115
153
|
dataType: 'json',
|
|
116
154
|
data: { action: 'uid', data: { name, value } },
|
|
117
155
|
});
|
|
@@ -120,6 +158,7 @@ export default class Nymph {
|
|
|
120
158
|
public async getUID(name: string) {
|
|
121
159
|
const data = await requester.GET({
|
|
122
160
|
url: this.restUrl,
|
|
161
|
+
headers: { ...this.headers },
|
|
123
162
|
dataType: 'text',
|
|
124
163
|
data: { action: 'uid', data: name },
|
|
125
164
|
});
|
|
@@ -129,6 +168,7 @@ export default class Nymph {
|
|
|
129
168
|
public async deleteUID(name: string) {
|
|
130
169
|
return await requester.DELETE({
|
|
131
170
|
url: this.restUrl,
|
|
171
|
+
headers: { ...this.headers },
|
|
132
172
|
dataType: 'text',
|
|
133
173
|
data: { action: 'uid', data: name },
|
|
134
174
|
});
|
|
@@ -152,7 +192,7 @@ export default class Nymph {
|
|
|
152
192
|
) {
|
|
153
193
|
throw new InvalidRequestError(
|
|
154
194
|
'Due to REST restriction, you can only create new entities or ' +
|
|
155
|
-
'update existing entities, not both at the same time.'
|
|
195
|
+
'update existing entities, not both at the same time.',
|
|
156
196
|
);
|
|
157
197
|
}
|
|
158
198
|
});
|
|
@@ -162,7 +202,7 @@ export default class Nymph {
|
|
|
162
202
|
public async patchEntity(entity: EntityInterface) {
|
|
163
203
|
if (entity.guid == null) {
|
|
164
204
|
throw new InvalidRequestError(
|
|
165
|
-
"You can't patch an entity that hasn't yet been saved."
|
|
205
|
+
"You can't patch an entity that hasn't yet been saved.",
|
|
166
206
|
);
|
|
167
207
|
}
|
|
168
208
|
|
|
@@ -179,7 +219,7 @@ export default class Nymph {
|
|
|
179
219
|
if (cur.guid == null) {
|
|
180
220
|
throw new InvalidRequestError(
|
|
181
221
|
'Due to REST restriction, you can only create new entities or ' +
|
|
182
|
-
'update existing entities, not both at the same time.'
|
|
222
|
+
'update existing entities, not both at the same time.',
|
|
183
223
|
);
|
|
184
224
|
}
|
|
185
225
|
});
|
|
@@ -191,22 +231,23 @@ export default class Nymph {
|
|
|
191
231
|
entity: T,
|
|
192
232
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
193
233
|
data: { [k: string]: any },
|
|
194
|
-
plural: false
|
|
234
|
+
plural: false,
|
|
195
235
|
): Promise<T>;
|
|
196
236
|
private async requestWithMethod<T extends EntityInterface>(
|
|
197
237
|
entity: T[],
|
|
198
238
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
199
239
|
data: { [k: string]: any },
|
|
200
|
-
plural: true
|
|
240
|
+
plural: true,
|
|
201
241
|
): Promise<T[]>;
|
|
202
242
|
private async requestWithMethod<T extends EntityInterface>(
|
|
203
243
|
entity: T | T[],
|
|
204
244
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
205
245
|
data: { [k: string]: any },
|
|
206
|
-
plural: boolean
|
|
246
|
+
plural: boolean,
|
|
207
247
|
): Promise<T | T[]> {
|
|
208
248
|
const response = await requester[method]({
|
|
209
249
|
url: this.restUrl,
|
|
250
|
+
headers: { ...this.headers },
|
|
210
251
|
dataType: 'json',
|
|
211
252
|
data: {
|
|
212
253
|
action: plural ? 'entities' : 'entity',
|
|
@@ -216,12 +257,12 @@ export default class Nymph {
|
|
|
216
257
|
if (plural && Array.isArray(entity) && entity.length === response.length) {
|
|
217
258
|
return entity.map((e, i) =>
|
|
218
259
|
response[i] &&
|
|
219
|
-
|
|
260
|
+
response[i].guid != null &&
|
|
220
261
|
(e.guid == null || e.guid === response[i].guid)
|
|
221
262
|
? e.$init(response[i])
|
|
222
|
-
: e
|
|
263
|
+
: e,
|
|
223
264
|
) as T[];
|
|
224
|
-
} else if (!Array.isArray(entity) &&
|
|
265
|
+
} else if (!Array.isArray(entity) && response.guid != null) {
|
|
225
266
|
return entity.$init(response) as T;
|
|
226
267
|
}
|
|
227
268
|
throw new Error('Server error');
|
|
@@ -238,29 +279,39 @@ export default class Nymph {
|
|
|
238
279
|
public async getEntity<T extends EntityConstructor = EntityConstructor>(
|
|
239
280
|
options: Options<T>,
|
|
240
281
|
...selectors: Selector[]
|
|
241
|
-
): Promise<
|
|
282
|
+
): Promise<EntityInstanceType<T> | null>;
|
|
242
283
|
public async getEntity<T extends EntityConstructor = EntityConstructor>(
|
|
243
284
|
options: Options<T> & { return: 'count' },
|
|
244
|
-
guid: string
|
|
285
|
+
guid: string,
|
|
245
286
|
): Promise<number>;
|
|
246
287
|
public async getEntity<T extends EntityConstructor = EntityConstructor>(
|
|
247
288
|
options: Options<T> & { return: 'guid' },
|
|
248
|
-
guid: string
|
|
289
|
+
guid: string,
|
|
249
290
|
): Promise<string | null>;
|
|
250
291
|
public async getEntity<T extends EntityConstructor = EntityConstructor>(
|
|
251
292
|
options: Options<T>,
|
|
252
|
-
guid: string
|
|
253
|
-
): Promise<
|
|
293
|
+
guid: string,
|
|
294
|
+
): Promise<EntityInstanceType<T> | null>;
|
|
254
295
|
public async getEntity<T extends EntityConstructor = EntityConstructor>(
|
|
255
296
|
options: Options<T>,
|
|
256
297
|
...selectors: Selector[] | string[]
|
|
257
|
-
): Promise<
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
298
|
+
): Promise<EntityInstanceType<T> | string | number | null> {
|
|
299
|
+
let data: any = null;
|
|
300
|
+
try {
|
|
301
|
+
// @ts-ignore: Implementation signatures of overloads are not externally visible.
|
|
302
|
+
data = (await this.getEntityData(options, ...selectors)) as
|
|
303
|
+
EntityJson<T> | string | number | null;
|
|
304
|
+
} catch (e: any) {
|
|
305
|
+
if (
|
|
306
|
+
this.returnNullOnNotFound &&
|
|
307
|
+
e instanceof ClientError &&
|
|
308
|
+
e.status === 404
|
|
309
|
+
) {
|
|
310
|
+
data = null;
|
|
311
|
+
} else {
|
|
312
|
+
throw e;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
264
315
|
|
|
265
316
|
if (options.return && options.return === 'count') {
|
|
266
317
|
return Number(data ?? 0) as number;
|
|
@@ -290,23 +341,23 @@ export default class Nymph {
|
|
|
290
341
|
): Promise<EntityJson<T> | null>;
|
|
291
342
|
public async getEntityData<T extends EntityConstructor = EntityConstructor>(
|
|
292
343
|
options: Options<T> & { return: 'count' },
|
|
293
|
-
guid: string
|
|
344
|
+
guid: string,
|
|
294
345
|
): Promise<number>;
|
|
295
346
|
public async getEntityData<T extends EntityConstructor = EntityConstructor>(
|
|
296
347
|
options: Options<T> & { return: 'guid' },
|
|
297
|
-
guid: string
|
|
348
|
+
guid: string,
|
|
298
349
|
): Promise<string | null>;
|
|
299
350
|
public async getEntityData<T extends EntityConstructor = EntityConstructor>(
|
|
300
351
|
options: Options<T>,
|
|
301
|
-
guid: string
|
|
352
|
+
guid: string,
|
|
302
353
|
): Promise<EntityJson<T> | null>;
|
|
303
354
|
public async getEntityData<T extends EntityConstructor = EntityConstructor>(
|
|
304
355
|
options: Options<T>,
|
|
305
356
|
...selectors: Selector[] | string[]
|
|
306
357
|
): Promise<EntityJson<T> | string | number | null> {
|
|
307
|
-
if (options.class
|
|
358
|
+
if (options.class instanceof Entity) {
|
|
308
359
|
throw new InvalidRequestError(
|
|
309
|
-
"You can't make REST requests with the base Entity class."
|
|
360
|
+
"You can't make REST requests with the base Entity class.",
|
|
310
361
|
);
|
|
311
362
|
}
|
|
312
363
|
// Set up options and selectors.
|
|
@@ -315,12 +366,13 @@ export default class Nymph {
|
|
|
315
366
|
}
|
|
316
367
|
const data = await requester.GET({
|
|
317
368
|
url: this.restUrl,
|
|
369
|
+
headers: { ...this.headers },
|
|
318
370
|
dataType: 'json',
|
|
319
371
|
data: {
|
|
320
372
|
action: 'entity',
|
|
321
373
|
data: [
|
|
322
|
-
|
|
323
|
-
...entityConstructorsToClassNames(selectors),
|
|
374
|
+
entityConstructorsToClassNames(options),
|
|
375
|
+
...entityConstructorsToClassNames(entitiesToReferences(selectors)),
|
|
324
376
|
],
|
|
325
377
|
},
|
|
326
378
|
});
|
|
@@ -342,25 +394,42 @@ export default class Nymph {
|
|
|
342
394
|
public async getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
343
395
|
options: Options<T>,
|
|
344
396
|
...selectors: Selector[]
|
|
345
|
-
): Promise<
|
|
397
|
+
): Promise<EntityInstanceType<T>[]>;
|
|
346
398
|
public async getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
347
399
|
options: Options<T>,
|
|
348
400
|
...selectors: Selector[]
|
|
349
|
-
): Promise<
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
401
|
+
): Promise<EntityInstanceType<T>[] | string[] | number> {
|
|
402
|
+
let data = null;
|
|
403
|
+
try {
|
|
404
|
+
data = await requester.GET({
|
|
405
|
+
url: this.restUrl,
|
|
406
|
+
headers: { ...this.headers },
|
|
407
|
+
dataType: 'json',
|
|
408
|
+
data: {
|
|
409
|
+
action: 'entities',
|
|
410
|
+
data: [
|
|
411
|
+
entityConstructorsToClassNames(options),
|
|
412
|
+
...entityConstructorsToClassNames(entitiesToReferences(selectors)),
|
|
413
|
+
],
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
} catch (e: any) {
|
|
417
|
+
if (
|
|
418
|
+
this.returnNullOnNotFound &&
|
|
419
|
+
e instanceof ClientError &&
|
|
420
|
+
e.status === 404
|
|
421
|
+
) {
|
|
422
|
+
data = null;
|
|
423
|
+
} else {
|
|
424
|
+
throw e;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
361
427
|
|
|
362
428
|
if (options.return && options.return === 'count') {
|
|
363
|
-
return Number(data);
|
|
429
|
+
return Number(data ?? 0) as number;
|
|
430
|
+
}
|
|
431
|
+
if (data == null) {
|
|
432
|
+
return [];
|
|
364
433
|
}
|
|
365
434
|
if (options.return && options.return === 'guid') {
|
|
366
435
|
return data;
|
|
@@ -369,12 +438,15 @@ export default class Nymph {
|
|
|
369
438
|
}
|
|
370
439
|
|
|
371
440
|
public initEntity<T extends EntityConstructor = EntityConstructor>(
|
|
372
|
-
entityJSON: EntityJson<T
|
|
373
|
-
):
|
|
374
|
-
const EntityClass =
|
|
441
|
+
entityJSON: EntityJson<T>,
|
|
442
|
+
): EntityInstanceType<T> {
|
|
443
|
+
const EntityClass = classNamesToEntityConstructors<T>(
|
|
444
|
+
this,
|
|
445
|
+
entityJSON.class as unknown as T,
|
|
446
|
+
);
|
|
375
447
|
if (!EntityClass) {
|
|
376
448
|
throw new ClassNotAvailableError(
|
|
377
|
-
entityJSON.class + ' class cannot be found.'
|
|
449
|
+
entityJSON.class + ' class cannot be found.',
|
|
378
450
|
);
|
|
379
451
|
}
|
|
380
452
|
let entity = EntityClass.factorySync();
|
|
@@ -382,30 +454,28 @@ export default class Nymph {
|
|
|
382
454
|
// Try to get it from cache.
|
|
383
455
|
const entityFromCache = this.cache.get(
|
|
384
456
|
EntityClass,
|
|
385
|
-
entityJSON.guid || ''
|
|
457
|
+
entityJSON.guid || '',
|
|
386
458
|
);
|
|
387
459
|
if (entityFromCache != null) {
|
|
388
|
-
entity = entityFromCache
|
|
460
|
+
entity = entityFromCache as EntityInstanceType<T>;
|
|
389
461
|
}
|
|
390
462
|
}
|
|
391
|
-
return entity.$init(entityJSON) as
|
|
463
|
+
return entity.$init(entityJSON) as EntityInstanceType<T>;
|
|
392
464
|
}
|
|
393
465
|
|
|
394
466
|
public getEntityFromCache<T extends EntityConstructor = EntityConstructor>(
|
|
395
467
|
EntityClass: EntityConstructor,
|
|
396
|
-
guid: string
|
|
397
|
-
):
|
|
468
|
+
guid: string,
|
|
469
|
+
): EntityInstanceType<T> | null {
|
|
398
470
|
if (!this.weakCache) {
|
|
399
471
|
return null;
|
|
400
472
|
}
|
|
401
|
-
return this.cache.get(EntityClass, guid) as
|
|
402
|
-
T['factorySync']
|
|
403
|
-
> | null;
|
|
473
|
+
return this.cache.get(EntityClass, guid) as EntityInstanceType<T> | null;
|
|
404
474
|
}
|
|
405
475
|
|
|
406
476
|
public setEntityToCache(
|
|
407
477
|
EntityClass: EntityConstructor,
|
|
408
|
-
entity: EntityInterface
|
|
478
|
+
entity: EntityInterface,
|
|
409
479
|
) {
|
|
410
480
|
if (!this.weakCache) {
|
|
411
481
|
return;
|
|
@@ -417,10 +487,7 @@ export default class Nymph {
|
|
|
417
487
|
if (Array.isArray(item)) {
|
|
418
488
|
// Recurse into lower arrays.
|
|
419
489
|
return item.map((entry) => this.initEntitiesFromData(entry)) as T;
|
|
420
|
-
} else if (
|
|
421
|
-
item instanceof Object &&
|
|
422
|
-
!(item instanceof this.getEntityClass('Entity'))
|
|
423
|
-
) {
|
|
490
|
+
} else if (item instanceof Object && !(item instanceof Entity)) {
|
|
424
491
|
if (
|
|
425
492
|
item.hasOwnProperty('class') &&
|
|
426
493
|
item.hasOwnProperty('guid') &&
|
|
@@ -428,7 +495,10 @@ export default class Nymph {
|
|
|
428
495
|
item.hasOwnProperty('mdate') &&
|
|
429
496
|
item.hasOwnProperty('tags') &&
|
|
430
497
|
item.hasOwnProperty('data') &&
|
|
431
|
-
|
|
498
|
+
classNamesToEntityConstructors(
|
|
499
|
+
this,
|
|
500
|
+
(item as any as EntityJson).class,
|
|
501
|
+
) != null
|
|
432
502
|
) {
|
|
433
503
|
return this.initEntity(item as any as EntityJson) as T;
|
|
434
504
|
} else {
|
|
@@ -444,10 +514,11 @@ export default class Nymph {
|
|
|
444
514
|
|
|
445
515
|
public async deleteEntity(
|
|
446
516
|
entity: EntityInterface | EntityInterface[],
|
|
447
|
-
_plural = false
|
|
517
|
+
_plural = false,
|
|
448
518
|
) {
|
|
449
519
|
return await requester.DELETE({
|
|
450
520
|
url: this.restUrl,
|
|
521
|
+
headers: { ...this.headers },
|
|
451
522
|
dataType: 'json',
|
|
452
523
|
data: {
|
|
453
524
|
action: _plural ? 'entities' : 'entity',
|
|
@@ -473,10 +544,11 @@ export default class Nymph {
|
|
|
473
544
|
entity: EntityInterface,
|
|
474
545
|
method: string,
|
|
475
546
|
params: any[],
|
|
476
|
-
stateless = false
|
|
547
|
+
stateless = false,
|
|
477
548
|
): Promise<ServerCallResponse> {
|
|
478
549
|
const data = await requester.POST({
|
|
479
550
|
url: this.restUrl,
|
|
551
|
+
headers: { ...this.headers },
|
|
480
552
|
dataType: 'json',
|
|
481
553
|
data: {
|
|
482
554
|
action: 'method',
|
|
@@ -484,7 +556,7 @@ export default class Nymph {
|
|
|
484
556
|
entity,
|
|
485
557
|
stateless,
|
|
486
558
|
method,
|
|
487
|
-
params: entitiesToReferences(
|
|
559
|
+
params: entityConstructorsToClassNames(entitiesToReferences(params)),
|
|
488
560
|
},
|
|
489
561
|
},
|
|
490
562
|
});
|
|
@@ -498,10 +570,11 @@ export default class Nymph {
|
|
|
498
570
|
public async serverCallStatic(
|
|
499
571
|
className: string,
|
|
500
572
|
method: string,
|
|
501
|
-
params: any[]
|
|
573
|
+
params: any[],
|
|
502
574
|
): Promise<ServerCallStaticResponse> {
|
|
503
575
|
const data = await requester.POST({
|
|
504
576
|
url: this.restUrl,
|
|
577
|
+
headers: { ...this.headers },
|
|
505
578
|
dataType: 'json',
|
|
506
579
|
data: {
|
|
507
580
|
action: 'method',
|
|
@@ -509,7 +582,7 @@ export default class Nymph {
|
|
|
509
582
|
class: className,
|
|
510
583
|
static: true,
|
|
511
584
|
method: method,
|
|
512
|
-
params: entitiesToReferences(
|
|
585
|
+
params: entityConstructorsToClassNames(entitiesToReferences(params)),
|
|
513
586
|
},
|
|
514
587
|
},
|
|
515
588
|
});
|
|
@@ -517,19 +590,57 @@ export default class Nymph {
|
|
|
517
590
|
return this.initEntitiesFromData(data);
|
|
518
591
|
}
|
|
519
592
|
|
|
593
|
+
public async serverCallStaticIterator(
|
|
594
|
+
className: string,
|
|
595
|
+
method: string,
|
|
596
|
+
params: any[],
|
|
597
|
+
): Promise<AbortableAsyncIterator<ServerCallStaticResponse>> {
|
|
598
|
+
const iterable = await requester.POST_ITERATOR({
|
|
599
|
+
url: this.restUrl,
|
|
600
|
+
headers: { ...this.headers },
|
|
601
|
+
dataType: 'json',
|
|
602
|
+
data: {
|
|
603
|
+
action: 'method',
|
|
604
|
+
data: {
|
|
605
|
+
class: className,
|
|
606
|
+
static: true,
|
|
607
|
+
method: method,
|
|
608
|
+
iterator: true,
|
|
609
|
+
params: entityConstructorsToClassNames(entitiesToReferences(params)),
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
const that = this;
|
|
615
|
+
const iterator: AbortableAsyncIterator = {
|
|
616
|
+
abortController: iterable.abortController,
|
|
617
|
+
async *[Symbol.asyncIterator]() {
|
|
618
|
+
for await (let response of iterable) {
|
|
619
|
+
if (response instanceof Error) {
|
|
620
|
+
yield response;
|
|
621
|
+
} else {
|
|
622
|
+
yield that.initEntitiesFromData(response);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
},
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
return iterator;
|
|
629
|
+
}
|
|
630
|
+
|
|
520
631
|
public on<T extends EventType>(
|
|
521
632
|
event: T,
|
|
522
633
|
callback: T extends 'request'
|
|
523
634
|
? RequestCallback
|
|
524
635
|
: T extends 'response'
|
|
525
|
-
|
|
526
|
-
|
|
636
|
+
? ResponseCallback
|
|
637
|
+
: never,
|
|
527
638
|
) {
|
|
528
639
|
const prop = (event + 'Callbacks') as T extends 'request'
|
|
529
640
|
? 'requestCallbacks'
|
|
530
641
|
: T extends 'request'
|
|
531
|
-
|
|
532
|
-
|
|
642
|
+
? 'responseCallbacks'
|
|
643
|
+
: never;
|
|
533
644
|
if (!(prop in this)) {
|
|
534
645
|
throw new Error('Invalid event type.');
|
|
535
646
|
}
|
|
@@ -543,14 +654,14 @@ export default class Nymph {
|
|
|
543
654
|
callback: T extends 'request'
|
|
544
655
|
? RequestCallback
|
|
545
656
|
: T extends 'response'
|
|
546
|
-
|
|
547
|
-
|
|
657
|
+
? ResponseCallback
|
|
658
|
+
: never,
|
|
548
659
|
) {
|
|
549
660
|
const prop = (event + 'Callbacks') as T extends 'request'
|
|
550
661
|
? 'requestCallbacks'
|
|
551
662
|
: T extends 'request'
|
|
552
|
-
|
|
553
|
-
|
|
663
|
+
? 'responseCallbacks'
|
|
664
|
+
: never;
|
|
554
665
|
if (!(prop in this)) {
|
|
555
666
|
return false;
|
|
556
667
|
}
|
|
@@ -562,10 +673,6 @@ export default class Nymph {
|
|
|
562
673
|
}
|
|
563
674
|
return true;
|
|
564
675
|
}
|
|
565
|
-
|
|
566
|
-
public setXsrfToken(token: string | null) {
|
|
567
|
-
requester.setXsrfToken(token);
|
|
568
|
-
}
|
|
569
676
|
}
|
|
570
677
|
|
|
571
678
|
export class ClassNotAvailableError extends Error {
|