@nymphjs/nymph 1.0.0-beta.40 → 1.0.0-beta.41
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 +7 -0
- package/README.md +8 -10
- package/dist/Entity.d.ts +22 -3
- package/dist/Entity.js +152 -79
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +17 -2
- package/dist/Entity.test.js.map +1 -1
- package/dist/Nymph.types.d.ts +3 -3
- package/dist/driver/NymphDriver.d.ts +0 -22
- package/dist/driver/NymphDriver.js +0 -14
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/testArtifacts.js +6 -3
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/errors/InvalidStateError.d.ts +3 -0
- package/dist/errors/InvalidStateError.js +11 -0
- package/dist/errors/InvalidStateError.js.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/testArtifacts.d.ts +4 -4
- package/dist/testArtifacts.js +10 -12
- package/dist/testArtifacts.js.map +1 -1
- package/dist/testMocks.d.ts +6 -6
- package/dist/testMocks.js +2 -2
- package/dist/testMocks.js.map +1 -1
- package/package.json +4 -4
- package/src/Entity.test.ts +17 -2
- package/src/Entity.ts +212 -99
- package/src/Nymph.types.ts +6 -3
- package/src/driver/NymphDriver.ts +0 -81
- package/src/driver/testArtifacts.ts +6 -8
- package/src/errors/InvalidStateError.ts +6 -0
- package/src/errors/index.ts +2 -0
- package/src/testArtifacts.ts +10 -12
- package/src/testMocks.ts +11 -11
package/src/Entity.ts
CHANGED
|
@@ -11,7 +11,12 @@ import {
|
|
|
11
11
|
EntityReference,
|
|
12
12
|
SerializedEntityData,
|
|
13
13
|
} from './Entity.types';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
EntityConflictError,
|
|
16
|
+
EntityIsSleepingReferenceError,
|
|
17
|
+
InvalidParametersError,
|
|
18
|
+
InvalidStateError,
|
|
19
|
+
} from './errors';
|
|
15
20
|
import {
|
|
16
21
|
entitiesToReferences,
|
|
17
22
|
referencesToEntities,
|
|
@@ -136,6 +141,10 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
136
141
|
* The reference to use to wake.
|
|
137
142
|
*/
|
|
138
143
|
protected $sleepingReference: EntityReference | null = null;
|
|
144
|
+
/**
|
|
145
|
+
* A promise that resolved when the entity's data is wake.
|
|
146
|
+
*/
|
|
147
|
+
protected $wakePromise: Promise<Entity<T>> | null = null;
|
|
139
148
|
/**
|
|
140
149
|
* Properties that will not be serialized into JSON with toJSON(). This
|
|
141
150
|
* can be considered a denylist, because these properties will not be set
|
|
@@ -222,20 +231,19 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
222
231
|
private $originalAcValues: ACProperties | null = null;
|
|
223
232
|
|
|
224
233
|
/**
|
|
225
|
-
*
|
|
226
|
-
* @param guid The ID of the entity to load, undefined for a new entity.
|
|
234
|
+
* Initialize an entity.
|
|
227
235
|
*/
|
|
228
|
-
public constructor(
|
|
236
|
+
public constructor() {
|
|
229
237
|
this.$nymph = (this.constructor as EntityConstructor).nymph;
|
|
230
238
|
this.$dataHandler = {
|
|
231
239
|
has: (data: EntityData, name: string) => {
|
|
232
|
-
this.$
|
|
240
|
+
this.$check();
|
|
233
241
|
|
|
234
242
|
return name in data || name in this.$sdata;
|
|
235
243
|
},
|
|
236
244
|
|
|
237
245
|
get: (data: EntityData, name: string) => {
|
|
238
|
-
this.$
|
|
246
|
+
this.$check();
|
|
239
247
|
|
|
240
248
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
241
249
|
data[name] = referencesToEntities(
|
|
@@ -252,7 +260,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
252
260
|
},
|
|
253
261
|
|
|
254
262
|
set: (data: EntityData, name: string, value: any) => {
|
|
255
|
-
this.$
|
|
263
|
+
this.$check();
|
|
256
264
|
|
|
257
265
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
258
266
|
delete this.$sdata[name];
|
|
@@ -262,7 +270,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
262
270
|
},
|
|
263
271
|
|
|
264
272
|
deleteProperty: (data: EntityData, name: string) => {
|
|
265
|
-
this.$
|
|
273
|
+
this.$check();
|
|
266
274
|
|
|
267
275
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
268
276
|
return delete this.$sdata[name];
|
|
@@ -278,7 +286,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
278
286
|
name: string,
|
|
279
287
|
descriptor: PropertyDescriptor
|
|
280
288
|
) => {
|
|
281
|
-
this.$
|
|
289
|
+
this.$check();
|
|
282
290
|
|
|
283
291
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
284
292
|
delete this.$sdata[name];
|
|
@@ -288,7 +296,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
288
296
|
},
|
|
289
297
|
|
|
290
298
|
getOwnPropertyDescriptor: (data: EntityData, name: string) => {
|
|
291
|
-
this.$
|
|
299
|
+
this.$check();
|
|
292
300
|
|
|
293
301
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
294
302
|
data[name] = referencesToEntities(
|
|
@@ -302,7 +310,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
302
310
|
},
|
|
303
311
|
|
|
304
312
|
ownKeys: (data: EntityData) => {
|
|
305
|
-
this.$
|
|
313
|
+
this.$check();
|
|
306
314
|
|
|
307
315
|
return Object.getOwnPropertyNames(data).concat(
|
|
308
316
|
Object.getOwnPropertyNames(this.$sdata)
|
|
@@ -314,24 +322,6 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
314
322
|
|
|
315
323
|
this.$data = new Proxy(this.$dataStore, this.$dataHandler);
|
|
316
324
|
|
|
317
|
-
if (guid != null) {
|
|
318
|
-
const entity = this.$nymph.driver.getEntitySync(
|
|
319
|
-
{
|
|
320
|
-
class: this.$nymph.getEntityClass(
|
|
321
|
-
this.constructor as EntityConstructor
|
|
322
|
-
),
|
|
323
|
-
},
|
|
324
|
-
{ type: '&', guid }
|
|
325
|
-
);
|
|
326
|
-
if (entity) {
|
|
327
|
-
this.guid = entity.guid;
|
|
328
|
-
this.tags = entity.tags;
|
|
329
|
-
this.cdate = entity.cdate;
|
|
330
|
-
this.mdate = entity.mdate;
|
|
331
|
-
this.$putData(entity.$getData(), entity.$getSData());
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
325
|
return new Proxy(this, {
|
|
336
326
|
has: (entity: Entity, name: string) => {
|
|
337
327
|
if (
|
|
@@ -342,7 +332,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
342
332
|
return name in entity;
|
|
343
333
|
}
|
|
344
334
|
|
|
345
|
-
this.$
|
|
335
|
+
this.$check();
|
|
346
336
|
return name in entity.$data;
|
|
347
337
|
},
|
|
348
338
|
|
|
@@ -353,12 +343,12 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
353
343
|
name.substring(0, 1) === '$'
|
|
354
344
|
) {
|
|
355
345
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
356
|
-
this.$
|
|
346
|
+
this.$check();
|
|
357
347
|
}
|
|
358
348
|
return (entity as any)[name];
|
|
359
349
|
}
|
|
360
350
|
|
|
361
|
-
this.$
|
|
351
|
+
this.$check();
|
|
362
352
|
if (name in entity.$data) {
|
|
363
353
|
return entity.$data[name];
|
|
364
354
|
}
|
|
@@ -372,11 +362,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
372
362
|
name.substring(0, 1) === '$'
|
|
373
363
|
) {
|
|
374
364
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
375
|
-
this.$
|
|
365
|
+
this.$check();
|
|
376
366
|
}
|
|
377
367
|
(entity as any)[name] = value;
|
|
378
368
|
} else {
|
|
379
|
-
this.$
|
|
369
|
+
this.$check();
|
|
380
370
|
(entity.$data as any)[name] = value;
|
|
381
371
|
}
|
|
382
372
|
return true;
|
|
@@ -386,7 +376,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
386
376
|
if (name in entity) {
|
|
387
377
|
return delete (entity as any)[name];
|
|
388
378
|
} else if (name in entity.$data) {
|
|
389
|
-
this.$
|
|
379
|
+
this.$check();
|
|
390
380
|
return delete entity.$data[name];
|
|
391
381
|
}
|
|
392
382
|
return true;
|
|
@@ -407,11 +397,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
407
397
|
name.substring(0, 1) === '$'
|
|
408
398
|
) {
|
|
409
399
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
410
|
-
this.$
|
|
400
|
+
this.$check();
|
|
411
401
|
}
|
|
412
402
|
Object.defineProperty(entity, name, descriptor);
|
|
413
403
|
} else {
|
|
414
|
-
this.$
|
|
404
|
+
this.$check();
|
|
415
405
|
Object.defineProperty(entity.$data, name, descriptor);
|
|
416
406
|
}
|
|
417
407
|
return true;
|
|
@@ -424,17 +414,17 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
424
414
|
name.substring(0, 1) === '$'
|
|
425
415
|
) {
|
|
426
416
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
427
|
-
this.$
|
|
417
|
+
this.$check();
|
|
428
418
|
}
|
|
429
419
|
return Object.getOwnPropertyDescriptor(entity, name);
|
|
430
420
|
} else {
|
|
431
|
-
this.$
|
|
421
|
+
this.$check();
|
|
432
422
|
return Object.getOwnPropertyDescriptor(entity.$data, name);
|
|
433
423
|
}
|
|
434
424
|
},
|
|
435
425
|
|
|
436
426
|
ownKeys: (entity: Entity) => {
|
|
437
|
-
this.$
|
|
427
|
+
this.$check();
|
|
438
428
|
return Object.getOwnPropertyNames(entity).concat(
|
|
439
429
|
Object.getOwnPropertyNames(entity.$data)
|
|
440
430
|
);
|
|
@@ -458,8 +448,8 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
458
448
|
return entity;
|
|
459
449
|
}
|
|
460
450
|
|
|
461
|
-
public static factorySync(
|
|
462
|
-
return new this(
|
|
451
|
+
public static factorySync() {
|
|
452
|
+
return new this();
|
|
463
453
|
}
|
|
464
454
|
|
|
465
455
|
public static factoryReference(reference: EntityReference) {
|
|
@@ -490,7 +480,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
490
480
|
}
|
|
491
481
|
|
|
492
482
|
public $addTag(...tags: string[]) {
|
|
493
|
-
this.$
|
|
483
|
+
this.$check();
|
|
494
484
|
|
|
495
485
|
if (tags.length < 1) {
|
|
496
486
|
return;
|
|
@@ -499,7 +489,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
499
489
|
}
|
|
500
490
|
|
|
501
491
|
public $arraySearch(array: any[], strict = false) {
|
|
502
|
-
this.$
|
|
492
|
+
this.$check();
|
|
503
493
|
|
|
504
494
|
if (!Array.isArray(array)) {
|
|
505
495
|
return -1;
|
|
@@ -514,7 +504,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
514
504
|
}
|
|
515
505
|
|
|
516
506
|
public $clearCache() {
|
|
517
|
-
this.$
|
|
507
|
+
this.$check();
|
|
518
508
|
|
|
519
509
|
this.$putData(this.$getData(), this.$getSData());
|
|
520
510
|
}
|
|
@@ -524,13 +514,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
524
514
|
}
|
|
525
515
|
|
|
526
516
|
public async $delete(): Promise<boolean> {
|
|
527
|
-
this.$
|
|
517
|
+
this.$check();
|
|
528
518
|
|
|
529
519
|
return await this.$nymph.deleteEntity(this);
|
|
530
520
|
}
|
|
531
521
|
|
|
532
522
|
public $equals(object: any) {
|
|
533
|
-
this.$
|
|
523
|
+
this.$check();
|
|
534
524
|
|
|
535
525
|
if (!(object instanceof Entity)) {
|
|
536
526
|
return false;
|
|
@@ -557,7 +547,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
557
547
|
}
|
|
558
548
|
|
|
559
549
|
public $getData(includeSData = false) {
|
|
560
|
-
this.$
|
|
550
|
+
this.$check();
|
|
561
551
|
|
|
562
552
|
if (includeSData) {
|
|
563
553
|
// Access all the serialized properties to initialize them.
|
|
@@ -569,30 +559,56 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
569
559
|
}
|
|
570
560
|
|
|
571
561
|
public $getSData() {
|
|
572
|
-
this.$
|
|
562
|
+
this.$check();
|
|
573
563
|
|
|
574
564
|
return this.$sdata;
|
|
575
565
|
}
|
|
576
566
|
|
|
577
567
|
public $getOriginalAcValues() {
|
|
578
|
-
this.$
|
|
579
|
-
|
|
580
|
-
return (
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
568
|
+
this.$check();
|
|
569
|
+
|
|
570
|
+
return this.$originalAcValues ?? this.$getCurrentAcValues();
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
public $getCurrentAcValues() {
|
|
574
|
+
this.$check();
|
|
575
|
+
|
|
576
|
+
return {
|
|
577
|
+
user: this.$getAcUid(),
|
|
578
|
+
group: this.$getAcGid(),
|
|
579
|
+
acUser: this.$data.acUser,
|
|
580
|
+
acGroup: this.$data.acGroup,
|
|
581
|
+
acOther: this.$data.acOther,
|
|
582
|
+
acRead: this.$getAcReadIds(),
|
|
583
|
+
acWrite: this.$getAcWriteIds(),
|
|
584
|
+
acFull: this.$getAcFullIds(),
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
public $getAcUid() {
|
|
589
|
+
return this.$data.user?.guid as string | null;
|
|
590
|
+
}
|
|
591
|
+
public $getAcGid() {
|
|
592
|
+
return this.$data.group?.guid as string | null;
|
|
593
|
+
}
|
|
594
|
+
public $getAcReadIds() {
|
|
595
|
+
return this.$data.acRead?.map((entity: EntityInterface) => entity.guid) as
|
|
596
|
+
| string[]
|
|
597
|
+
| null;
|
|
598
|
+
}
|
|
599
|
+
public $getAcWriteIds() {
|
|
600
|
+
return this.$data.acWrite?.map((entity: EntityInterface) => entity.guid) as
|
|
601
|
+
| string[]
|
|
602
|
+
| null;
|
|
603
|
+
}
|
|
604
|
+
public $getAcFullIds() {
|
|
605
|
+
return this.$data.acFull?.map((entity: EntityInterface) => entity.guid) as
|
|
606
|
+
| string[]
|
|
607
|
+
| null;
|
|
592
608
|
}
|
|
593
609
|
|
|
594
610
|
public $getValidatable() {
|
|
595
|
-
this.$
|
|
611
|
+
this.$check();
|
|
596
612
|
|
|
597
613
|
// Access all the serialized properties to initialize them.
|
|
598
614
|
for (const key in this.$sdata) {
|
|
@@ -608,13 +624,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
608
624
|
}
|
|
609
625
|
|
|
610
626
|
public $getTags() {
|
|
611
|
-
this.$
|
|
627
|
+
this.$check();
|
|
612
628
|
|
|
613
629
|
return this.tags;
|
|
614
630
|
}
|
|
615
631
|
|
|
616
632
|
public $hasTag(...tags: string[]) {
|
|
617
|
-
this.$
|
|
633
|
+
this.$check();
|
|
618
634
|
|
|
619
635
|
if (!tags.length) {
|
|
620
636
|
return false;
|
|
@@ -640,7 +656,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
640
656
|
return this.guid === object.guid;
|
|
641
657
|
}
|
|
642
658
|
|
|
643
|
-
this.$
|
|
659
|
+
this.$check();
|
|
644
660
|
if (typeof object.$getData !== 'function') {
|
|
645
661
|
return false;
|
|
646
662
|
} else {
|
|
@@ -656,8 +672,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
656
672
|
}
|
|
657
673
|
|
|
658
674
|
public $jsonAcceptData(input: EntityJson, allowConflict = false) {
|
|
659
|
-
|
|
660
|
-
this.$referenceWake();
|
|
675
|
+
this.$check();
|
|
661
676
|
|
|
662
677
|
if (this.guid != input.guid) {
|
|
663
678
|
throw new EntityConflictError(
|
|
@@ -709,7 +724,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
709
724
|
if (
|
|
710
725
|
((this.constructor as typeof Entity).class !== 'User' &&
|
|
711
726
|
(this.constructor as typeof Entity).class !== 'Group') ||
|
|
712
|
-
!this.$nymph.tilmeld.
|
|
727
|
+
!(this.$nymph.tilmeld as any).currentUser ||
|
|
728
|
+
(!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
729
|
+
'tilmeld/admin'
|
|
730
|
+
) &&
|
|
731
|
+
!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
732
|
+
'system/admin'
|
|
733
|
+
))
|
|
713
734
|
) {
|
|
714
735
|
protectedProps.push('user');
|
|
715
736
|
protectedProps.push('group');
|
|
@@ -746,7 +767,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
746
767
|
}
|
|
747
768
|
|
|
748
769
|
public $jsonAcceptPatch(patch: EntityPatch, allowConflict = false) {
|
|
749
|
-
this.$
|
|
770
|
+
this.$check();
|
|
750
771
|
|
|
751
772
|
if (this.guid != patch.guid) {
|
|
752
773
|
throw new EntityConflictError(
|
|
@@ -773,7 +794,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
773
794
|
if (
|
|
774
795
|
((this.constructor as typeof Entity).class !== 'User' &&
|
|
775
796
|
(this.constructor as typeof Entity).class !== 'Group') ||
|
|
776
|
-
!this.$nymph.tilmeld.
|
|
797
|
+
!(this.$nymph.tilmeld as any).currentUser ||
|
|
798
|
+
(!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
799
|
+
'tilmeld/admin'
|
|
800
|
+
) &&
|
|
801
|
+
!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
802
|
+
'system/admin'
|
|
803
|
+
))
|
|
777
804
|
) {
|
|
778
805
|
protectedProps.push('user');
|
|
779
806
|
protectedProps.push('group');
|
|
@@ -832,7 +859,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
832
859
|
}
|
|
833
860
|
|
|
834
861
|
public $putData(data: EntityData, sdata?: SerializedEntityData) {
|
|
835
|
-
this.$
|
|
862
|
+
this.$check();
|
|
836
863
|
|
|
837
864
|
const mySdata = sdata ?? this.$getSData();
|
|
838
865
|
for (const name in data) {
|
|
@@ -851,7 +878,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
851
878
|
this.$sdata = mySdata;
|
|
852
879
|
// Set original AC values if not set..
|
|
853
880
|
if (this.$originalAcValues == null) {
|
|
854
|
-
this.$originalAcValues = this.$
|
|
881
|
+
this.$originalAcValues = this.$getCurrentAcValues();
|
|
855
882
|
}
|
|
856
883
|
}
|
|
857
884
|
|
|
@@ -883,38 +910,124 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
883
910
|
this.$sleepingReference = reference;
|
|
884
911
|
}
|
|
885
912
|
|
|
913
|
+
/**
|
|
914
|
+
* Check if this is a sleeping reference and throw an error if so.
|
|
915
|
+
*/
|
|
916
|
+
protected $check() {
|
|
917
|
+
if (this.$isASleepingReference || this.$sleepingReference != null) {
|
|
918
|
+
throw new EntityIsSleepingReferenceError(
|
|
919
|
+
'This entity is in a sleeping reference state. You must use .$wake() to wake it.'
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Check if this is a sleeping reference.
|
|
926
|
+
*/
|
|
927
|
+
public $asleep() {
|
|
928
|
+
return this.$isASleepingReference || this.$sleepingReference != null;
|
|
929
|
+
}
|
|
930
|
+
|
|
886
931
|
/**
|
|
887
932
|
* Wake from a sleeping reference.
|
|
888
|
-
*
|
|
889
|
-
* @returns True on success, false on failure.
|
|
890
933
|
*/
|
|
891
|
-
|
|
934
|
+
public $wake() {
|
|
892
935
|
if (!this.$isASleepingReference || this.$sleepingReference == null) {
|
|
893
|
-
|
|
936
|
+
this.$wakePromise = null;
|
|
937
|
+
return Promise.resolve(this);
|
|
894
938
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
skipAc: this.$skipAc,
|
|
900
|
-
},
|
|
901
|
-
{ type: '&', guid: this.$sleepingReference[1] }
|
|
902
|
-
);
|
|
903
|
-
if (entity == null) {
|
|
904
|
-
return false;
|
|
939
|
+
if (this.$sleepingReference?.[1] == null) {
|
|
940
|
+
throw new InvalidStateError(
|
|
941
|
+
'Tried to wake a sleeping reference with no GUID.'
|
|
942
|
+
);
|
|
905
943
|
}
|
|
906
|
-
this.$
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
944
|
+
if (!this.$wakePromise) {
|
|
945
|
+
const EntityClass = this.$nymph.getEntityClass(
|
|
946
|
+
this.$sleepingReference[2]
|
|
947
|
+
);
|
|
948
|
+
this.$wakePromise = this.$nymph
|
|
949
|
+
.getEntity(
|
|
950
|
+
{
|
|
951
|
+
class: EntityClass,
|
|
952
|
+
skipAc: this.$skipAc,
|
|
953
|
+
},
|
|
954
|
+
{ type: '&', guid: this.$sleepingReference[1] }
|
|
955
|
+
)
|
|
956
|
+
.then((entity) => {
|
|
957
|
+
if (entity == null || entity.guid == null) {
|
|
958
|
+
return Promise.reject(
|
|
959
|
+
new InvalidStateError(
|
|
960
|
+
'The sleeping reference could not be retrieved.'
|
|
961
|
+
)
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
this.$isASleepingReference = false;
|
|
965
|
+
this.$sleepingReference = null;
|
|
966
|
+
this.guid = entity.guid;
|
|
967
|
+
this.tags = entity.tags;
|
|
968
|
+
this.cdate = entity.cdate;
|
|
969
|
+
this.mdate = entity.mdate;
|
|
970
|
+
this.$putData(entity.$getData(), entity.$getSData());
|
|
971
|
+
|
|
972
|
+
return this;
|
|
973
|
+
})
|
|
974
|
+
.finally(() => {
|
|
975
|
+
this.$wakePromise = null;
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
return this.$wakePromise;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
public $wakeAll(level?: number) {
|
|
982
|
+
return new Promise((resolve, reject) => {
|
|
983
|
+
// Run this once this entity is wake.
|
|
984
|
+
const wakeProps = () => {
|
|
985
|
+
let newLevel;
|
|
986
|
+
// If level is undefined, keep going forever, otherwise, stop once we've
|
|
987
|
+
// gone deep enough.
|
|
988
|
+
if (level !== undefined) {
|
|
989
|
+
newLevel = level - 1;
|
|
990
|
+
}
|
|
991
|
+
if (newLevel !== undefined && newLevel < 0) {
|
|
992
|
+
resolve(this);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const promises = [];
|
|
996
|
+
// Go through data looking for entities to wake.
|
|
997
|
+
for (let [key, value] of Object.entries(this.$data)) {
|
|
998
|
+
if (value instanceof Entity && value.$isASleepingReference) {
|
|
999
|
+
promises.push(value.$wakeAll(newLevel));
|
|
1000
|
+
} else if (Array.isArray(value)) {
|
|
1001
|
+
for (let i = 0; i < value.length; i++) {
|
|
1002
|
+
if (
|
|
1003
|
+
value[i] instanceof Entity &&
|
|
1004
|
+
value[i].$isASleepingReference
|
|
1005
|
+
) {
|
|
1006
|
+
promises.push(value[i].$wakeAll(newLevel));
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
if (promises.length) {
|
|
1012
|
+
Promise.all(promises).then(
|
|
1013
|
+
() => resolve(this),
|
|
1014
|
+
(errObj) => reject(errObj)
|
|
1015
|
+
);
|
|
1016
|
+
} else {
|
|
1017
|
+
resolve(this);
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
if (this.$isASleepingReference) {
|
|
1022
|
+
this.$wake().then(wakeProps, (errObj) => reject(errObj));
|
|
1023
|
+
} else {
|
|
1024
|
+
wakeProps();
|
|
1025
|
+
}
|
|
1026
|
+
}) as Promise<Entity<T>>;
|
|
914
1027
|
}
|
|
915
1028
|
|
|
916
1029
|
public async $refresh() {
|
|
917
|
-
this.$
|
|
1030
|
+
await this.$wake();
|
|
918
1031
|
|
|
919
1032
|
if (this.guid == null) {
|
|
920
1033
|
return false;
|
|
@@ -940,13 +1053,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
940
1053
|
}
|
|
941
1054
|
|
|
942
1055
|
public $removeTag(...tags: string[]) {
|
|
943
|
-
this.$
|
|
1056
|
+
this.$check();
|
|
944
1057
|
|
|
945
1058
|
this.tags = difference(this.tags, tags);
|
|
946
1059
|
}
|
|
947
1060
|
|
|
948
1061
|
public async $save(): Promise<boolean> {
|
|
949
|
-
this.$
|
|
1062
|
+
await this.$wake();
|
|
950
1063
|
|
|
951
1064
|
return await this.$nymph.saveEntity(this);
|
|
952
1065
|
}
|
package/src/Nymph.types.ts
CHANGED
|
@@ -376,10 +376,13 @@ export interface TilmeldInterface {
|
|
|
376
376
|
response: any;
|
|
377
377
|
init(nymph: Nymph): void;
|
|
378
378
|
clone(): TilmeldInterface;
|
|
379
|
-
gatekeeper(ability?: string): boolean
|
|
380
|
-
authenticate():
|
|
379
|
+
gatekeeper(ability?: string): Promise<boolean>;
|
|
380
|
+
authenticate(): Promise<boolean>;
|
|
381
381
|
clearSession(): void;
|
|
382
382
|
extractToken(token: string): Promise<any>;
|
|
383
383
|
fillSession(user: any): void;
|
|
384
|
-
checkClientUIDPermissions(
|
|
384
|
+
checkClientUIDPermissions(
|
|
385
|
+
name: string,
|
|
386
|
+
type?: TilmeldAccessLevels
|
|
387
|
+
): Promise<boolean>;
|
|
385
388
|
}
|
|
@@ -102,30 +102,6 @@ export default abstract class NymphDriver {
|
|
|
102
102
|
options?: Options<T>,
|
|
103
103
|
...selectors: Selector[]
|
|
104
104
|
): Promise<ReturnType<T['factorySync']>[] | string[] | number>;
|
|
105
|
-
protected abstract getEntitiesSync<
|
|
106
|
-
T extends EntityConstructor = EntityConstructor
|
|
107
|
-
>(
|
|
108
|
-
options: Options<T> & { return: 'count' },
|
|
109
|
-
...selectors: Selector[]
|
|
110
|
-
): number;
|
|
111
|
-
protected abstract getEntitiesSync<
|
|
112
|
-
T extends EntityConstructor = EntityConstructor
|
|
113
|
-
>(
|
|
114
|
-
options: Options<T> & { return: 'guid' },
|
|
115
|
-
...selectors: Selector[]
|
|
116
|
-
): string[];
|
|
117
|
-
protected abstract getEntitiesSync<
|
|
118
|
-
T extends EntityConstructor = EntityConstructor
|
|
119
|
-
>(
|
|
120
|
-
options?: Options<T>,
|
|
121
|
-
...selectors: Selector[]
|
|
122
|
-
): ReturnType<T['factorySync']>[];
|
|
123
|
-
protected abstract getEntitiesSync<
|
|
124
|
-
T extends EntityConstructor = EntityConstructor
|
|
125
|
-
>(
|
|
126
|
-
options?: Options<T>,
|
|
127
|
-
...selectors: Selector[]
|
|
128
|
-
): ReturnType<T['factorySync']>[] | string[] | number;
|
|
129
105
|
abstract getUID(name: string): Promise<number | null>;
|
|
130
106
|
abstract import(filename: string): Promise<boolean>;
|
|
131
107
|
abstract newUID(name: string): Promise<number | null>;
|
|
@@ -718,63 +694,6 @@ export default abstract class NymphDriver {
|
|
|
718
694
|
return queryParts;
|
|
719
695
|
}
|
|
720
696
|
|
|
721
|
-
/**
|
|
722
|
-
* Get the first entity to match all options/selectors, synchronously.
|
|
723
|
-
*
|
|
724
|
-
* This should really only be used internally by the Entity class. It's a bad
|
|
725
|
-
* idea to get entities synchronously. The Entity class uses this to load
|
|
726
|
-
* sleeping references.
|
|
727
|
-
*
|
|
728
|
-
* @param options The options.
|
|
729
|
-
* @param selectors Unlimited optional selectors to search for, or a single GUID. If none are given, all entities are searched for the given options.
|
|
730
|
-
* @returns An entity, or null on failure or nothing found.
|
|
731
|
-
*/
|
|
732
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
733
|
-
options: Options<T> & { return: 'count' },
|
|
734
|
-
...selectors: Selector[]
|
|
735
|
-
): number;
|
|
736
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
737
|
-
options: Options<T> & { return: 'guid' },
|
|
738
|
-
...selectors: Selector[]
|
|
739
|
-
): string | null;
|
|
740
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
741
|
-
options: Options<T>,
|
|
742
|
-
...selectors: Selector[]
|
|
743
|
-
): ReturnType<T['factorySync']> | null;
|
|
744
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
745
|
-
options: Options<T> & { return: 'count' },
|
|
746
|
-
guid: string
|
|
747
|
-
): number;
|
|
748
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
749
|
-
options: Options<T> & { return: 'guid' },
|
|
750
|
-
guid: string
|
|
751
|
-
): string | null;
|
|
752
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
753
|
-
options: Options<T>,
|
|
754
|
-
guid: string
|
|
755
|
-
): ReturnType<T['factorySync']> | null;
|
|
756
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
757
|
-
options: Options<T> = {},
|
|
758
|
-
...selectors: Selector[] | string[]
|
|
759
|
-
): ReturnType<T['factorySync']> | string | number | null {
|
|
760
|
-
// Set up options and selectors.
|
|
761
|
-
if (typeof selectors[0] === 'string') {
|
|
762
|
-
selectors = [{ type: '&', guid: selectors[0] }];
|
|
763
|
-
}
|
|
764
|
-
options.limit = 1;
|
|
765
|
-
const entities = this.getEntitiesSync(
|
|
766
|
-
options,
|
|
767
|
-
...(selectors as Selector[])
|
|
768
|
-
);
|
|
769
|
-
if (options.return === 'count') {
|
|
770
|
-
return entities as unknown as number;
|
|
771
|
-
}
|
|
772
|
-
if (!entities || !entities.length) {
|
|
773
|
-
return null;
|
|
774
|
-
}
|
|
775
|
-
return entities[0];
|
|
776
|
-
}
|
|
777
|
-
|
|
778
697
|
protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
779
698
|
options: Options<T> & { return: 'count' },
|
|
780
699
|
selectors: Selector[],
|