@nymphjs/nymph 1.0.0-beta.10 → 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 +483 -0
- package/README.md +10 -20
- package/dist/Entity.d.ts +293 -10
- package/dist/Entity.js +563 -148
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +52 -13
- package/dist/Entity.test.js.map +1 -1
- package/dist/Entity.types.d.ts +256 -23
- package/dist/Entity.types.js +1 -2
- package/dist/Nymph.d.ts +496 -12
- package/dist/Nymph.js +752 -179
- package/dist/Nymph.js.map +1 -1
- package/dist/Nymph.types.d.ts +77 -8
- package/dist/Nymph.types.js +3 -5
- package/dist/Nymph.types.js.map +1 -1
- package/dist/conf/d.d.ts +43 -0
- package/dist/conf/d.js +1 -2
- package/dist/conf/defaults.d.ts +1 -1
- package/dist/conf/defaults.js +26 -3
- package/dist/conf/defaults.js.map +1 -1
- package/dist/conf/index.d.ts +2 -2
- package/dist/conf/index.js +2 -8
- package/dist/conf/index.js.map +1 -1
- package/dist/driver/NymphDriver.d.ts +174 -40
- package/dist/driver/NymphDriver.js +469 -239
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/index.d.ts +2 -2
- package/dist/driver/index.js +3 -23
- package/dist/driver/index.js.map +1 -1
- package/dist/driver/testArtifacts.d.ts +2 -2
- package/dist/driver/testArtifacts.js +814 -92
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/errors/ClassNotAvailableError.js +1 -5
- package/dist/errors/ClassNotAvailableError.js.map +1 -1
- package/dist/errors/EntityConflictError.js +1 -5
- package/dist/errors/EntityConflictError.js.map +1 -1
- package/dist/errors/EntityInvalidDataError.d.ts +6 -0
- package/dist/errors/EntityInvalidDataError.js +8 -6
- package/dist/errors/EntityInvalidDataError.js.map +1 -1
- package/dist/errors/EntityIsSleepingReferenceError.js +1 -5
- package/dist/errors/EntityIsSleepingReferenceError.js.map +1 -1
- package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
- package/dist/errors/EntityUniqueConstraintError.js +7 -0
- package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
- package/dist/errors/InvalidParametersError.js +1 -5
- package/dist/errors/InvalidParametersError.js.map +1 -1
- package/dist/errors/InvalidStateError.d.ts +3 -0
- package/dist/errors/InvalidStateError.js +7 -0
- package/dist/errors/InvalidStateError.js.map +1 -0
- package/dist/errors/NotConfiguredError.js +1 -5
- package/dist/errors/NotConfiguredError.js.map +1 -1
- package/dist/errors/QueryFailedError.js +2 -5
- package/dist/errors/QueryFailedError.js.map +1 -1
- package/dist/errors/UnableToConnectError.js +1 -5
- package/dist/errors/UnableToConnectError.js.map +1 -1
- package/dist/errors/index.d.ts +10 -8
- package/dist/errors/index.js +10 -24
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +14 -34
- package/dist/index.js.map +1 -1
- package/dist/nymphJoiProps.js +10 -15
- package/dist/nymphJoiProps.js.map +1 -1
- package/dist/testArtifacts.d.ts +19 -6
- package/dist/testArtifacts.js +32 -37
- package/dist/testArtifacts.js.map +1 -1
- package/dist/testMocks.d.ts +27 -12
- package/dist/testMocks.js +40 -29
- package/dist/testMocks.js.map +1 -1
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +40 -29
- package/dist/utils.js.map +1 -1
- package/jest.config.js +11 -2
- package/package.json +23 -19
- package/src/Entity.test.ts +50 -7
- package/src/Entity.ts +483 -147
- package/src/Entity.types.ts +72 -74
- package/src/Nymph.ts +868 -322
- package/src/Nymph.types.ts +146 -27
- package/src/conf/d.ts +25 -0
- package/src/conf/defaults.ts +34 -1
- package/src/conf/index.ts +2 -2
- package/src/driver/NymphDriver.ts +562 -414
- package/src/driver/index.ts +2 -2
- package/src/driver/testArtifacts.ts +954 -185
- package/src/errors/EntityUniqueConstraintError.ts +6 -0
- package/src/errors/InvalidStateError.ts +6 -0
- package/src/errors/index.ts +12 -8
- package/src/index.ts +11 -11
- package/src/nymphJoiProps.ts +2 -2
- package/src/testArtifacts.ts +20 -20
- package/src/testMocks.ts +76 -35
- package/src/type/locutus.d.ts +3 -0
- package/src/utils.ts +39 -18
- package/tsconfig.json +5 -3
- package/typedoc.json +4 -0
package/src/Entity.ts
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
|
-
import { difference, intersection, isEqual } from 'lodash';
|
|
1
|
+
import { difference, intersection, isEqual } from 'lodash-es';
|
|
2
|
+
import { guid } from '@nymphjs/guid';
|
|
2
3
|
|
|
3
|
-
import type Nymph from './Nymph';
|
|
4
|
-
import {
|
|
4
|
+
import type Nymph from './Nymph.js';
|
|
5
|
+
import type { Options } from './Nymph.types.js';
|
|
6
|
+
import type {
|
|
5
7
|
ACProperties,
|
|
6
8
|
EntityConstructor,
|
|
7
9
|
EntityData,
|
|
8
10
|
EntityInterface,
|
|
9
11
|
EntityJson,
|
|
12
|
+
EntityObject,
|
|
10
13
|
EntityPatch,
|
|
11
14
|
EntityReference,
|
|
12
15
|
SerializedEntityData,
|
|
13
|
-
} from './Entity.types';
|
|
14
|
-
import {
|
|
16
|
+
} from './Entity.types.js';
|
|
17
|
+
import {
|
|
18
|
+
EntityConflictError,
|
|
19
|
+
EntityIsSleepingReferenceError,
|
|
20
|
+
InvalidParametersError,
|
|
21
|
+
InvalidStateError,
|
|
22
|
+
} from './errors/index.js';
|
|
15
23
|
import {
|
|
16
24
|
entitiesToReferences,
|
|
17
25
|
referencesToEntities,
|
|
18
26
|
uniqueStrings,
|
|
19
|
-
} from './utils';
|
|
27
|
+
} from './utils.js';
|
|
28
|
+
|
|
29
|
+
export type EntityDataType<T> =
|
|
30
|
+
T extends Entity<infer DataType> ? DataType : never;
|
|
31
|
+
|
|
32
|
+
export type EntityInstanceType<T extends EntityConstructor> =
|
|
33
|
+
T extends new () => infer E ? E & EntityDataType<E> : never;
|
|
34
|
+
|
|
35
|
+
export type EntityObjectType<T extends EntityConstructor> =
|
|
36
|
+
T extends new () => infer E ? EntityObject & EntityDataType<E> : never;
|
|
20
37
|
|
|
21
38
|
/**
|
|
22
39
|
* Database abstraction object.
|
|
@@ -136,6 +153,10 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
136
153
|
* The reference to use to wake.
|
|
137
154
|
*/
|
|
138
155
|
protected $sleepingReference: EntityReference | null = null;
|
|
156
|
+
/**
|
|
157
|
+
* A promise that resolved when the entity's data is wake.
|
|
158
|
+
*/
|
|
159
|
+
protected $wakePromise: Promise<Entity<T>> | null = null;
|
|
139
160
|
/**
|
|
140
161
|
* Properties that will not be serialized into JSON with toJSON(). This
|
|
141
162
|
* can be considered a denylist, because these properties will not be set
|
|
@@ -145,6 +166,18 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
145
166
|
* also listed in searchRestrictedData.
|
|
146
167
|
*/
|
|
147
168
|
protected $privateData: string[] = [];
|
|
169
|
+
/**
|
|
170
|
+
* Whether this entity should publish changes to PubSub servers.
|
|
171
|
+
*/
|
|
172
|
+
public static pubSubEnabled = true;
|
|
173
|
+
/**
|
|
174
|
+
* Whether this entity should be accessible on the frontend through the REST
|
|
175
|
+
* server.
|
|
176
|
+
*
|
|
177
|
+
* If this is false, any request from the client that attempts to use this
|
|
178
|
+
* entity will fail.
|
|
179
|
+
*/
|
|
180
|
+
public static restEnabled = true;
|
|
148
181
|
/**
|
|
149
182
|
* Properties that will not be searchable from the frontend. If the frontend
|
|
150
183
|
* includes any of these properties in any of their clauses, they will be
|
|
@@ -156,8 +189,20 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
156
189
|
* be visible on the frontend, unlike $privateData, but any changes to them
|
|
157
190
|
* that come from the frontend will be ignored.
|
|
158
191
|
*
|
|
159
|
-
* In addition to what's listed here, the
|
|
160
|
-
* be
|
|
192
|
+
* In addition to what's listed here, all of the access control properties
|
|
193
|
+
* will be included when Tilmeld is being used. These are:
|
|
194
|
+
*
|
|
195
|
+
* - acUser
|
|
196
|
+
* - acGroup
|
|
197
|
+
* - acOther
|
|
198
|
+
* - acRead
|
|
199
|
+
* - acWrite
|
|
200
|
+
* - acFull
|
|
201
|
+
* - user
|
|
202
|
+
* - group
|
|
203
|
+
*
|
|
204
|
+
* You should modify these through client enabled methods or the $save method
|
|
205
|
+
* instead, for safety.
|
|
161
206
|
*/
|
|
162
207
|
protected $protectedData: string[] = [];
|
|
163
208
|
/**
|
|
@@ -196,28 +241,39 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
196
241
|
* The AC properties' values when the entity was loaded.
|
|
197
242
|
*/
|
|
198
243
|
private $originalAcValues: ACProperties | null = null;
|
|
244
|
+
/**
|
|
245
|
+
* This is used to hold a generated GUID for a new entity.
|
|
246
|
+
*/
|
|
247
|
+
private $guaranteedGUID: string | null = null;
|
|
199
248
|
|
|
200
249
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
250
|
+
* Alter the options for a query for this entity.
|
|
251
|
+
*
|
|
252
|
+
* @param options The current options.
|
|
253
|
+
* @returns The altered options.
|
|
203
254
|
*/
|
|
204
|
-
|
|
255
|
+
static alterOptions?<T extends Options>(options: T): T;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Initialize an entity.
|
|
259
|
+
*/
|
|
260
|
+
public constructor(..._rest: any[]) {
|
|
205
261
|
this.$nymph = (this.constructor as EntityConstructor).nymph;
|
|
206
262
|
this.$dataHandler = {
|
|
207
263
|
has: (data: EntityData, name: string) => {
|
|
208
|
-
this.$
|
|
264
|
+
this.$check();
|
|
209
265
|
|
|
210
266
|
return name in data || name in this.$sdata;
|
|
211
267
|
},
|
|
212
268
|
|
|
213
269
|
get: (data: EntityData, name: string) => {
|
|
214
|
-
this.$
|
|
270
|
+
this.$check();
|
|
215
271
|
|
|
216
272
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
217
273
|
data[name] = referencesToEntities(
|
|
218
274
|
JSON.parse(this.$sdata[name]),
|
|
219
275
|
this.$nymph,
|
|
220
|
-
this.$skipAc
|
|
276
|
+
this.$skipAc,
|
|
221
277
|
);
|
|
222
278
|
delete this.$sdata[name];
|
|
223
279
|
}
|
|
@@ -228,7 +284,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
228
284
|
},
|
|
229
285
|
|
|
230
286
|
set: (data: EntityData, name: string, value: any) => {
|
|
231
|
-
this.$
|
|
287
|
+
this.$check();
|
|
232
288
|
|
|
233
289
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
234
290
|
delete this.$sdata[name];
|
|
@@ -238,7 +294,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
238
294
|
},
|
|
239
295
|
|
|
240
296
|
deleteProperty: (data: EntityData, name: string) => {
|
|
241
|
-
this.$
|
|
297
|
+
this.$check();
|
|
242
298
|
|
|
243
299
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
244
300
|
return delete this.$sdata[name];
|
|
@@ -252,9 +308,9 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
252
308
|
defineProperty: (
|
|
253
309
|
data: EntityData,
|
|
254
310
|
name: string,
|
|
255
|
-
descriptor: PropertyDescriptor
|
|
311
|
+
descriptor: PropertyDescriptor,
|
|
256
312
|
) => {
|
|
257
|
-
this.$
|
|
313
|
+
this.$check();
|
|
258
314
|
|
|
259
315
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
260
316
|
delete this.$sdata[name];
|
|
@@ -264,13 +320,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
264
320
|
},
|
|
265
321
|
|
|
266
322
|
getOwnPropertyDescriptor: (data: EntityData, name: string) => {
|
|
267
|
-
this.$
|
|
323
|
+
this.$check();
|
|
268
324
|
|
|
269
325
|
if (this.$sdata.hasOwnProperty(name)) {
|
|
270
326
|
data[name] = referencesToEntities(
|
|
271
327
|
JSON.parse(this.$sdata[name]),
|
|
272
328
|
this.$nymph,
|
|
273
|
-
this.$skipAc
|
|
329
|
+
this.$skipAc,
|
|
274
330
|
);
|
|
275
331
|
delete this.$sdata[name];
|
|
276
332
|
}
|
|
@@ -278,10 +334,10 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
278
334
|
},
|
|
279
335
|
|
|
280
336
|
ownKeys: (data: EntityData) => {
|
|
281
|
-
this.$
|
|
337
|
+
this.$check();
|
|
282
338
|
|
|
283
339
|
return Object.getOwnPropertyNames(data).concat(
|
|
284
|
-
Object.getOwnPropertyNames(this.$sdata)
|
|
340
|
+
Object.getOwnPropertyNames(this.$sdata),
|
|
285
341
|
);
|
|
286
342
|
},
|
|
287
343
|
};
|
|
@@ -290,20 +346,6 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
290
346
|
|
|
291
347
|
this.$data = new Proxy(this.$dataStore, this.$dataHandler);
|
|
292
348
|
|
|
293
|
-
if (guid != null) {
|
|
294
|
-
const entity = this.$nymph.driver.getEntitySync(
|
|
295
|
-
{ class: this.constructor as EntityConstructor },
|
|
296
|
-
{ type: '&', guid }
|
|
297
|
-
);
|
|
298
|
-
if (entity) {
|
|
299
|
-
this.guid = entity.guid;
|
|
300
|
-
this.tags = entity.tags;
|
|
301
|
-
this.cdate = entity.cdate;
|
|
302
|
-
this.mdate = entity.mdate;
|
|
303
|
-
this.$putData(entity.$getData(), entity.$getSData());
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
349
|
return new Proxy(this, {
|
|
308
350
|
has: (entity: Entity, name: string) => {
|
|
309
351
|
if (
|
|
@@ -314,7 +356,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
314
356
|
return name in entity;
|
|
315
357
|
}
|
|
316
358
|
|
|
317
|
-
this.$
|
|
359
|
+
this.$check();
|
|
318
360
|
return name in entity.$data;
|
|
319
361
|
},
|
|
320
362
|
|
|
@@ -325,12 +367,12 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
325
367
|
name.substring(0, 1) === '$'
|
|
326
368
|
) {
|
|
327
369
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
328
|
-
this.$
|
|
370
|
+
this.$check();
|
|
329
371
|
}
|
|
330
372
|
return (entity as any)[name];
|
|
331
373
|
}
|
|
332
374
|
|
|
333
|
-
this.$
|
|
375
|
+
this.$check();
|
|
334
376
|
if (name in entity.$data) {
|
|
335
377
|
return entity.$data[name];
|
|
336
378
|
}
|
|
@@ -344,11 +386,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
344
386
|
name.substring(0, 1) === '$'
|
|
345
387
|
) {
|
|
346
388
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
347
|
-
this.$
|
|
389
|
+
this.$check();
|
|
348
390
|
}
|
|
349
391
|
(entity as any)[name] = value;
|
|
350
392
|
} else {
|
|
351
|
-
this.$
|
|
393
|
+
this.$check();
|
|
352
394
|
(entity.$data as any)[name] = value;
|
|
353
395
|
}
|
|
354
396
|
return true;
|
|
@@ -358,7 +400,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
358
400
|
if (name in entity) {
|
|
359
401
|
return delete (entity as any)[name];
|
|
360
402
|
} else if (name in entity.$data) {
|
|
361
|
-
this.$
|
|
403
|
+
this.$check();
|
|
362
404
|
return delete entity.$data[name];
|
|
363
405
|
}
|
|
364
406
|
return true;
|
|
@@ -371,7 +413,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
371
413
|
defineProperty: (
|
|
372
414
|
entity: Entity,
|
|
373
415
|
name: string,
|
|
374
|
-
descriptor: PropertyDescriptor
|
|
416
|
+
descriptor: PropertyDescriptor,
|
|
375
417
|
) => {
|
|
376
418
|
if (
|
|
377
419
|
typeof name !== 'string' ||
|
|
@@ -379,11 +421,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
379
421
|
name.substring(0, 1) === '$'
|
|
380
422
|
) {
|
|
381
423
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
382
|
-
this.$
|
|
424
|
+
this.$check();
|
|
383
425
|
}
|
|
384
426
|
Object.defineProperty(entity, name, descriptor);
|
|
385
427
|
} else {
|
|
386
|
-
this.$
|
|
428
|
+
this.$check();
|
|
387
429
|
Object.defineProperty(entity.$data, name, descriptor);
|
|
388
430
|
}
|
|
389
431
|
return true;
|
|
@@ -396,48 +438,147 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
396
438
|
name.substring(0, 1) === '$'
|
|
397
439
|
) {
|
|
398
440
|
if (name === 'tags' || name === 'cdate' || name === 'mdate') {
|
|
399
|
-
this.$
|
|
441
|
+
this.$check();
|
|
400
442
|
}
|
|
401
443
|
return Object.getOwnPropertyDescriptor(entity, name);
|
|
402
444
|
} else {
|
|
403
|
-
this.$
|
|
445
|
+
this.$check();
|
|
404
446
|
return Object.getOwnPropertyDescriptor(entity.$data, name);
|
|
405
447
|
}
|
|
406
448
|
},
|
|
407
449
|
|
|
408
450
|
ownKeys: (entity: Entity) => {
|
|
409
|
-
this.$
|
|
451
|
+
this.$check();
|
|
410
452
|
return Object.getOwnPropertyNames(entity).concat(
|
|
411
|
-
Object.getOwnPropertyNames(entity.$data)
|
|
453
|
+
Object.getOwnPropertyNames(entity.$data),
|
|
412
454
|
);
|
|
413
455
|
},
|
|
414
456
|
}) as Entity<T>;
|
|
415
457
|
}
|
|
416
458
|
|
|
417
|
-
|
|
459
|
+
/**
|
|
460
|
+
* Create or retrieve a new entity instance.
|
|
461
|
+
*
|
|
462
|
+
* Note that this will always return an entity, even if the GUID is not found.
|
|
463
|
+
*
|
|
464
|
+
* @param guid An optional GUID to retrieve.
|
|
465
|
+
*/
|
|
466
|
+
public static async factory<E extends Entity>(
|
|
467
|
+
this: {
|
|
468
|
+
new (): E;
|
|
469
|
+
},
|
|
470
|
+
guid?: string,
|
|
471
|
+
): Promise<E & EntityDataType<E>> {
|
|
418
472
|
const entity = new this();
|
|
419
473
|
if (guid != null) {
|
|
420
|
-
const entity = await
|
|
474
|
+
const entity = await (
|
|
475
|
+
this as unknown as EntityConstructor
|
|
476
|
+
).nymph.getEntity(
|
|
421
477
|
{
|
|
422
|
-
class: this as
|
|
478
|
+
class: this as unknown as EntityConstructor,
|
|
423
479
|
},
|
|
424
|
-
{ type: '&', guid }
|
|
480
|
+
{ type: '&', guid },
|
|
425
481
|
);
|
|
426
482
|
if (entity != null) {
|
|
427
|
-
return entity
|
|
483
|
+
return entity as E & EntityDataType<E>;
|
|
428
484
|
}
|
|
429
485
|
}
|
|
430
|
-
return entity
|
|
486
|
+
return entity as E & EntityDataType<E>;
|
|
431
487
|
}
|
|
432
488
|
|
|
433
|
-
|
|
434
|
-
|
|
489
|
+
/**
|
|
490
|
+
* Create a new entity instance.
|
|
491
|
+
*/
|
|
492
|
+
public static factorySync<E extends Entity>(this: {
|
|
493
|
+
new (): E;
|
|
494
|
+
}): E & EntityDataType<E> {
|
|
495
|
+
return new this() as E & EntityDataType<E>;
|
|
435
496
|
}
|
|
436
497
|
|
|
437
|
-
|
|
498
|
+
/**
|
|
499
|
+
* Create a new sleeping reference instance.
|
|
500
|
+
*
|
|
501
|
+
* Sleeping references won't retrieve their data from the database until they
|
|
502
|
+
* are readied with `$wake()` or a parent's `$wakeAll()`.
|
|
503
|
+
*
|
|
504
|
+
* @param reference The Nymph Entity Reference to use to wake.
|
|
505
|
+
* @returns The new instance.
|
|
506
|
+
*/
|
|
507
|
+
public static factoryReference<E extends Entity>(
|
|
508
|
+
this: {
|
|
509
|
+
new (): E;
|
|
510
|
+
},
|
|
511
|
+
reference: EntityReference,
|
|
512
|
+
): E & EntityDataType<E> {
|
|
438
513
|
const entity = new this();
|
|
439
514
|
entity.$referenceSleep(reference);
|
|
440
|
-
return entity
|
|
515
|
+
return entity as E & EntityDataType<E>;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Get an array of strings that **must** be unique across the current etype.
|
|
520
|
+
*
|
|
521
|
+
* When you try to save another entity with any of the same unique strings,
|
|
522
|
+
* Nymph will throw an error.
|
|
523
|
+
*
|
|
524
|
+
* The default implementation of this static method instantiates the entity,
|
|
525
|
+
* assigns all of the given data, then calls `$getUniques` and returns its
|
|
526
|
+
* output. This can have a performance impact if a lot of extra processing
|
|
527
|
+
* happens during any of these steps. You can override this method to
|
|
528
|
+
* calculate the unique strings faster, but you must return the same strings
|
|
529
|
+
* that would be returned by `$getUniques`.
|
|
530
|
+
*
|
|
531
|
+
* @returns Resolves to an array of entity's unique constraint strings.
|
|
532
|
+
*/
|
|
533
|
+
public static async getUniques({
|
|
534
|
+
guid,
|
|
535
|
+
cdate,
|
|
536
|
+
mdate,
|
|
537
|
+
tags,
|
|
538
|
+
data,
|
|
539
|
+
sdata,
|
|
540
|
+
}: {
|
|
541
|
+
guid?: string;
|
|
542
|
+
cdate?: number;
|
|
543
|
+
mdate?: number;
|
|
544
|
+
tags: string[];
|
|
545
|
+
data: EntityData;
|
|
546
|
+
sdata?: SerializedEntityData;
|
|
547
|
+
}) {
|
|
548
|
+
const entity = new this();
|
|
549
|
+
if (guid != null) {
|
|
550
|
+
entity.guid = guid;
|
|
551
|
+
}
|
|
552
|
+
if (cdate != null) {
|
|
553
|
+
entity.cdate = cdate;
|
|
554
|
+
}
|
|
555
|
+
if (mdate != null) {
|
|
556
|
+
entity.mdate = mdate;
|
|
557
|
+
}
|
|
558
|
+
entity.tags = tags;
|
|
559
|
+
entity.$putData(data, sdata);
|
|
560
|
+
return await entity.$getUniques();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Get a string for full text search for one of an entity's properties.
|
|
565
|
+
*
|
|
566
|
+
* The result will be tokenized and stored as the full text search index for
|
|
567
|
+
* use with "search" clauses.
|
|
568
|
+
*
|
|
569
|
+
* Return null to not include any tokens in the full text search storage.
|
|
570
|
+
*
|
|
571
|
+
* You shouldn't use any other entity data to transform the text, as it won't
|
|
572
|
+
* always be available. This function is meant for things like stripping HTML
|
|
573
|
+
* tags.
|
|
574
|
+
*
|
|
575
|
+
* @returns By default, returns the value if it is a string.
|
|
576
|
+
*/
|
|
577
|
+
public static getFTSText(_name: string, value: any) {
|
|
578
|
+
if (typeof value === 'string') {
|
|
579
|
+
return value;
|
|
580
|
+
}
|
|
581
|
+
return null;
|
|
441
582
|
}
|
|
442
583
|
|
|
443
584
|
public toJSON() {
|
|
@@ -452,17 +593,29 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
452
593
|
tags: [...this.tags],
|
|
453
594
|
data: {},
|
|
454
595
|
};
|
|
455
|
-
const
|
|
456
|
-
|
|
596
|
+
for (const key of [
|
|
597
|
+
...Object.keys(this.$dataStore),
|
|
598
|
+
...Object.keys(this.$sdata),
|
|
599
|
+
]) {
|
|
457
600
|
if (this.$privateData.indexOf(key) === -1) {
|
|
458
|
-
obj.data[key] = entitiesToReferences(data[key]);
|
|
601
|
+
obj.data[key] = entitiesToReferences(this.$data[key], true);
|
|
459
602
|
}
|
|
460
603
|
}
|
|
461
604
|
return obj;
|
|
462
605
|
}
|
|
463
606
|
|
|
607
|
+
public $getGuaranteedGUID() {
|
|
608
|
+
if (this.guid !== null) {
|
|
609
|
+
return this.guid;
|
|
610
|
+
}
|
|
611
|
+
if (this.$guaranteedGUID == null) {
|
|
612
|
+
this.$guaranteedGUID = guid();
|
|
613
|
+
}
|
|
614
|
+
return this.$guaranteedGUID;
|
|
615
|
+
}
|
|
616
|
+
|
|
464
617
|
public $addTag(...tags: string[]) {
|
|
465
|
-
this.$
|
|
618
|
+
this.$check();
|
|
466
619
|
|
|
467
620
|
if (tags.length < 1) {
|
|
468
621
|
return;
|
|
@@ -471,7 +624,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
471
624
|
}
|
|
472
625
|
|
|
473
626
|
public $arraySearch(array: any[], strict = false) {
|
|
474
|
-
this.$
|
|
627
|
+
this.$check();
|
|
475
628
|
|
|
476
629
|
if (!Array.isArray(array)) {
|
|
477
630
|
return -1;
|
|
@@ -486,9 +639,9 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
486
639
|
}
|
|
487
640
|
|
|
488
641
|
public $clearCache() {
|
|
489
|
-
this.$
|
|
642
|
+
this.$check();
|
|
490
643
|
|
|
491
|
-
this.$putData(this.$getData(), this.$getSData());
|
|
644
|
+
this.$putData(this.$getData(false, true), this.$getSData());
|
|
492
645
|
}
|
|
493
646
|
|
|
494
647
|
public $getClientEnabledMethods() {
|
|
@@ -496,13 +649,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
496
649
|
}
|
|
497
650
|
|
|
498
651
|
public async $delete(): Promise<boolean> {
|
|
499
|
-
this.$
|
|
652
|
+
this.$check();
|
|
500
653
|
|
|
501
654
|
return await this.$nymph.deleteEntity(this);
|
|
502
655
|
}
|
|
503
656
|
|
|
504
657
|
public $equals(object: any) {
|
|
505
|
-
this.$
|
|
658
|
+
this.$check();
|
|
506
659
|
|
|
507
660
|
if (!(object instanceof Entity)) {
|
|
508
661
|
return false;
|
|
@@ -523,13 +676,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
523
676
|
if (!isEqual(obTags, myTags)) {
|
|
524
677
|
return false;
|
|
525
678
|
}
|
|
526
|
-
const obData = object.$getData(true);
|
|
527
|
-
const myData = this.$getData(true);
|
|
679
|
+
const obData = object.$getData(true, true);
|
|
680
|
+
const myData = this.$getData(true, true);
|
|
528
681
|
return isEqual(obData, myData);
|
|
529
682
|
}
|
|
530
683
|
|
|
531
|
-
public $getData(includeSData = false) {
|
|
532
|
-
this.$
|
|
684
|
+
public $getData(includeSData = false, referenceOnlyExisting?: boolean) {
|
|
685
|
+
this.$check();
|
|
533
686
|
|
|
534
687
|
if (includeSData) {
|
|
535
688
|
// Access all the serialized properties to initialize them.
|
|
@@ -537,34 +690,79 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
537
690
|
const _unused: any = (this as any)[key];
|
|
538
691
|
}
|
|
539
692
|
}
|
|
540
|
-
return entitiesToReferences({ ...this.$dataStore });
|
|
693
|
+
return entitiesToReferences({ ...this.$dataStore }, referenceOnlyExisting);
|
|
541
694
|
}
|
|
542
695
|
|
|
543
696
|
public $getSData() {
|
|
544
|
-
this.$
|
|
697
|
+
this.$check();
|
|
545
698
|
|
|
546
699
|
return this.$sdata;
|
|
547
700
|
}
|
|
548
701
|
|
|
549
|
-
public $
|
|
550
|
-
|
|
702
|
+
public async $getUniques(): Promise<string[]> {
|
|
703
|
+
return [];
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
public $getOriginalAcValues(): ACProperties {
|
|
707
|
+
this.$check();
|
|
708
|
+
|
|
709
|
+
return this.$originalAcValues ?? this.$getCurrentAcValues();
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
public $getCurrentAcValues(): ACProperties {
|
|
713
|
+
this.$check();
|
|
714
|
+
|
|
715
|
+
return {
|
|
716
|
+
user: this.$getAcUid(),
|
|
717
|
+
group: this.$getAcGid(),
|
|
718
|
+
acUser: this.$data.acUser ?? null,
|
|
719
|
+
acGroup: this.$data.acGroup ?? null,
|
|
720
|
+
acOther: this.$data.acOther ?? null,
|
|
721
|
+
acRead: this.$getAcReadIds(),
|
|
722
|
+
acWrite: this.$getAcWriteIds(),
|
|
723
|
+
acFull: this.$getAcFullIds(),
|
|
724
|
+
};
|
|
725
|
+
}
|
|
551
726
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
acWrite: this.$data.acWrite,
|
|
561
|
-
acFull: this.$data.acFull,
|
|
727
|
+
public $getAcUid() {
|
|
728
|
+
if ('user' in this.$sdata) {
|
|
729
|
+
const userValue = JSON.parse(this.$sdata.user);
|
|
730
|
+
if (
|
|
731
|
+
Array.isArray(userValue) &&
|
|
732
|
+
userValue[0] === 'nymph_entity_reference'
|
|
733
|
+
) {
|
|
734
|
+
return userValue[1];
|
|
562
735
|
}
|
|
563
|
-
|
|
736
|
+
}
|
|
737
|
+
return (this.$data.user?.guid ?? null) as string | null;
|
|
738
|
+
}
|
|
739
|
+
public $getAcGid() {
|
|
740
|
+
if ('group' in this.$sdata) {
|
|
741
|
+
const groupValue = JSON.parse(this.$sdata.group);
|
|
742
|
+
if (
|
|
743
|
+
Array.isArray(groupValue) &&
|
|
744
|
+
groupValue[0] === 'nymph_entity_reference'
|
|
745
|
+
) {
|
|
746
|
+
return groupValue[1];
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return (this.$data.group?.guid ?? null) as string | null;
|
|
750
|
+
}
|
|
751
|
+
public $getAcReadIds() {
|
|
752
|
+
return (this.$data.acRead?.map((entity: EntityInterface) => entity.guid) ??
|
|
753
|
+
null) as (string | null)[] | null;
|
|
754
|
+
}
|
|
755
|
+
public $getAcWriteIds() {
|
|
756
|
+
return (this.$data.acWrite?.map((entity: EntityInterface) => entity.guid) ??
|
|
757
|
+
null) as (string | null)[] | null;
|
|
758
|
+
}
|
|
759
|
+
public $getAcFullIds() {
|
|
760
|
+
return (this.$data.acFull?.map((entity: EntityInterface) => entity.guid) ??
|
|
761
|
+
null) as (string | null)[] | null;
|
|
564
762
|
}
|
|
565
763
|
|
|
566
764
|
public $getValidatable() {
|
|
567
|
-
this.$
|
|
765
|
+
this.$check();
|
|
568
766
|
|
|
569
767
|
// Access all the serialized properties to initialize them.
|
|
570
768
|
for (const key in this.$sdata) {
|
|
@@ -580,13 +778,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
580
778
|
}
|
|
581
779
|
|
|
582
780
|
public $getTags() {
|
|
583
|
-
this.$
|
|
781
|
+
this.$check();
|
|
584
782
|
|
|
585
783
|
return this.tags;
|
|
586
784
|
}
|
|
587
785
|
|
|
588
786
|
public $hasTag(...tags: string[]) {
|
|
589
|
-
this.$
|
|
787
|
+
this.$check();
|
|
590
788
|
|
|
591
789
|
if (!tags.length) {
|
|
592
790
|
return false;
|
|
@@ -608,11 +806,15 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
608
806
|
return false;
|
|
609
807
|
}
|
|
610
808
|
|
|
611
|
-
if (this
|
|
809
|
+
if (this === object) {
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if (this.guid != null || object.guid != null) {
|
|
612
814
|
return this.guid === object.guid;
|
|
613
815
|
}
|
|
614
816
|
|
|
615
|
-
this.$
|
|
817
|
+
this.$check();
|
|
616
818
|
if (typeof object.$getData !== 'function') {
|
|
617
819
|
return false;
|
|
618
820
|
} else {
|
|
@@ -621,19 +823,18 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
621
823
|
if (!isEqual(obTags, myTags)) {
|
|
622
824
|
return false;
|
|
623
825
|
}
|
|
624
|
-
const obData = object.$getData(true);
|
|
625
|
-
const myData = this.$getData(true);
|
|
826
|
+
const obData = object.$getData(true, true);
|
|
827
|
+
const myData = this.$getData(true, true);
|
|
626
828
|
return isEqual(obData, myData);
|
|
627
829
|
}
|
|
628
830
|
}
|
|
629
831
|
|
|
630
832
|
public $jsonAcceptData(input: EntityJson, allowConflict = false) {
|
|
631
|
-
|
|
632
|
-
this.$referenceWake();
|
|
833
|
+
this.$check();
|
|
633
834
|
|
|
634
835
|
if (this.guid != input.guid) {
|
|
635
836
|
throw new EntityConflictError(
|
|
636
|
-
'Tried to accept JSON input for the wrong entity.'
|
|
837
|
+
'Tried to accept JSON input for the wrong entity.',
|
|
637
838
|
);
|
|
638
839
|
}
|
|
639
840
|
|
|
@@ -658,7 +859,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
658
859
|
this.$addTag(...protectedTags, ...tags);
|
|
659
860
|
|
|
660
861
|
// Accept the data.
|
|
661
|
-
const data = input.data;
|
|
862
|
+
const data = { ...input.data };
|
|
662
863
|
const privateData: EntityData = {};
|
|
663
864
|
for (const name of this.$privateData) {
|
|
664
865
|
if (name in this.$data) {
|
|
@@ -671,12 +872,27 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
671
872
|
|
|
672
873
|
const protectedData: EntityData = {};
|
|
673
874
|
const protectedProps = [...this.$protectedData];
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
protectedProps.push('
|
|
679
|
-
protectedProps.push('
|
|
875
|
+
if (this.$nymph.tilmeld) {
|
|
876
|
+
protectedProps.push('acUser');
|
|
877
|
+
protectedProps.push('acGroup');
|
|
878
|
+
protectedProps.push('acOther');
|
|
879
|
+
protectedProps.push('acRead');
|
|
880
|
+
protectedProps.push('acWrite');
|
|
881
|
+
protectedProps.push('acFull');
|
|
882
|
+
if (
|
|
883
|
+
((this.constructor as EntityConstructor).class !== 'User' &&
|
|
884
|
+
(this.constructor as EntityConstructor).class !== 'Group') ||
|
|
885
|
+
!(this.$nymph.tilmeld as any).currentUser ||
|
|
886
|
+
(!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
887
|
+
'tilmeld/admin',
|
|
888
|
+
) &&
|
|
889
|
+
!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
890
|
+
'system/admin',
|
|
891
|
+
))
|
|
892
|
+
) {
|
|
893
|
+
protectedProps.push('user');
|
|
894
|
+
protectedProps.push('group');
|
|
895
|
+
}
|
|
680
896
|
}
|
|
681
897
|
for (const name of protectedProps) {
|
|
682
898
|
if (name in this.$data) {
|
|
@@ -689,7 +905,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
689
905
|
|
|
690
906
|
let nonAllowlistData: EntityData = {};
|
|
691
907
|
if (this.$allowlistData != null) {
|
|
692
|
-
nonAllowlistData = { ...this.$getData(true) };
|
|
908
|
+
nonAllowlistData = { ...this.$getData(true, true) };
|
|
693
909
|
for (const name of this.$allowlistData) {
|
|
694
910
|
delete nonAllowlistData[name];
|
|
695
911
|
}
|
|
@@ -709,11 +925,11 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
709
925
|
}
|
|
710
926
|
|
|
711
927
|
public $jsonAcceptPatch(patch: EntityPatch, allowConflict = false) {
|
|
712
|
-
this.$
|
|
928
|
+
this.$check();
|
|
713
929
|
|
|
714
930
|
if (this.guid != patch.guid) {
|
|
715
931
|
throw new EntityConflictError(
|
|
716
|
-
'Tried to accept JSON patch for the wrong entity.'
|
|
932
|
+
'Tried to accept JSON patch for the wrong entity.',
|
|
717
933
|
);
|
|
718
934
|
}
|
|
719
935
|
|
|
@@ -725,11 +941,35 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
725
941
|
}
|
|
726
942
|
this.mdate = patch.mdate;
|
|
727
943
|
|
|
944
|
+
const protectedProps = [...this.$protectedData];
|
|
945
|
+
if (this.$nymph.tilmeld) {
|
|
946
|
+
protectedProps.push('acUser');
|
|
947
|
+
protectedProps.push('acGroup');
|
|
948
|
+
protectedProps.push('acOther');
|
|
949
|
+
protectedProps.push('acRead');
|
|
950
|
+
protectedProps.push('acWrite');
|
|
951
|
+
protectedProps.push('acFull');
|
|
952
|
+
if (
|
|
953
|
+
((this.constructor as EntityConstructor).class !== 'User' &&
|
|
954
|
+
(this.constructor as EntityConstructor).class !== 'Group') ||
|
|
955
|
+
!(this.$nymph.tilmeld as any).currentUser ||
|
|
956
|
+
(!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
957
|
+
'tilmeld/admin',
|
|
958
|
+
) &&
|
|
959
|
+
!(this.$nymph.tilmeld as any).currentUser.abilities?.includes(
|
|
960
|
+
'system/admin',
|
|
961
|
+
))
|
|
962
|
+
) {
|
|
963
|
+
protectedProps.push('user');
|
|
964
|
+
protectedProps.push('group');
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
728
968
|
for (const name in patch.set) {
|
|
729
969
|
if (
|
|
730
970
|
(this.$allowlistData != null &&
|
|
731
971
|
this.$allowlistData.indexOf(name) === -1) ||
|
|
732
|
-
|
|
972
|
+
protectedProps.indexOf(name) !== -1 ||
|
|
733
973
|
this.$privateData.indexOf(name) !== -1
|
|
734
974
|
) {
|
|
735
975
|
continue;
|
|
@@ -737,7 +977,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
737
977
|
(this.$data as any)[name] = referencesToEntities(
|
|
738
978
|
patch.set[name],
|
|
739
979
|
this.$nymph,
|
|
740
|
-
this.$skipAc
|
|
980
|
+
this.$skipAc,
|
|
741
981
|
);
|
|
742
982
|
}
|
|
743
983
|
|
|
@@ -745,7 +985,7 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
745
985
|
if (
|
|
746
986
|
(this.$allowlistData != null &&
|
|
747
987
|
this.$allowlistData.indexOf(name) === -1) ||
|
|
748
|
-
|
|
988
|
+
protectedProps.indexOf(name) !== -1 ||
|
|
749
989
|
this.$privateData.indexOf(name) !== -1
|
|
750
990
|
) {
|
|
751
991
|
continue;
|
|
@@ -776,8 +1016,12 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
776
1016
|
}
|
|
777
1017
|
}
|
|
778
1018
|
|
|
779
|
-
public $putData(
|
|
780
|
-
|
|
1019
|
+
public $putData(
|
|
1020
|
+
data: EntityData,
|
|
1021
|
+
sdata?: SerializedEntityData,
|
|
1022
|
+
_source?: 'server',
|
|
1023
|
+
) {
|
|
1024
|
+
this.$check();
|
|
781
1025
|
|
|
782
1026
|
const mySdata = sdata ?? this.$getSData();
|
|
783
1027
|
for (const name in data) {
|
|
@@ -790,13 +1034,13 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
790
1034
|
(this.$dataStore as any)[name] = referencesToEntities(
|
|
791
1035
|
data[name],
|
|
792
1036
|
this.$nymph,
|
|
793
|
-
this.$skipAc
|
|
1037
|
+
this.$skipAc,
|
|
794
1038
|
);
|
|
795
1039
|
}
|
|
796
1040
|
this.$sdata = mySdata;
|
|
797
1041
|
// Set original AC values if not set..
|
|
798
1042
|
if (this.$originalAcValues == null) {
|
|
799
|
-
this.$originalAcValues = this.$
|
|
1043
|
+
this.$originalAcValues = this.$getCurrentAcValues();
|
|
800
1044
|
}
|
|
801
1045
|
}
|
|
802
1046
|
|
|
@@ -813,14 +1057,14 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
813
1057
|
) {
|
|
814
1058
|
throw new InvalidParametersError(
|
|
815
1059
|
'referenceSleep expects parameter 1 to be a valid Nymph entity ' +
|
|
816
|
-
'reference.'
|
|
1060
|
+
'reference.',
|
|
817
1061
|
);
|
|
818
1062
|
}
|
|
819
1063
|
const thisClass: string = (this.constructor as any).class;
|
|
820
1064
|
if (reference[2] !== thisClass) {
|
|
821
1065
|
throw new InvalidParametersError(
|
|
822
1066
|
'referenceSleep can only be called with an entity reference of the ' +
|
|
823
|
-
`same class. Given class: ${reference[2]}; this class: ${thisClass}
|
|
1067
|
+
`same class. Given class: ${reference[2]}; this class: ${thisClass}.`,
|
|
824
1068
|
);
|
|
825
1069
|
}
|
|
826
1070
|
this.$isASleepingReference = true;
|
|
@@ -828,49 +1072,141 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
828
1072
|
this.$sleepingReference = reference;
|
|
829
1073
|
}
|
|
830
1074
|
|
|
1075
|
+
/**
|
|
1076
|
+
* Check if this is a sleeping reference and throw an error if so.
|
|
1077
|
+
*/
|
|
1078
|
+
protected $check() {
|
|
1079
|
+
if (this.$isASleepingReference || this.$sleepingReference != null) {
|
|
1080
|
+
throw new EntityIsSleepingReferenceError(
|
|
1081
|
+
'This entity is in a sleeping reference state. You must use .$wake() to wake it.',
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* Check if this is a sleeping reference.
|
|
1088
|
+
*/
|
|
1089
|
+
public $asleep() {
|
|
1090
|
+
return this.$isASleepingReference || this.$sleepingReference != null;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
831
1093
|
/**
|
|
832
1094
|
* Wake from a sleeping reference.
|
|
833
|
-
*
|
|
834
|
-
* @returns True on success, false on failure.
|
|
835
1095
|
*/
|
|
836
|
-
|
|
1096
|
+
public $wake() {
|
|
837
1097
|
if (!this.$isASleepingReference || this.$sleepingReference == null) {
|
|
838
|
-
|
|
1098
|
+
this.$wakePromise = null;
|
|
1099
|
+
return Promise.resolve(this);
|
|
839
1100
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
skipAc: this.$skipAc,
|
|
845
|
-
},
|
|
846
|
-
{ type: '&', guid: this.$sleepingReference[1] }
|
|
847
|
-
);
|
|
848
|
-
if (entity == null) {
|
|
849
|
-
return false;
|
|
1101
|
+
if (this.$sleepingReference?.[1] == null) {
|
|
1102
|
+
throw new InvalidStateError(
|
|
1103
|
+
'Tried to wake a sleeping reference with no GUID.',
|
|
1104
|
+
);
|
|
850
1105
|
}
|
|
851
|
-
this.$
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1106
|
+
if (!this.$wakePromise) {
|
|
1107
|
+
const EntityClass = this.$nymph.getEntityClass(
|
|
1108
|
+
this.$sleepingReference[2],
|
|
1109
|
+
);
|
|
1110
|
+
this.$wakePromise = this.$nymph
|
|
1111
|
+
.getEntity(
|
|
1112
|
+
{
|
|
1113
|
+
class: EntityClass,
|
|
1114
|
+
skipAc: this.$skipAc,
|
|
1115
|
+
},
|
|
1116
|
+
{ type: '&', guid: this.$sleepingReference[1] },
|
|
1117
|
+
)
|
|
1118
|
+
.then((entity) => {
|
|
1119
|
+
if (entity == null || entity.guid == null) {
|
|
1120
|
+
return Promise.reject(
|
|
1121
|
+
new InvalidStateError(
|
|
1122
|
+
'The sleeping reference could not be retrieved.',
|
|
1123
|
+
),
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
this.$isASleepingReference = false;
|
|
1127
|
+
this.$sleepingReference = null;
|
|
1128
|
+
this.guid = entity.guid;
|
|
1129
|
+
this.tags = entity.tags;
|
|
1130
|
+
this.cdate = entity.cdate;
|
|
1131
|
+
this.mdate = entity.mdate;
|
|
1132
|
+
this.$putData(
|
|
1133
|
+
entity.$getData(false, true),
|
|
1134
|
+
entity.$getSData(),
|
|
1135
|
+
'server',
|
|
1136
|
+
);
|
|
1137
|
+
|
|
1138
|
+
return this;
|
|
1139
|
+
})
|
|
1140
|
+
.finally(() => {
|
|
1141
|
+
this.$wakePromise = null;
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
return this.$wakePromise;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
public $wakeAll(level?: number) {
|
|
1148
|
+
return new Promise((resolve, reject) => {
|
|
1149
|
+
// Run this once this entity is wake.
|
|
1150
|
+
const wakeProps = () => {
|
|
1151
|
+
let newLevel;
|
|
1152
|
+
// If level is undefined, keep going forever, otherwise, stop once we've
|
|
1153
|
+
// gone deep enough.
|
|
1154
|
+
if (level !== undefined) {
|
|
1155
|
+
newLevel = level - 1;
|
|
1156
|
+
}
|
|
1157
|
+
if (newLevel !== undefined && newLevel < 0) {
|
|
1158
|
+
resolve(this);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const promises = [];
|
|
1162
|
+
// Go through data looking for entities to wake.
|
|
1163
|
+
for (let [key, value] of Object.entries(this.$data)) {
|
|
1164
|
+
if (value instanceof Entity && value.$isASleepingReference) {
|
|
1165
|
+
promises.push(value.$wakeAll(newLevel));
|
|
1166
|
+
} else if (Array.isArray(value)) {
|
|
1167
|
+
for (let i = 0; i < value.length; i++) {
|
|
1168
|
+
if (
|
|
1169
|
+
value[i] instanceof Entity &&
|
|
1170
|
+
value[i].$isASleepingReference
|
|
1171
|
+
) {
|
|
1172
|
+
promises.push(value[i].$wakeAll(newLevel));
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
if (promises.length) {
|
|
1178
|
+
Promise.all(promises).then(
|
|
1179
|
+
() => resolve(this),
|
|
1180
|
+
(errObj) => reject(errObj),
|
|
1181
|
+
);
|
|
1182
|
+
} else {
|
|
1183
|
+
resolve(this);
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
|
|
1187
|
+
if (this.$isASleepingReference) {
|
|
1188
|
+
this.$wake().then(wakeProps, (errObj) => reject(errObj));
|
|
1189
|
+
} else {
|
|
1190
|
+
wakeProps();
|
|
1191
|
+
}
|
|
1192
|
+
}) as Promise<Entity<T>>;
|
|
859
1193
|
}
|
|
860
1194
|
|
|
861
1195
|
public async $refresh() {
|
|
862
|
-
this.$
|
|
1196
|
+
await this.$wake();
|
|
863
1197
|
|
|
864
1198
|
if (this.guid == null) {
|
|
865
1199
|
return false;
|
|
866
1200
|
}
|
|
867
1201
|
const refresh = await this.$nymph.getEntity(
|
|
868
1202
|
{
|
|
869
|
-
class: this.
|
|
1203
|
+
class: this.$nymph.getEntityClass(
|
|
1204
|
+
this.constructor as EntityConstructor,
|
|
1205
|
+
),
|
|
870
1206
|
skipCache: true,
|
|
871
1207
|
skipAc: this.$skipAc,
|
|
872
1208
|
},
|
|
873
|
-
{ type: '&', guid: this.guid }
|
|
1209
|
+
{ type: '&', guid: this.guid },
|
|
874
1210
|
);
|
|
875
1211
|
if (refresh == null) {
|
|
876
1212
|
return 0;
|
|
@@ -878,32 +1214,32 @@ export default class Entity<T extends EntityData = EntityData>
|
|
|
878
1214
|
this.tags = refresh.tags;
|
|
879
1215
|
this.cdate = refresh.cdate;
|
|
880
1216
|
this.mdate = refresh.mdate;
|
|
881
|
-
this.$putData(refresh.$getData(), refresh.$getSData());
|
|
1217
|
+
this.$putData(refresh.$getData(false, true), refresh.$getSData(), 'server');
|
|
882
1218
|
return true;
|
|
883
1219
|
}
|
|
884
1220
|
|
|
885
1221
|
public $removeTag(...tags: string[]) {
|
|
886
|
-
this.$
|
|
1222
|
+
this.$check();
|
|
887
1223
|
|
|
888
1224
|
this.tags = difference(this.tags, tags);
|
|
889
1225
|
}
|
|
890
1226
|
|
|
891
1227
|
public async $save(): Promise<boolean> {
|
|
892
|
-
this.$
|
|
1228
|
+
await this.$wake();
|
|
893
1229
|
|
|
894
1230
|
return await this.$nymph.saveEntity(this);
|
|
895
1231
|
}
|
|
896
1232
|
|
|
897
|
-
public $toReference() {
|
|
1233
|
+
public $toReference(existingOnly?: boolean) {
|
|
898
1234
|
if (this.$isASleepingReference && this.$sleepingReference != null) {
|
|
899
1235
|
return this.$sleepingReference;
|
|
900
1236
|
}
|
|
901
|
-
if (this.guid == null) {
|
|
1237
|
+
if (existingOnly && this.guid == null) {
|
|
902
1238
|
return this;
|
|
903
1239
|
}
|
|
904
1240
|
return [
|
|
905
1241
|
'nymph_entity_reference',
|
|
906
|
-
this
|
|
1242
|
+
this.$getGuaranteedGUID(),
|
|
907
1243
|
(this.constructor as any).class as string,
|
|
908
1244
|
] as EntityReference;
|
|
909
1245
|
}
|