@nymphjs/nymph 1.0.0-beta.1 → 1.0.0-beta.10
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 +52 -0
- package/README.md +4 -2
- package/dist/Entity.js +10 -3
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +17 -15
- package/dist/Entity.test.js.map +1 -1
- package/dist/Entity.types.d.ts +1 -1
- package/dist/Nymph.d.ts +3 -3
- package/dist/Nymph.js +38 -38
- package/dist/Nymph.js.map +1 -1
- package/dist/Nymph.types.d.ts +18 -18
- package/dist/Nymph.types.js.map +1 -1
- package/dist/driver/NymphDriver.d.ts +8 -4
- package/dist/driver/NymphDriver.js +81 -64
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/testArtifacts.js +147 -149
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/testMocks.d.ts +3 -1
- package/dist/testMocks.js +11 -6
- package/dist/testMocks.js.map +1 -1
- package/package.json +7 -7
- package/src/Entity.test.ts +14 -7
- package/src/Entity.ts +15 -9
- package/src/Entity.types.ts +1 -1
- package/src/Nymph.ts +67 -45
- package/src/Nymph.types.ts +35 -19
- package/src/driver/NymphDriver.ts +116 -74
- package/src/driver/testArtifacts.ts +14 -13
- package/src/testMocks.ts +14 -7
package/src/Nymph.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Config, ConfigDefaults as defaults } from './conf';
|
|
2
2
|
import { NymphDriver } from './driver';
|
|
3
3
|
import Entity from './Entity';
|
|
4
|
-
import { EntityConstructor,
|
|
4
|
+
import { EntityConstructor, EntityInterface } from './Entity.types';
|
|
5
5
|
import { ClassNotAvailableError } from './errors';
|
|
6
6
|
import type {
|
|
7
7
|
Selector,
|
|
@@ -63,7 +63,7 @@ export default class Nymph {
|
|
|
63
63
|
/**
|
|
64
64
|
* The entity class for this instance of Nymph.
|
|
65
65
|
*/
|
|
66
|
-
public Entity: typeof Entity
|
|
66
|
+
public Entity: typeof Entity;
|
|
67
67
|
|
|
68
68
|
private connectCallbacks: NymphConnectCallback[] = [];
|
|
69
69
|
private disconnectCallbacks: NymphDisconnectCallback[] = [];
|
|
@@ -87,20 +87,6 @@ export default class Nymph {
|
|
|
87
87
|
private beforeDeleteUIDCallbacks: NymphBeforeDeleteUIDCallback[] = [];
|
|
88
88
|
private afterDeleteUIDCallbacks: NymphAfterDeleteUIDCallback[] = [];
|
|
89
89
|
|
|
90
|
-
public addEntityClass(entityClass: EntityConstructor) {
|
|
91
|
-
this.entityClasses[entityClass.class] = entityClass;
|
|
92
|
-
entityClass.nymph = this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
public getEntityClass(className: string): EntityConstructor {
|
|
96
|
-
if (className in this.entityClasses) {
|
|
97
|
-
const EntityClass = this.entityClasses[className];
|
|
98
|
-
EntityClass.nymph = this;
|
|
99
|
-
return EntityClass;
|
|
100
|
-
}
|
|
101
|
-
throw new ClassNotAvailableError('Tried to use class: ' + className);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
90
|
/**
|
|
105
91
|
* Initialize Nymph.
|
|
106
92
|
*
|
|
@@ -115,28 +101,63 @@ export default class Nymph {
|
|
|
115
101
|
) {
|
|
116
102
|
this.config = { ...defaults, ...config };
|
|
117
103
|
this.driver = driver;
|
|
104
|
+
|
|
105
|
+
this.Entity = this.addEntityClass(Entity);
|
|
106
|
+
|
|
118
107
|
if (typeof tilmeld !== 'undefined') {
|
|
119
108
|
this.tilmeld = tilmeld;
|
|
120
109
|
}
|
|
121
110
|
|
|
122
|
-
class NymphEntity<T extends EntityData = EntityData> extends Entity<T> {}
|
|
123
|
-
NymphEntity.nymph = this;
|
|
124
|
-
this.Entity = NymphEntity;
|
|
125
|
-
this.addEntityClass(NymphEntity);
|
|
126
|
-
|
|
127
111
|
this.driver.init(this);
|
|
128
112
|
if (this.tilmeld) {
|
|
129
113
|
this.tilmeld.init(this);
|
|
130
114
|
}
|
|
131
115
|
}
|
|
132
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Add your class to this instance.
|
|
119
|
+
*
|
|
120
|
+
* This will create a class that extends your class within this instance of
|
|
121
|
+
* Nymph and return it. You can then use this class's constructor and methods,
|
|
122
|
+
* which will use this instance of Nymph.
|
|
123
|
+
*
|
|
124
|
+
* Because this creates a subclass, don't use the class
|
|
125
|
+
* returned from `getEntityClass` to check with `instanceof`.
|
|
126
|
+
*/
|
|
127
|
+
public addEntityClass<T extends EntityConstructor>(entityClass: T): T {
|
|
128
|
+
const nymph = this;
|
|
129
|
+
class NymphEntity extends entityClass {
|
|
130
|
+
static nymph: Nymph = nymph;
|
|
131
|
+
|
|
132
|
+
constructor(...args: any[]) {
|
|
133
|
+
super(...args);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
this.entityClasses[entityClass.class] = NymphEntity;
|
|
137
|
+
return NymphEntity;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the class that uses the specified class name.
|
|
142
|
+
*/
|
|
143
|
+
public getEntityClass(className: string): EntityConstructor {
|
|
144
|
+
if (className in this.entityClasses) {
|
|
145
|
+
return this.entityClasses[className];
|
|
146
|
+
}
|
|
147
|
+
throw new ClassNotAvailableError('Tried to use class: ' + className);
|
|
148
|
+
}
|
|
149
|
+
|
|
133
150
|
/**
|
|
134
151
|
* Get a clone of this instance with duplicate classes and event listeners.
|
|
135
152
|
*
|
|
136
153
|
* @returns A clone of this instance.
|
|
137
154
|
*/
|
|
138
155
|
public clone() {
|
|
139
|
-
const nymph = new Nymph(
|
|
156
|
+
const nymph = new Nymph(
|
|
157
|
+
this.config,
|
|
158
|
+
this.driver.clone(),
|
|
159
|
+
this.tilmeld?.clone()
|
|
160
|
+
);
|
|
140
161
|
for (const name in this.entityClasses) {
|
|
141
162
|
if (name === 'Entity' || (this.entityClasses[name] as any).skipOnClone) {
|
|
142
163
|
continue;
|
|
@@ -190,7 +211,7 @@ export default class Nymph {
|
|
|
190
211
|
const result = this.driver.connect();
|
|
191
212
|
for (let callback of this.connectCallbacks) {
|
|
192
213
|
if (callback) {
|
|
193
|
-
callback(this, result);
|
|
214
|
+
await callback(this, result);
|
|
194
215
|
}
|
|
195
216
|
}
|
|
196
217
|
return await result;
|
|
@@ -205,7 +226,7 @@ export default class Nymph {
|
|
|
205
226
|
const result = this.driver.disconnect();
|
|
206
227
|
for (let callback of this.disconnectCallbacks) {
|
|
207
228
|
if (callback) {
|
|
208
|
-
callback(this, result);
|
|
229
|
+
await callback(this, result);
|
|
209
230
|
}
|
|
210
231
|
}
|
|
211
232
|
return await result;
|
|
@@ -214,10 +235,7 @@ export default class Nymph {
|
|
|
214
235
|
/**
|
|
215
236
|
* Run all the query callbacks on a query.
|
|
216
237
|
*/
|
|
217
|
-
public
|
|
218
|
-
options: Options,
|
|
219
|
-
selectors: FormattedSelector[]
|
|
220
|
-
) {
|
|
238
|
+
public runQueryCallbacks(options: Options, selectors: FormattedSelector[]) {
|
|
221
239
|
for (let callback of this.queryCallbacks) {
|
|
222
240
|
if (callback) {
|
|
223
241
|
callback(this, options, selectors);
|
|
@@ -235,7 +253,7 @@ export default class Nymph {
|
|
|
235
253
|
* Transactions will nest as long as every name is unique. Internally, Nymph
|
|
236
254
|
* uses names prefixed with "nymph-".
|
|
237
255
|
*
|
|
238
|
-
* @returns
|
|
256
|
+
* @returns A new instance of Nymph that should be used for the transaction.
|
|
239
257
|
*/
|
|
240
258
|
public async startTransaction(name: string): Promise<Nymph> {
|
|
241
259
|
return await this.driver.startTransaction(name);
|
|
@@ -244,6 +262,8 @@ export default class Nymph {
|
|
|
244
262
|
/**
|
|
245
263
|
* Commit the named transaction.
|
|
246
264
|
*
|
|
265
|
+
* After this is called, the transaction instance should be discarded.
|
|
266
|
+
*
|
|
247
267
|
* @returns True on success, false on failure.
|
|
248
268
|
*/
|
|
249
269
|
public async commit(name: string): Promise<boolean> {
|
|
@@ -253,6 +273,8 @@ export default class Nymph {
|
|
|
253
273
|
/**
|
|
254
274
|
* Rollback the named transaction.
|
|
255
275
|
*
|
|
276
|
+
* After this is called, the transaction instance should be discarded.
|
|
277
|
+
*
|
|
256
278
|
* @returns True on success, false on failure.
|
|
257
279
|
*/
|
|
258
280
|
public async rollback(name: string): Promise<boolean> {
|
|
@@ -292,13 +314,13 @@ export default class Nymph {
|
|
|
292
314
|
public async newUID(name: string): Promise<number | null> {
|
|
293
315
|
for (let callback of this.beforeNewUIDCallbacks) {
|
|
294
316
|
if (callback) {
|
|
295
|
-
callback(this, name);
|
|
317
|
+
await callback(this, name);
|
|
296
318
|
}
|
|
297
319
|
}
|
|
298
320
|
const result = this.driver.newUID(name);
|
|
299
321
|
for (let callback of this.afterNewUIDCallbacks) {
|
|
300
322
|
if (callback) {
|
|
301
|
-
callback(this, result);
|
|
323
|
+
await callback(this, result);
|
|
302
324
|
}
|
|
303
325
|
}
|
|
304
326
|
return await result;
|
|
@@ -323,13 +345,13 @@ export default class Nymph {
|
|
|
323
345
|
public async setUID(name: string, value: number): Promise<boolean> {
|
|
324
346
|
for (let callback of this.beforeSetUIDCallbacks) {
|
|
325
347
|
if (callback) {
|
|
326
|
-
callback(this, name, value);
|
|
348
|
+
await callback(this, name, value);
|
|
327
349
|
}
|
|
328
350
|
}
|
|
329
351
|
const result = this.driver.setUID(name, value);
|
|
330
352
|
for (let callback of this.afterSetUIDCallbacks) {
|
|
331
353
|
if (callback) {
|
|
332
|
-
callback(this, result);
|
|
354
|
+
await callback(this, result);
|
|
333
355
|
}
|
|
334
356
|
}
|
|
335
357
|
return await result;
|
|
@@ -344,13 +366,13 @@ export default class Nymph {
|
|
|
344
366
|
public async deleteUID(name: string): Promise<boolean> {
|
|
345
367
|
for (let callback of this.beforeDeleteUIDCallbacks) {
|
|
346
368
|
if (callback) {
|
|
347
|
-
callback(this, name);
|
|
369
|
+
await callback(this, name);
|
|
348
370
|
}
|
|
349
371
|
}
|
|
350
372
|
const result = this.driver.deleteUID(name);
|
|
351
373
|
for (let callback of this.afterDeleteUIDCallbacks) {
|
|
352
374
|
if (callback) {
|
|
353
|
-
callback(this, result);
|
|
375
|
+
await callback(this, result);
|
|
354
376
|
}
|
|
355
377
|
}
|
|
356
378
|
return await result;
|
|
@@ -366,13 +388,13 @@ export default class Nymph {
|
|
|
366
388
|
public async renameUID(oldName: string, newName: string): Promise<boolean> {
|
|
367
389
|
for (let callback of this.beforeRenameUIDCallbacks) {
|
|
368
390
|
if (callback) {
|
|
369
|
-
callback(this, oldName, newName);
|
|
391
|
+
await callback(this, oldName, newName);
|
|
370
392
|
}
|
|
371
393
|
}
|
|
372
394
|
const result = this.driver.renameUID(oldName, newName);
|
|
373
395
|
for (let callback of this.afterRenameUIDCallbacks) {
|
|
374
396
|
if (callback) {
|
|
375
|
-
callback(this, result);
|
|
397
|
+
await callback(this, result);
|
|
376
398
|
}
|
|
377
399
|
}
|
|
378
400
|
return await result;
|
|
@@ -392,13 +414,13 @@ export default class Nymph {
|
|
|
392
414
|
public async saveEntity(entity: EntityInterface): Promise<boolean> {
|
|
393
415
|
for (let callback of this.beforeSaveEntityCallbacks) {
|
|
394
416
|
if (callback) {
|
|
395
|
-
callback(this, entity);
|
|
417
|
+
await callback(this, entity);
|
|
396
418
|
}
|
|
397
419
|
}
|
|
398
420
|
const result = this.driver.saveEntity(entity);
|
|
399
421
|
for (let callback of this.afterSaveEntityCallbacks) {
|
|
400
422
|
if (callback) {
|
|
401
|
-
callback(this, result);
|
|
423
|
+
await callback(this, result);
|
|
402
424
|
}
|
|
403
425
|
}
|
|
404
426
|
return await result;
|
|
@@ -581,7 +603,7 @@ export default class Nymph {
|
|
|
581
603
|
): Promise<ReturnType<T['factorySync']>[] | string[] | number> {
|
|
582
604
|
for (let callback of this.beforeGetEntitiesCallbacks) {
|
|
583
605
|
if (callback) {
|
|
584
|
-
callback(this, options, selectors);
|
|
606
|
+
await callback(this, options, selectors);
|
|
585
607
|
}
|
|
586
608
|
}
|
|
587
609
|
return await this.driver.getEntities(options, ...selectors);
|
|
@@ -631,7 +653,7 @@ export default class Nymph {
|
|
|
631
653
|
options.limit = 1;
|
|
632
654
|
for (let callback of this.beforeGetEntityCallbacks) {
|
|
633
655
|
if (callback) {
|
|
634
|
-
callback(this, options, selectors as Selector[]);
|
|
656
|
+
await callback(this, options, selectors as Selector[]);
|
|
635
657
|
}
|
|
636
658
|
}
|
|
637
659
|
const entities = await this.driver.getEntities(
|
|
@@ -656,13 +678,13 @@ export default class Nymph {
|
|
|
656
678
|
public async deleteEntity(entity: EntityInterface): Promise<boolean> {
|
|
657
679
|
for (let callback of this.beforeDeleteEntityCallbacks) {
|
|
658
680
|
if (callback) {
|
|
659
|
-
callback(this, entity);
|
|
681
|
+
await callback(this, entity);
|
|
660
682
|
}
|
|
661
683
|
}
|
|
662
684
|
const result = this.driver.deleteEntity(entity);
|
|
663
685
|
for (let callback of this.afterDeleteEntityCallbacks) {
|
|
664
686
|
if (callback) {
|
|
665
|
-
callback(this, result);
|
|
687
|
+
await callback(this, result);
|
|
666
688
|
}
|
|
667
689
|
}
|
|
668
690
|
return await result;
|
|
@@ -681,13 +703,13 @@ export default class Nymph {
|
|
|
681
703
|
): Promise<boolean> {
|
|
682
704
|
for (let callback of this.beforeDeleteEntityByIDCallbacks) {
|
|
683
705
|
if (callback) {
|
|
684
|
-
callback(this, guid, className);
|
|
706
|
+
await callback(this, guid, className);
|
|
685
707
|
}
|
|
686
708
|
}
|
|
687
709
|
const result = this.driver.deleteEntityByID(guid, className);
|
|
688
710
|
for (let callback of this.afterDeleteEntityByIDCallbacks) {
|
|
689
711
|
if (callback) {
|
|
690
|
-
callback(this, result);
|
|
712
|
+
await callback(this, result);
|
|
691
713
|
}
|
|
692
714
|
}
|
|
693
715
|
return await result;
|
package/src/Nymph.types.ts
CHANGED
|
@@ -24,12 +24,22 @@ export type NymphEventType =
|
|
|
24
24
|
export type NymphConnectCallback = (
|
|
25
25
|
nymph: Nymph,
|
|
26
26
|
result: Promise<boolean>
|
|
27
|
-
) => void
|
|
27
|
+
) => Promise<void>;
|
|
28
28
|
export type NymphDisconnectCallback = (
|
|
29
29
|
nymph: Nymph,
|
|
30
30
|
result: Promise<boolean>
|
|
31
|
-
) => void
|
|
32
|
-
/**
|
|
31
|
+
) => Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* The NymphQueryCallback will be called on both top level and qref queries.
|
|
34
|
+
*
|
|
35
|
+
* This is the only callback that is not asynchronous.
|
|
36
|
+
*
|
|
37
|
+
* This also isn't necessarily run on every "query". It is run before a database
|
|
38
|
+
* query for an entity, but it is not run during PubSub entity change
|
|
39
|
+
* propagation. Therefore, it shouldn't do anything _entity_ specific, instead
|
|
40
|
+
* it should be _query_ specific. For example, throw an error if the user is not
|
|
41
|
+
* permitted to run the query at all.
|
|
42
|
+
*/
|
|
33
43
|
export type NymphQueryCallback = (
|
|
34
44
|
nymph: Nymph,
|
|
35
45
|
options: Options,
|
|
@@ -39,65 +49,71 @@ export type NymphBeforeGetEntityCallback = (
|
|
|
39
49
|
nymph: Nymph,
|
|
40
50
|
options: Options,
|
|
41
51
|
selectors: Selector[]
|
|
42
|
-
) => void
|
|
52
|
+
) => Promise<void>;
|
|
43
53
|
export type NymphBeforeGetEntitiesCallback = (
|
|
44
54
|
nymph: Nymph,
|
|
45
55
|
options: Options,
|
|
46
56
|
selectors: Selector[]
|
|
47
|
-
) => void
|
|
57
|
+
) => Promise<void>;
|
|
48
58
|
export type NymphBeforeSaveEntityCallback = (
|
|
49
59
|
nymph: Nymph,
|
|
50
60
|
entity: EntityInterface
|
|
51
|
-
) => void
|
|
61
|
+
) => Promise<void>;
|
|
52
62
|
export type NymphAfterSaveEntityCallback = (
|
|
53
63
|
nymph: Nymph,
|
|
54
64
|
result: Promise<boolean>
|
|
55
|
-
) => void
|
|
65
|
+
) => Promise<void>;
|
|
56
66
|
export type NymphBeforeDeleteEntityCallback = (
|
|
57
67
|
nymph: Nymph,
|
|
58
68
|
entity: EntityInterface
|
|
59
|
-
) => void
|
|
69
|
+
) => Promise<void>;
|
|
60
70
|
export type NymphAfterDeleteEntityCallback = (
|
|
61
71
|
nymph: Nymph,
|
|
62
72
|
result: Promise<boolean>
|
|
63
|
-
) => void
|
|
73
|
+
) => Promise<void>;
|
|
64
74
|
export type NymphBeforeDeleteEntityByIDCallback = (
|
|
65
75
|
nymph: Nymph,
|
|
66
76
|
guid: string,
|
|
67
77
|
className?: string
|
|
68
|
-
) => void
|
|
78
|
+
) => Promise<void>;
|
|
69
79
|
export type NymphAfterDeleteEntityByIDCallback = (
|
|
70
80
|
nymph: Nymph,
|
|
71
81
|
result: Promise<boolean>
|
|
72
|
-
) => void
|
|
73
|
-
export type NymphBeforeNewUIDCallback = (
|
|
82
|
+
) => Promise<void>;
|
|
83
|
+
export type NymphBeforeNewUIDCallback = (
|
|
84
|
+
nymph: Nymph,
|
|
85
|
+
name: string
|
|
86
|
+
) => Promise<void>;
|
|
74
87
|
export type NymphAfterNewUIDCallback = (
|
|
75
88
|
nymph: Nymph,
|
|
76
89
|
result: Promise<number | null>
|
|
77
|
-
) => void
|
|
90
|
+
) => Promise<void>;
|
|
78
91
|
export type NymphBeforeSetUIDCallback = (
|
|
79
92
|
nymph: Nymph,
|
|
80
93
|
name: string,
|
|
81
94
|
value: number
|
|
82
|
-
) => void
|
|
95
|
+
) => Promise<void>;
|
|
83
96
|
export type NymphAfterSetUIDCallback = (
|
|
84
97
|
nymph: Nymph,
|
|
85
98
|
result: Promise<boolean>
|
|
86
|
-
) => void
|
|
99
|
+
) => Promise<void>;
|
|
87
100
|
export type NymphBeforeRenameUIDCallback = (
|
|
88
101
|
nymph: Nymph,
|
|
89
102
|
oldName: string,
|
|
90
103
|
newName: string
|
|
91
|
-
) => void
|
|
104
|
+
) => Promise<void>;
|
|
92
105
|
export type NymphAfterRenameUIDCallback = (
|
|
93
106
|
nymph: Nymph,
|
|
94
107
|
result: Promise<boolean>
|
|
95
|
-
) => void
|
|
96
|
-
export type NymphBeforeDeleteUIDCallback = (
|
|
108
|
+
) => Promise<void>;
|
|
109
|
+
export type NymphBeforeDeleteUIDCallback = (
|
|
110
|
+
nymph: Nymph,
|
|
111
|
+
name: string
|
|
112
|
+
) => Promise<void>;
|
|
97
113
|
export type NymphAfterDeleteUIDCallback = (
|
|
98
114
|
nymph: Nymph,
|
|
99
115
|
result: Promise<boolean>
|
|
100
|
-
) => void
|
|
116
|
+
) => Promise<void>;
|
|
101
117
|
|
|
102
118
|
export type Options<T extends EntityConstructor = EntityConstructor> = {
|
|
103
119
|
class?: T;
|
|
@@ -54,7 +54,18 @@ export default abstract class NymphDriver {
|
|
|
54
54
|
*/
|
|
55
55
|
private putDataCounter = 0;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* This is used internally by Nymph. Don't call it yourself.
|
|
59
|
+
*
|
|
60
|
+
* @returns A clone of this instance.
|
|
61
|
+
*/
|
|
62
|
+
abstract clone(): NymphDriver;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Connect to the data store.
|
|
66
|
+
*/
|
|
57
67
|
abstract connect(): Promise<boolean>;
|
|
68
|
+
|
|
58
69
|
abstract isConnected(): boolean;
|
|
59
70
|
abstract startTransaction(name: string): Promise<Nymph>;
|
|
60
71
|
abstract commit(name: string): Promise<boolean>;
|
|
@@ -66,7 +77,12 @@ export default abstract class NymphDriver {
|
|
|
66
77
|
): Promise<boolean>;
|
|
67
78
|
abstract deleteEntityByID(guid: string, className?: string): Promise<boolean>;
|
|
68
79
|
abstract deleteUID(name: string): Promise<boolean>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Disconnect from the data store.
|
|
83
|
+
*/
|
|
69
84
|
abstract disconnect(): Promise<boolean>;
|
|
85
|
+
|
|
70
86
|
protected abstract exportEntities(
|
|
71
87
|
writeLine: (line: string) => void
|
|
72
88
|
): Promise<void>;
|
|
@@ -283,7 +299,7 @@ export default abstract class NymphDriver {
|
|
|
283
299
|
guid: string | null = null,
|
|
284
300
|
tags: string[] | null = null
|
|
285
301
|
) {
|
|
286
|
-
const formattedSelectors = this.formatSelectors(selectors);
|
|
302
|
+
const formattedSelectors = this.formatSelectors(selectors).selectors;
|
|
287
303
|
|
|
288
304
|
for (const curSelector of formattedSelectors) {
|
|
289
305
|
const type = curSelector.type;
|
|
@@ -575,8 +591,12 @@ export default abstract class NymphDriver {
|
|
|
575
591
|
public formatSelectors(
|
|
576
592
|
selectors: Selector[],
|
|
577
593
|
options: Options = {}
|
|
578
|
-
):
|
|
594
|
+
): {
|
|
595
|
+
selectors: FormattedSelector[];
|
|
596
|
+
qrefs: [Options, ...FormattedSelector[]][];
|
|
597
|
+
} {
|
|
579
598
|
const newSelectors: FormattedSelector[] = [];
|
|
599
|
+
const qrefs: [Options, ...FormattedSelector[]][] = [];
|
|
580
600
|
|
|
581
601
|
for (const curSelector of selectors) {
|
|
582
602
|
const newSelector: FormattedSelector = {
|
|
@@ -615,13 +635,18 @@ export default abstract class NymphDriver {
|
|
|
615
635
|
source: options.source,
|
|
616
636
|
};
|
|
617
637
|
const newSelectors = this.formatSelectors(qrefSelectors, options);
|
|
618
|
-
|
|
619
|
-
|
|
638
|
+
qrefs.push(
|
|
639
|
+
[newOptions, ...newSelectors.selectors],
|
|
640
|
+
...newSelectors.qrefs
|
|
641
|
+
);
|
|
642
|
+
formatArr[i] = [name, [newOptions, ...newSelectors.selectors]];
|
|
620
643
|
}
|
|
621
644
|
newSelector[key] = formatArr;
|
|
622
645
|
} else if (key === 'selector' || key === '!selector') {
|
|
623
646
|
const tmpArr = (Array.isArray(value) ? value : [value]) as Selector[];
|
|
624
|
-
|
|
647
|
+
const newSelectors = this.formatSelectors(tmpArr, options);
|
|
648
|
+
newSelector[key] = newSelectors.selectors;
|
|
649
|
+
qrefs.push(...newSelectors.qrefs);
|
|
625
650
|
} else if (!Array.isArray(value)) {
|
|
626
651
|
// @ts-ignore: ts doesn't know what value is here.
|
|
627
652
|
newSelector[key] = [[value]];
|
|
@@ -655,7 +680,7 @@ export default abstract class NymphDriver {
|
|
|
655
680
|
newSelectors.push(newSelector);
|
|
656
681
|
}
|
|
657
682
|
|
|
658
|
-
return newSelectors;
|
|
683
|
+
return { selectors: newSelectors, qrefs };
|
|
659
684
|
}
|
|
660
685
|
|
|
661
686
|
protected iterateSelectorsForQuery(
|
|
@@ -774,7 +799,7 @@ export default abstract class NymphDriver {
|
|
|
774
799
|
name: string;
|
|
775
800
|
svalue: string;
|
|
776
801
|
}
|
|
777
|
-
): { result: any; process: () => number };
|
|
802
|
+
): { result: any; process: () => number | Error };
|
|
778
803
|
protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
779
804
|
options: Options<T> & { return: 'guid' },
|
|
780
805
|
selectors: Selector[],
|
|
@@ -798,7 +823,7 @@ export default abstract class NymphDriver {
|
|
|
798
823
|
name: string;
|
|
799
824
|
svalue: string;
|
|
800
825
|
}
|
|
801
|
-
): { result: any; process: () => string[] };
|
|
826
|
+
): { result: any; process: () => string[] | Error };
|
|
802
827
|
protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
803
828
|
options: Options<T>,
|
|
804
829
|
selectors: Selector[],
|
|
@@ -822,7 +847,7 @@ export default abstract class NymphDriver {
|
|
|
822
847
|
name: string;
|
|
823
848
|
svalue: string;
|
|
824
849
|
}
|
|
825
|
-
): { result: any; process: () => ReturnType<T['factorySync']>[] };
|
|
850
|
+
): { result: any; process: () => ReturnType<T['factorySync']>[] | Error };
|
|
826
851
|
protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
827
852
|
options: Options<T>,
|
|
828
853
|
selectors: Selector[],
|
|
@@ -848,7 +873,7 @@ export default abstract class NymphDriver {
|
|
|
848
873
|
}
|
|
849
874
|
): {
|
|
850
875
|
result: any;
|
|
851
|
-
process: () => ReturnType<T['factorySync']>[] | string[] | number;
|
|
876
|
+
process: () => ReturnType<T['factorySync']>[] | string[] | number | Error;
|
|
852
877
|
} {
|
|
853
878
|
if (!this.isConnected()) {
|
|
854
879
|
throw new UnableToConnectError('not connected to DB');
|
|
@@ -918,78 +943,95 @@ export default abstract class NymphDriver {
|
|
|
918
943
|
}
|
|
919
944
|
}
|
|
920
945
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
946
|
+
try {
|
|
947
|
+
const formattedSelectors = this.formatSelectors(selectors, options);
|
|
948
|
+
this.nymph.runQueryCallbacks(options, formattedSelectors.selectors);
|
|
949
|
+
for (let qref of formattedSelectors.qrefs) {
|
|
950
|
+
const [options, ...selectors] = qref;
|
|
951
|
+
this.nymph.runQueryCallbacks(options, selectors);
|
|
952
|
+
}
|
|
953
|
+
const { result } = performQueryCallback(
|
|
954
|
+
options,
|
|
955
|
+
formattedSelectors.selectors,
|
|
956
|
+
etype
|
|
957
|
+
);
|
|
924
958
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
row = rowFetchCallback();
|
|
933
|
-
}
|
|
934
|
-
} else if (options.return === 'guid') {
|
|
935
|
-
while (row != null) {
|
|
936
|
-
(entities as string[]).push(getGUIDCallback(row));
|
|
937
|
-
row = rowFetchCallback();
|
|
938
|
-
}
|
|
939
|
-
} else {
|
|
940
|
-
while (row != null) {
|
|
941
|
-
const guid = getGUIDCallback(row);
|
|
942
|
-
const tagsAndDates = getTagsAndDatesCallback(row);
|
|
943
|
-
const tags = tagsAndDates.tags;
|
|
944
|
-
const cdate = tagsAndDates.cdate;
|
|
945
|
-
const mdate = tagsAndDates.mdate;
|
|
946
|
-
let dataNameAndSValue = getDataNameAndSValueCallback(row);
|
|
947
|
-
// Data.
|
|
948
|
-
const data: EntityData = {};
|
|
949
|
-
// Serialized data.
|
|
950
|
-
const sdata: SerializedEntityData = {};
|
|
951
|
-
if (dataNameAndSValue.name !== '') {
|
|
952
|
-
// This do will keep going and adding the data until the
|
|
953
|
-
// next entity is reached. $row will end on the next entity.
|
|
954
|
-
do {
|
|
955
|
-
dataNameAndSValue = getDataNameAndSValueCallback(row);
|
|
956
|
-
sdata[dataNameAndSValue.name] = dataNameAndSValue.svalue;
|
|
957
|
-
row = rowFetchCallback();
|
|
958
|
-
} while (row != null && getGUIDCallback(row) === guid);
|
|
959
|
-
} else {
|
|
960
|
-
// Make sure that $row is incremented :)
|
|
959
|
+
return {
|
|
960
|
+
result,
|
|
961
|
+
process: () => {
|
|
962
|
+
let row = rowFetchCallback();
|
|
963
|
+
if (options.return === 'count') {
|
|
964
|
+
while (row != null) {
|
|
965
|
+
count += getCountCallback(row);
|
|
961
966
|
row = rowFetchCallback();
|
|
962
967
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
if (options.skipAc != null) {
|
|
968
|
-
entity.$useSkipAc(!!options.skipAc);
|
|
969
|
-
}
|
|
970
|
-
entity.guid = guid;
|
|
971
|
-
entity.cdate = cdate;
|
|
972
|
-
entity.mdate = mdate;
|
|
973
|
-
entity.tags = tags;
|
|
974
|
-
this.putDataCounter++;
|
|
975
|
-
if (this.putDataCounter == 100) {
|
|
976
|
-
throw new Error('Infinite loop detected in Entity loading.');
|
|
968
|
+
} else if (options.return === 'guid') {
|
|
969
|
+
while (row != null) {
|
|
970
|
+
(entities as string[]).push(getGUIDCallback(row));
|
|
971
|
+
row = rowFetchCallback();
|
|
977
972
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
973
|
+
} else {
|
|
974
|
+
while (row != null) {
|
|
975
|
+
const guid = getGUIDCallback(row);
|
|
976
|
+
const tagsAndDates = getTagsAndDatesCallback(row);
|
|
977
|
+
const tags = tagsAndDates.tags;
|
|
978
|
+
const cdate = tagsAndDates.cdate;
|
|
979
|
+
const mdate = tagsAndDates.mdate;
|
|
980
|
+
let dataNameAndSValue = getDataNameAndSValueCallback(row);
|
|
981
|
+
// Data.
|
|
982
|
+
const data: EntityData = {};
|
|
983
|
+
// Serialized data.
|
|
984
|
+
const sdata: SerializedEntityData = {};
|
|
985
|
+
if (dataNameAndSValue.name !== '') {
|
|
986
|
+
// This do will keep going and adding the data until the
|
|
987
|
+
// next entity is reached. $row will end on the next entity.
|
|
988
|
+
do {
|
|
989
|
+
dataNameAndSValue = getDataNameAndSValueCallback(row);
|
|
990
|
+
sdata[dataNameAndSValue.name] = dataNameAndSValue.svalue;
|
|
991
|
+
row = rowFetchCallback();
|
|
992
|
+
} while (row != null && getGUIDCallback(row) === guid);
|
|
993
|
+
} else {
|
|
994
|
+
// Make sure that $row is incremented :)
|
|
995
|
+
row = rowFetchCallback();
|
|
996
|
+
}
|
|
997
|
+
const entity = EntityClass.factorySync() as ReturnType<
|
|
998
|
+
T['factorySync']
|
|
999
|
+
>;
|
|
1000
|
+
entity.$nymph = this.nymph;
|
|
1001
|
+
if (options.skipAc != null) {
|
|
1002
|
+
entity.$useSkipAc(!!options.skipAc);
|
|
1003
|
+
}
|
|
1004
|
+
entity.guid = guid;
|
|
1005
|
+
entity.cdate = cdate;
|
|
1006
|
+
entity.mdate = mdate;
|
|
1007
|
+
entity.tags = tags;
|
|
1008
|
+
this.putDataCounter++;
|
|
1009
|
+
if (this.putDataCounter == 100) {
|
|
1010
|
+
throw new Error('Infinite loop detected in Entity loading.');
|
|
1011
|
+
}
|
|
1012
|
+
entity.$putData(data, sdata);
|
|
1013
|
+
this.putDataCounter--;
|
|
1014
|
+
if (this.nymph.config.cache) {
|
|
1015
|
+
this.pushCache(guid, cdate, mdate, tags, data, sdata);
|
|
1016
|
+
}
|
|
1017
|
+
// @ts-ignore: ts doesn't know the return type here.
|
|
1018
|
+
entities.push(entity);
|
|
982
1019
|
}
|
|
983
|
-
// @ts-ignore: ts doesn't know the return type here.
|
|
984
|
-
entities.push(entity);
|
|
985
1020
|
}
|
|
986
|
-
}
|
|
987
1021
|
|
|
988
|
-
|
|
1022
|
+
freeResultCallback();
|
|
989
1023
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1024
|
+
return options.return === 'count' ? count : entities;
|
|
1025
|
+
},
|
|
1026
|
+
};
|
|
1027
|
+
} catch (e: any) {
|
|
1028
|
+
return {
|
|
1029
|
+
result: Promise.resolve(e),
|
|
1030
|
+
process: () => {
|
|
1031
|
+
return e;
|
|
1032
|
+
},
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
993
1035
|
}
|
|
994
1036
|
|
|
995
1037
|
protected async saveEntityRowLike(
|