@nymphjs/client 1.0.0-beta.13 → 1.0.0-beta.130
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 +546 -0
- package/README.md +12 -8
- package/asyncitertest.js +53 -0
- package/dist/Entity.d.ts +156 -0
- package/{lib → dist}/Entity.js +244 -118
- 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 +229 -129
- 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.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/Entity.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { difference, isEqual } from 'lodash';
|
|
1
|
+
import { difference, isEqual } from 'lodash-es';
|
|
2
2
|
|
|
3
|
-
import type Nymph from './Nymph';
|
|
3
|
+
import type Nymph from './Nymph.js';
|
|
4
4
|
import {
|
|
5
5
|
EntityConstructor,
|
|
6
6
|
EntityData,
|
|
@@ -8,21 +8,25 @@ import {
|
|
|
8
8
|
EntityJson,
|
|
9
9
|
EntityPatch,
|
|
10
10
|
EntityReference,
|
|
11
|
-
} from './Entity.types';
|
|
11
|
+
} from './Entity.types.js';
|
|
12
12
|
import {
|
|
13
13
|
uniqueStrings,
|
|
14
14
|
entitiesToReferences,
|
|
15
15
|
referencesToEntities,
|
|
16
16
|
sortObj,
|
|
17
|
-
|
|
17
|
+
entityConstructorsToClassNames,
|
|
18
|
+
classNamesToEntityConstructors,
|
|
19
|
+
} from './utils.js';
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'You must use .$ready() to wake it.';
|
|
21
|
+
export type EntityDataType<T> =
|
|
22
|
+
T extends Entity<infer DataType> ? DataType : never;
|
|
22
23
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
export type EntityInstanceType<T extends EntityConstructor> =
|
|
25
|
+
T extends new () => infer E ? E & EntityDataType<E> : never;
|
|
26
|
+
|
|
27
|
+
export default class Entity<
|
|
28
|
+
T extends EntityData = EntityData,
|
|
29
|
+
> implements EntityInterface {
|
|
26
30
|
/**
|
|
27
31
|
* The instance of Nymph to use for queries.
|
|
28
32
|
*/
|
|
@@ -84,15 +88,14 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
84
88
|
*/
|
|
85
89
|
protected $sleepingReference: EntityReference | null = null;
|
|
86
90
|
/**
|
|
87
|
-
* A promise that resolved when the entity's data is
|
|
91
|
+
* A promise that resolved when the entity's data is wake.
|
|
88
92
|
*/
|
|
89
|
-
protected $
|
|
93
|
+
protected $wakePromise: Promise<Entity<T>> | null = null;
|
|
90
94
|
|
|
91
95
|
/**
|
|
92
|
-
*
|
|
93
|
-
* @param guid The ID of the entity to load, undefined for a new entity.
|
|
96
|
+
* Initialize an entity.
|
|
94
97
|
*/
|
|
95
|
-
public constructor(
|
|
98
|
+
public constructor(..._rest: any[]) {
|
|
96
99
|
this.$nymph = (this.constructor as EntityConstructor).nymph;
|
|
97
100
|
this.$dataHandler = {
|
|
98
101
|
has: (data: EntityData, name: string) => {
|
|
@@ -129,7 +132,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
129
132
|
deleteProperty: (data: EntityData, name: string) => {
|
|
130
133
|
if (typeof name !== 'symbol' && this.$isASleepingReference) {
|
|
131
134
|
console.error(
|
|
132
|
-
`Tried to delete data on a sleeping reference: ${name}
|
|
135
|
+
`Tried to delete data on a sleeping reference: ${name}`,
|
|
133
136
|
);
|
|
134
137
|
return false;
|
|
135
138
|
}
|
|
@@ -143,11 +146,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
143
146
|
defineProperty: (
|
|
144
147
|
data: EntityData,
|
|
145
148
|
name: string,
|
|
146
|
-
descriptor: PropertyDescriptor
|
|
149
|
+
descriptor: PropertyDescriptor,
|
|
147
150
|
) => {
|
|
148
151
|
if (typeof name !== 'symbol' && this.$isASleepingReference) {
|
|
149
152
|
console.error(
|
|
150
|
-
`Tried to define data on a sleeping reference: ${name}
|
|
153
|
+
`Tried to define data on a sleeping reference: ${name}`,
|
|
151
154
|
);
|
|
152
155
|
return false;
|
|
153
156
|
}
|
|
@@ -161,7 +164,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
161
164
|
getOwnPropertyDescriptor: (data: EntityData, name: string) => {
|
|
162
165
|
if (typeof name !== 'symbol' && this.$isASleepingReference) {
|
|
163
166
|
console.error(
|
|
164
|
-
`Tried to get property descriptor on a sleeping reference: ${name}
|
|
167
|
+
`Tried to get property descriptor on a sleeping reference: ${name}`,
|
|
165
168
|
);
|
|
166
169
|
return undefined;
|
|
167
170
|
}
|
|
@@ -179,17 +182,6 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
179
182
|
this.$dataStore = {} as T;
|
|
180
183
|
this.$data = new Proxy(this.$dataStore, this.$dataHandler);
|
|
181
184
|
|
|
182
|
-
if (guid != null) {
|
|
183
|
-
this.guid = guid;
|
|
184
|
-
this.$isASleepingReference = true;
|
|
185
|
-
this.$sleepingReference = [
|
|
186
|
-
'nymph_entity_reference',
|
|
187
|
-
this.guid,
|
|
188
|
-
(this.constructor as EntityConstructor).class,
|
|
189
|
-
];
|
|
190
|
-
this.$ready();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
185
|
return new Proxy(this, {
|
|
194
186
|
has(entity: Entity, name: string) {
|
|
195
187
|
if (
|
|
@@ -245,7 +237,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
245
237
|
defineProperty(
|
|
246
238
|
entity: Entity,
|
|
247
239
|
name: string,
|
|
248
|
-
descriptor: PropertyDescriptor
|
|
240
|
+
descriptor: PropertyDescriptor,
|
|
249
241
|
) {
|
|
250
242
|
if (
|
|
251
243
|
typeof name !== 'string' ||
|
|
@@ -273,59 +265,132 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
273
265
|
|
|
274
266
|
ownKeys(entity: Entity) {
|
|
275
267
|
return Object.getOwnPropertyNames(entity).concat(
|
|
276
|
-
Object.getOwnPropertyNames(entity.$data)
|
|
268
|
+
Object.getOwnPropertyNames(entity.$data),
|
|
277
269
|
);
|
|
278
270
|
},
|
|
279
271
|
}) as Entity<T>;
|
|
280
272
|
}
|
|
281
273
|
|
|
282
|
-
|
|
274
|
+
/**
|
|
275
|
+
* Create or retrieve a new entity instance.
|
|
276
|
+
*
|
|
277
|
+
* Note that this will always return an entity, even if the GUID is not found.
|
|
278
|
+
*
|
|
279
|
+
* @param guid An optional GUID to retrieve.
|
|
280
|
+
*/
|
|
281
|
+
public static async factory<E extends Entity>(
|
|
282
|
+
this: {
|
|
283
|
+
new (): E;
|
|
284
|
+
},
|
|
285
|
+
guid?: string,
|
|
286
|
+
): Promise<E & EntityDataType<E>> {
|
|
283
287
|
const cacheEntity = (
|
|
284
|
-
guid
|
|
288
|
+
guid
|
|
289
|
+
? (this as unknown as EntityConstructor).nymph.getEntityFromCache(
|
|
290
|
+
this as unknown as EntityConstructor,
|
|
291
|
+
guid,
|
|
292
|
+
)
|
|
293
|
+
: null
|
|
285
294
|
) as Entity | null;
|
|
286
|
-
|
|
295
|
+
if (cacheEntity) {
|
|
296
|
+
return cacheEntity as E & EntityDataType<E>;
|
|
297
|
+
}
|
|
298
|
+
const entity = new this();
|
|
287
299
|
if (guid != null) {
|
|
288
|
-
|
|
300
|
+
entity.guid = guid;
|
|
301
|
+
entity.$isASleepingReference = true;
|
|
302
|
+
entity.$sleepingReference = [
|
|
303
|
+
'nymph_entity_reference',
|
|
304
|
+
guid,
|
|
305
|
+
(this as unknown as EntityConstructor).class,
|
|
306
|
+
];
|
|
307
|
+
await entity.$wake();
|
|
289
308
|
}
|
|
290
|
-
return entity
|
|
309
|
+
return entity as E & EntityDataType<E>;
|
|
291
310
|
}
|
|
292
311
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
/**
|
|
313
|
+
* Create a new entity instance.
|
|
314
|
+
*/
|
|
315
|
+
public static factorySync<E extends Entity>(this: {
|
|
316
|
+
new (): E;
|
|
317
|
+
}): E & EntityDataType<E> {
|
|
318
|
+
return new this() as E & EntityDataType<E>;
|
|
298
319
|
}
|
|
299
320
|
|
|
300
|
-
|
|
321
|
+
/**
|
|
322
|
+
* Create a new sleeping reference instance.
|
|
323
|
+
*
|
|
324
|
+
* Sleeping references won't retrieve their data from the server until they
|
|
325
|
+
* are readied with `$wake()` or a parent's `$wakeAll()`.
|
|
326
|
+
*
|
|
327
|
+
* @param reference The Nymph Entity Reference to use to wake.
|
|
328
|
+
* @returns The new instance.
|
|
329
|
+
*/
|
|
330
|
+
public static factoryReference<E extends Entity>(
|
|
331
|
+
this: {
|
|
332
|
+
new (): E;
|
|
333
|
+
},
|
|
334
|
+
reference: EntityReference,
|
|
335
|
+
): E & EntityDataType<E> {
|
|
301
336
|
const cacheEntity = (
|
|
302
|
-
reference[1]
|
|
337
|
+
reference[1]
|
|
338
|
+
? (this as unknown as EntityConstructor).nymph.getEntityFromCache(
|
|
339
|
+
this as unknown as EntityConstructor,
|
|
340
|
+
reference[1],
|
|
341
|
+
)
|
|
342
|
+
: null
|
|
303
343
|
) as Entity | null;
|
|
304
344
|
|
|
305
345
|
const entity = cacheEntity || new this();
|
|
306
346
|
if (!cacheEntity) {
|
|
307
347
|
entity.$referenceSleep(reference);
|
|
308
348
|
}
|
|
309
|
-
return entity
|
|
349
|
+
return entity as E & EntityDataType<E>;
|
|
310
350
|
}
|
|
311
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Call a static method on the server version of this entity.
|
|
354
|
+
*
|
|
355
|
+
* @param method The name of the method.
|
|
356
|
+
* @param params The parameters to call the method with.
|
|
357
|
+
* @returns The value that the method on the server returned.
|
|
358
|
+
*/
|
|
312
359
|
public static async serverCallStatic(method: string, params: Iterable<any>) {
|
|
313
360
|
const data = await this.nymph.serverCallStatic(
|
|
314
361
|
this.class,
|
|
315
362
|
method,
|
|
316
363
|
// Turn the params into a real array, in case an arguments object was
|
|
317
364
|
// passed.
|
|
318
|
-
Array.prototype.slice.call(params)
|
|
365
|
+
Array.prototype.slice.call(params),
|
|
319
366
|
);
|
|
320
367
|
return data.return;
|
|
321
368
|
}
|
|
322
369
|
|
|
370
|
+
/**
|
|
371
|
+
* Call a static iterator method on the server version of this entity.
|
|
372
|
+
*
|
|
373
|
+
* @param method The name of the method.
|
|
374
|
+
* @param params The parameters to call the method with.
|
|
375
|
+
* @returns An iterator that iterates over values that the method on the server yields.
|
|
376
|
+
*/
|
|
377
|
+
public static async serverCallStaticIterator(
|
|
378
|
+
method: string,
|
|
379
|
+
params: Iterable<any>,
|
|
380
|
+
) {
|
|
381
|
+
return await this.nymph.serverCallStaticIterator(
|
|
382
|
+
this.class,
|
|
383
|
+
method,
|
|
384
|
+
// Turn the params into a real array, in case an arguments object was
|
|
385
|
+
// passed.
|
|
386
|
+
Array.prototype.slice.call(params),
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
323
390
|
public toJSON() {
|
|
324
|
-
|
|
325
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
326
|
-
}
|
|
391
|
+
this.$check();
|
|
327
392
|
const obj: EntityJson = {
|
|
328
|
-
class: (this.constructor
|
|
393
|
+
class: entityConstructorsToClassNames(this.constructor),
|
|
329
394
|
guid: this.guid,
|
|
330
395
|
cdate: this.cdate,
|
|
331
396
|
mdate: this.mdate,
|
|
@@ -333,7 +398,9 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
333
398
|
data: {},
|
|
334
399
|
};
|
|
335
400
|
for (let [key, value] of Object.entries(this.$dataStore)) {
|
|
336
|
-
obj.data[key] =
|
|
401
|
+
obj.data[key] = entityConstructorsToClassNames(
|
|
402
|
+
entitiesToReferences(value),
|
|
403
|
+
);
|
|
337
404
|
}
|
|
338
405
|
return obj;
|
|
339
406
|
}
|
|
@@ -355,11 +422,17 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
355
422
|
this.$dataStore = Object.entries(entityJson.data)
|
|
356
423
|
.map(([key, value]) => {
|
|
357
424
|
this.$dirty[key] = false;
|
|
358
|
-
return {
|
|
425
|
+
return {
|
|
426
|
+
key,
|
|
427
|
+
value: classNamesToEntityConstructors(
|
|
428
|
+
this.$nymph,
|
|
429
|
+
referencesToEntities(value, this.$nymph),
|
|
430
|
+
),
|
|
431
|
+
};
|
|
359
432
|
})
|
|
360
433
|
.reduce(
|
|
361
434
|
(obj, { key, value }) => Object.assign(obj, { [key]: value }),
|
|
362
|
-
{}
|
|
435
|
+
{},
|
|
363
436
|
) as T;
|
|
364
437
|
this.$data = new Proxy(this.$dataStore, this.$dataHandler);
|
|
365
438
|
|
|
@@ -369,9 +442,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
369
442
|
}
|
|
370
443
|
|
|
371
444
|
public $addTag(...tags: string[]) {
|
|
372
|
-
|
|
373
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
374
|
-
}
|
|
445
|
+
this.$check();
|
|
375
446
|
|
|
376
447
|
if (tags.length < 1) {
|
|
377
448
|
return;
|
|
@@ -380,9 +451,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
380
451
|
}
|
|
381
452
|
|
|
382
453
|
public $arraySearch(array: any[], strict = false) {
|
|
383
|
-
|
|
384
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
385
|
-
}
|
|
454
|
+
this.$check();
|
|
386
455
|
|
|
387
456
|
if (!Array.isArray(array)) {
|
|
388
457
|
return -1;
|
|
@@ -396,20 +465,18 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
396
465
|
return -1;
|
|
397
466
|
}
|
|
398
467
|
|
|
399
|
-
public async $delete(): Promise<
|
|
400
|
-
|
|
401
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
402
|
-
}
|
|
468
|
+
public async $delete(): Promise<void> {
|
|
469
|
+
this.$check();
|
|
403
470
|
|
|
404
471
|
const guid = this.guid;
|
|
405
472
|
|
|
406
|
-
|
|
473
|
+
if ((await this.$nymph.deleteEntity(this)) !== guid) {
|
|
474
|
+
throw new Error('Failed to delete entity.');
|
|
475
|
+
}
|
|
407
476
|
}
|
|
408
477
|
|
|
409
478
|
public $equals(object: any) {
|
|
410
|
-
|
|
411
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
412
|
-
}
|
|
479
|
+
this.$check();
|
|
413
480
|
|
|
414
481
|
if (!(object instanceof Entity)) {
|
|
415
482
|
return false;
|
|
@@ -435,23 +502,21 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
435
502
|
}
|
|
436
503
|
|
|
437
504
|
public $getPatch(): EntityPatch {
|
|
438
|
-
|
|
439
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
440
|
-
}
|
|
505
|
+
this.$check();
|
|
441
506
|
if (this.guid == null) {
|
|
442
507
|
throw new InvalidStateError(
|
|
443
|
-
"You can't make a patch from an unsaved entity."
|
|
508
|
+
"You can't make a patch from an unsaved entity.",
|
|
444
509
|
);
|
|
445
510
|
}
|
|
446
511
|
const patch: EntityPatch = {
|
|
447
512
|
guid: this.guid,
|
|
448
513
|
mdate: this.mdate,
|
|
449
|
-
class: (this.constructor
|
|
514
|
+
class: entityConstructorsToClassNames(this.constructor),
|
|
450
515
|
addTags: this.tags.filter(
|
|
451
|
-
(tag) => this.$originalTags.indexOf(tag) === -1
|
|
516
|
+
(tag) => this.$originalTags.indexOf(tag) === -1,
|
|
452
517
|
),
|
|
453
518
|
removeTags: this.$originalTags.filter(
|
|
454
|
-
(tag) => this.tags.indexOf(tag) === -1
|
|
519
|
+
(tag) => this.tags.indexOf(tag) === -1,
|
|
455
520
|
),
|
|
456
521
|
unset: [],
|
|
457
522
|
set: {},
|
|
@@ -460,7 +525,9 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
460
525
|
for (let [key, dirty] of Object.entries(this.$dirty)) {
|
|
461
526
|
if (dirty) {
|
|
462
527
|
if (key in this.$data) {
|
|
463
|
-
patch.set[key] =
|
|
528
|
+
patch.set[key] = entityConstructorsToClassNames(
|
|
529
|
+
entitiesToReferences(this.$data[key]),
|
|
530
|
+
);
|
|
464
531
|
} else {
|
|
465
532
|
patch.unset.push(key);
|
|
466
533
|
}
|
|
@@ -471,9 +538,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
471
538
|
}
|
|
472
539
|
|
|
473
540
|
public $hasTag(...tags: string[]) {
|
|
474
|
-
|
|
475
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
476
|
-
}
|
|
541
|
+
this.$check();
|
|
477
542
|
|
|
478
543
|
if (!tags.length) {
|
|
479
544
|
return false;
|
|
@@ -486,14 +551,16 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
486
551
|
return true;
|
|
487
552
|
}
|
|
488
553
|
|
|
554
|
+
public $isDirty(property: string) {
|
|
555
|
+
return property in this.$dirty ? this.$dirty[property] : null;
|
|
556
|
+
}
|
|
557
|
+
|
|
489
558
|
public $inArray(array: any[], strict = false) {
|
|
490
559
|
return this.$arraySearch(array, strict) !== -1;
|
|
491
560
|
}
|
|
492
561
|
|
|
493
562
|
public $is(object: any) {
|
|
494
|
-
|
|
495
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
496
|
-
}
|
|
563
|
+
this.$check();
|
|
497
564
|
|
|
498
565
|
if (!(object instanceof Entity)) {
|
|
499
566
|
return false;
|
|
@@ -514,31 +581,52 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
514
581
|
}
|
|
515
582
|
|
|
516
583
|
public async $patch() {
|
|
517
|
-
|
|
518
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
519
|
-
}
|
|
584
|
+
this.$check();
|
|
520
585
|
|
|
521
586
|
const mdate = this.mdate;
|
|
522
587
|
|
|
523
588
|
await this.$nymph.patchEntity(this);
|
|
524
|
-
|
|
589
|
+
if (mdate === this.mdate) {
|
|
590
|
+
throw new Error('Failed to patch entity.');
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Check if this is a sleeping reference and throw an error if so.
|
|
596
|
+
*/
|
|
597
|
+
protected $check() {
|
|
598
|
+
if (this.$isASleepingReference || this.$sleepingReference != null) {
|
|
599
|
+
throw new EntityIsSleepingReferenceError(
|
|
600
|
+
'This entity is in a sleeping reference state. You must use .$wake() to wake it.',
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Check if this is a sleeping reference.
|
|
607
|
+
*/
|
|
608
|
+
public $asleep() {
|
|
609
|
+
return this.$isASleepingReference || this.$sleepingReference != null;
|
|
525
610
|
}
|
|
526
611
|
|
|
527
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Wake from a sleeping reference.
|
|
614
|
+
*/
|
|
615
|
+
public $wake() {
|
|
528
616
|
if (!this.$isASleepingReference) {
|
|
529
|
-
this.$
|
|
617
|
+
this.$wakePromise = null;
|
|
530
618
|
return Promise.resolve(this);
|
|
531
619
|
}
|
|
532
620
|
if (this.$sleepingReference?.[1] == null) {
|
|
533
621
|
throw new InvalidStateError(
|
|
534
|
-
'Tried to
|
|
622
|
+
'Tried to wake a sleeping reference with no GUID.',
|
|
535
623
|
);
|
|
536
624
|
}
|
|
537
|
-
if (!this.$
|
|
538
|
-
this.$
|
|
625
|
+
if (!this.$wakePromise) {
|
|
626
|
+
this.$wakePromise = this.$nymph
|
|
539
627
|
.getEntityData(
|
|
540
628
|
{ class: this.constructor as EntityConstructor },
|
|
541
|
-
{ type: '&', guid: this.$sleepingReference[1] }
|
|
629
|
+
{ type: '&', guid: this.$sleepingReference[1] },
|
|
542
630
|
)
|
|
543
631
|
.then((data) => {
|
|
544
632
|
if (data == null) {
|
|
@@ -548,17 +636,17 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
548
636
|
return this.$init(data);
|
|
549
637
|
})
|
|
550
638
|
.finally(() => {
|
|
551
|
-
this.$
|
|
639
|
+
this.$wakePromise = null;
|
|
552
640
|
});
|
|
553
641
|
}
|
|
554
|
-
return this.$
|
|
642
|
+
return this.$wakePromise;
|
|
555
643
|
}
|
|
556
644
|
|
|
557
|
-
public $
|
|
645
|
+
public $wakeAll(level?: number) {
|
|
558
646
|
return new Promise((resolve, reject) => {
|
|
559
|
-
// Run this once this entity is
|
|
560
|
-
const
|
|
561
|
-
let newLevel;
|
|
647
|
+
// Run this once this entity is awake.
|
|
648
|
+
const wakeProps = () => {
|
|
649
|
+
let newLevel: number | undefined;
|
|
562
650
|
// If level is undefined, keep going forever, otherwise, stop once we've
|
|
563
651
|
// gone deep enough.
|
|
564
652
|
if (level !== undefined) {
|
|
@@ -568,26 +656,39 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
568
656
|
resolve(this);
|
|
569
657
|
return;
|
|
570
658
|
}
|
|
571
|
-
const promises = [];
|
|
572
|
-
// Go through data looking for entities to
|
|
573
|
-
|
|
574
|
-
if (
|
|
575
|
-
|
|
576
|
-
} else if (
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
659
|
+
const promises: Promise<any>[] = [];
|
|
660
|
+
// Go through data looking for entities to wake.
|
|
661
|
+
const walkData = (data: any) => {
|
|
662
|
+
if (data == null) {
|
|
663
|
+
return;
|
|
664
|
+
} else if (
|
|
665
|
+
typeof data === 'function' &&
|
|
666
|
+
data.prototype instanceof Entity
|
|
667
|
+
) {
|
|
668
|
+
// Ignore this, it is an entity class.
|
|
669
|
+
return;
|
|
670
|
+
} else if (data instanceof Entity) {
|
|
671
|
+
// Wake it up.
|
|
672
|
+
if (data.$isASleepingReference) {
|
|
673
|
+
promises.push(data.$wakeAll(newLevel));
|
|
674
|
+
}
|
|
675
|
+
} else if (Array.isArray(data)) {
|
|
676
|
+
// Recurse into lower arrays.
|
|
677
|
+
for (let i = 0; i < data.length; i++) {
|
|
678
|
+
walkData(data[i]);
|
|
679
|
+
}
|
|
680
|
+
} else if (data instanceof Object) {
|
|
681
|
+
// Recurse into objects.
|
|
682
|
+
for (let [key, value] of Object.entries(data)) {
|
|
683
|
+
walkData(value);
|
|
584
684
|
}
|
|
585
685
|
}
|
|
586
|
-
}
|
|
686
|
+
};
|
|
687
|
+
walkData(this.$data);
|
|
587
688
|
if (promises.length) {
|
|
588
689
|
Promise.all(promises).then(
|
|
589
690
|
() => resolve(this),
|
|
590
|
-
(errObj) => reject(errObj)
|
|
691
|
+
(errObj) => reject(errObj),
|
|
591
692
|
);
|
|
592
693
|
} else {
|
|
593
694
|
resolve(this);
|
|
@@ -595,9 +696,9 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
595
696
|
};
|
|
596
697
|
|
|
597
698
|
if (this.$isASleepingReference) {
|
|
598
|
-
this.$
|
|
699
|
+
this.$wake().then(wakeProps, (errObj) => reject(errObj));
|
|
599
700
|
} else {
|
|
600
|
-
|
|
701
|
+
wakeProps();
|
|
601
702
|
}
|
|
602
703
|
}) as Promise<Entity<T>>;
|
|
603
704
|
}
|
|
@@ -610,7 +711,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
610
711
|
|
|
611
712
|
public async $refresh() {
|
|
612
713
|
if (this.$isASleepingReference) {
|
|
613
|
-
await this.$
|
|
714
|
+
await this.$wake();
|
|
614
715
|
return true;
|
|
615
716
|
}
|
|
616
717
|
|
|
@@ -624,37 +725,36 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
624
725
|
{
|
|
625
726
|
type: '&',
|
|
626
727
|
guid: this.guid,
|
|
627
|
-
}
|
|
728
|
+
},
|
|
628
729
|
);
|
|
730
|
+
if (data == null) {
|
|
731
|
+
throw new Error("The entity's data could not be refreshed.");
|
|
732
|
+
}
|
|
629
733
|
this.$init(data);
|
|
630
|
-
return
|
|
734
|
+
return true;
|
|
631
735
|
}
|
|
632
736
|
|
|
633
737
|
public $removeTag(...tags: string[]) {
|
|
634
|
-
|
|
635
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
636
|
-
}
|
|
738
|
+
this.$check();
|
|
637
739
|
|
|
638
740
|
this.tags = difference(this.tags, tags);
|
|
639
741
|
}
|
|
640
742
|
|
|
641
743
|
public async $save() {
|
|
642
|
-
|
|
643
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
644
|
-
}
|
|
744
|
+
this.$check();
|
|
645
745
|
|
|
646
746
|
await this.$nymph.saveEntity(this);
|
|
647
|
-
|
|
747
|
+
if (!this.guid) {
|
|
748
|
+
throw new Error('Failed to save entity.');
|
|
749
|
+
}
|
|
648
750
|
}
|
|
649
751
|
|
|
650
752
|
public async $serverCall(
|
|
651
753
|
method: string,
|
|
652
754
|
params: Iterable<any>,
|
|
653
|
-
stateless = false
|
|
755
|
+
stateless = false,
|
|
654
756
|
) {
|
|
655
|
-
|
|
656
|
-
throw new EntityIsSleepingReferenceError(sleepErr);
|
|
657
|
-
}
|
|
757
|
+
this.$check();
|
|
658
758
|
// Turn the params into a real array, in case an arguments object was
|
|
659
759
|
// passed.
|
|
660
760
|
const paramArray = Array.prototype.slice.call(params);
|
|
@@ -662,7 +762,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
662
762
|
this,
|
|
663
763
|
method,
|
|
664
764
|
paramArray,
|
|
665
|
-
stateless
|
|
765
|
+
stateless,
|
|
666
766
|
);
|
|
667
767
|
if (!stateless && data.entity) {
|
|
668
768
|
this.$init(data.entity);
|