@nymphjs/nymph 1.0.0-beta.7 → 1.0.0-beta.71
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 +324 -0
- package/README.md +13 -21
- package/dist/Entity.d.ts +269 -7
- package/dist/Entity.js +491 -105
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +39 -17
- package/dist/Entity.test.js.map +1 -1
- package/dist/Entity.types.d.ts +225 -19
- package/dist/Nymph.d.ts +423 -11
- package/dist/Nymph.js +685 -176
- package/dist/Nymph.js.map +1 -1
- package/dist/Nymph.types.d.ts +31 -7
- package/dist/Nymph.types.js +2 -1
- package/dist/Nymph.types.js.map +1 -1
- package/dist/conf/d.d.ts +26 -0
- package/dist/conf/defaults.js +22 -0
- package/dist/conf/defaults.js.map +1 -1
- package/dist/driver/NymphDriver.d.ts +129 -38
- package/dist/driver/NymphDriver.js +264 -131
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/testArtifacts.d.ts +1 -1
- package/dist/driver/testArtifacts.js +336 -42
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/errors/EntityInvalidDataError.d.ts +6 -0
- package/dist/errors/EntityInvalidDataError.js +7 -1
- package/dist/errors/EntityInvalidDataError.js.map +1 -1
- package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
- package/dist/errors/EntityUniqueConstraintError.js +11 -0
- package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
- 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/QueryFailedError.js +1 -0
- package/dist/errors/QueryFailedError.js.map +1 -1
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +2 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/testArtifacts.d.ts +17 -5
- package/dist/testArtifacts.js +31 -27
- package/dist/testArtifacts.js.map +1 -1
- package/dist/testMocks.d.ts +15 -10
- package/dist/testMocks.js +37 -13
- package/dist/testMocks.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +21 -5
- package/dist/utils.js.map +1 -1
- package/package.json +16 -14
- package/src/Entity.test.ts +32 -11
- package/src/Entity.ts +423 -134
- package/src/Entity.types.ts +32 -66
- package/src/Nymph.ts +618 -195
- package/src/Nymph.types.ts +97 -26
- package/src/conf/d.ts +8 -0
- package/src/conf/defaults.ts +24 -0
- package/src/driver/NymphDriver.ts +281 -311
- package/src/driver/testArtifacts.ts +384 -173
- package/src/errors/EntityUniqueConstraintError.ts +6 -0
- package/src/errors/InvalidStateError.ts +6 -0
- package/src/errors/index.ts +4 -0
- package/src/nymphJoiProps.ts +2 -2
- package/src/testArtifacts.ts +18 -19
- package/src/testMocks.ts +64 -32
- package/src/utils.ts +22 -8
- package/tsconfig.json +3 -3
- package/typedoc.json +4 -0
|
@@ -5,7 +5,9 @@ import strtotime from 'locutus/php/datetime/strtotime';
|
|
|
5
5
|
import { guid } from '@nymphjs/guid';
|
|
6
6
|
|
|
7
7
|
import type Nymph from '../Nymph';
|
|
8
|
-
import {
|
|
8
|
+
import type { Selector, Options, FormattedSelector } from '../Nymph.types';
|
|
9
|
+
import Entity, { type EntityInstanceType } from '../Entity';
|
|
10
|
+
import type {
|
|
9
11
|
EntityConstructor,
|
|
10
12
|
EntityData,
|
|
11
13
|
EntityInterface,
|
|
@@ -13,7 +15,6 @@ import {
|
|
|
13
15
|
SerializedEntityData,
|
|
14
16
|
} from '../Entity.types';
|
|
15
17
|
import { InvalidParametersError, UnableToConnectError } from '../errors';
|
|
16
|
-
import { Selector, Options, FormattedSelector } from '../Nymph.types';
|
|
17
18
|
import { xor } from '../utils';
|
|
18
19
|
|
|
19
20
|
// from: https://stackoverflow.com/a/6969486/664915
|
|
@@ -28,7 +29,7 @@ export default abstract class NymphDriver {
|
|
|
28
29
|
protected nymph: Nymph = new Proxy({} as Nymph, {
|
|
29
30
|
get() {
|
|
30
31
|
throw new Error(
|
|
31
|
-
'Attempted access of Nymph instance before driver initialization!'
|
|
32
|
+
'Attempted access of Nymph instance before driver initialization!',
|
|
32
33
|
);
|
|
33
34
|
},
|
|
34
35
|
});
|
|
@@ -67,13 +68,14 @@ export default abstract class NymphDriver {
|
|
|
67
68
|
abstract connect(): Promise<boolean>;
|
|
68
69
|
|
|
69
70
|
abstract isConnected(): boolean;
|
|
71
|
+
protected abstract internalTransaction(name: string): Promise<any>;
|
|
70
72
|
abstract startTransaction(name: string): Promise<Nymph>;
|
|
71
73
|
abstract commit(name: string): Promise<boolean>;
|
|
72
74
|
abstract rollback(name: string): Promise<boolean>;
|
|
73
75
|
abstract inTransaction(): Promise<boolean>;
|
|
74
76
|
abstract deleteEntityByID(
|
|
75
77
|
guid: string,
|
|
76
|
-
classConstructor: EntityConstructor
|
|
78
|
+
classConstructor: EntityConstructor,
|
|
77
79
|
): Promise<boolean>;
|
|
78
80
|
abstract deleteEntityByID(guid: string, className?: string): Promise<boolean>;
|
|
79
81
|
abstract deleteUID(name: string): Promise<boolean>;
|
|
@@ -83,9 +85,11 @@ export default abstract class NymphDriver {
|
|
|
83
85
|
*/
|
|
84
86
|
abstract disconnect(): Promise<boolean>;
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
abstract exportDataIterator(): AsyncGenerator<
|
|
89
|
+
{ type: 'comment' | 'uid' | 'entity'; content: string },
|
|
90
|
+
void,
|
|
91
|
+
undefined | false
|
|
92
|
+
>;
|
|
89
93
|
abstract getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
90
94
|
options: Options<T> & { return: 'count' },
|
|
91
95
|
...selectors: Selector[]
|
|
@@ -97,37 +101,21 @@ export default abstract class NymphDriver {
|
|
|
97
101
|
abstract getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
98
102
|
options?: Options<T>,
|
|
99
103
|
...selectors: Selector[]
|
|
100
|
-
): Promise<
|
|
104
|
+
): Promise<EntityInstanceType<T>[]>;
|
|
101
105
|
abstract getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
102
106
|
options?: Options<T>,
|
|
103
107
|
...selectors: Selector[]
|
|
104
|
-
): Promise<
|
|
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;
|
|
108
|
+
): Promise<EntityInstanceType<T>[] | string[] | number>;
|
|
129
109
|
abstract getUID(name: string): Promise<number | null>;
|
|
130
|
-
abstract
|
|
110
|
+
abstract importEntity(entity: {
|
|
111
|
+
guid: string;
|
|
112
|
+
cdate: number;
|
|
113
|
+
mdate: number;
|
|
114
|
+
tags: string[];
|
|
115
|
+
sdata: SerializedEntityData;
|
|
116
|
+
etype: string;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
abstract importUID(uid: { name: string; value: number }): Promise<void>;
|
|
131
119
|
abstract newUID(name: string): Promise<number | null>;
|
|
132
120
|
abstract renameUID(oldName: string, newName: string): Promise<boolean>;
|
|
133
121
|
abstract saveEntity(entity: EntityInterface): Promise<boolean>;
|
|
@@ -147,7 +135,7 @@ export default abstract class NymphDriver {
|
|
|
147
135
|
protected posixRegexMatch(
|
|
148
136
|
pattern: string,
|
|
149
137
|
subject: string,
|
|
150
|
-
caseInsensitive = false
|
|
138
|
+
caseInsensitive = false,
|
|
151
139
|
) {
|
|
152
140
|
const posixClasses = [
|
|
153
141
|
// '[[:<:]]',
|
|
@@ -204,9 +192,9 @@ export default abstract class NymphDriver {
|
|
|
204
192
|
if (!fhandle) {
|
|
205
193
|
throw new InvalidParametersError('Provided filename is not writeable.');
|
|
206
194
|
}
|
|
207
|
-
await this.
|
|
208
|
-
fs.writeSync(fhandle,
|
|
209
|
-
}
|
|
195
|
+
for await (let entry of this.exportDataIterator()) {
|
|
196
|
+
fs.writeSync(fhandle, entry.content);
|
|
197
|
+
}
|
|
210
198
|
fs.closeSync(fhandle);
|
|
211
199
|
} catch (e: any) {
|
|
212
200
|
return false;
|
|
@@ -215,130 +203,155 @@ export default abstract class NymphDriver {
|
|
|
215
203
|
}
|
|
216
204
|
|
|
217
205
|
public async exportPrint() {
|
|
218
|
-
await this.
|
|
219
|
-
console.log(
|
|
220
|
-
}
|
|
206
|
+
for await (let entry of this.exportDataIterator()) {
|
|
207
|
+
console.log(entry.content);
|
|
208
|
+
}
|
|
221
209
|
return true;
|
|
222
210
|
}
|
|
223
211
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
guid: string,
|
|
228
|
-
tags: string[],
|
|
229
|
-
sdata: SerializedEntityData,
|
|
230
|
-
etype: string
|
|
231
|
-
) => Promise<void>,
|
|
232
|
-
saveUIDCallback: (name: string, value: number) => Promise<void>,
|
|
233
|
-
startTransactionCallback: (() => Promise<void>) | null = null,
|
|
234
|
-
commitTransactionCallback: (() => Promise<void>) | null = null
|
|
212
|
+
public async importDataIterator(
|
|
213
|
+
lines: Iterable<string>,
|
|
214
|
+
transaction?: boolean,
|
|
235
215
|
) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
throw new InvalidParametersError('Provided filename is unreadable.');
|
|
216
|
+
const first = lines[Symbol.iterator]().next();
|
|
217
|
+
|
|
218
|
+
if (first.done || first.value !== '#nex2') {
|
|
219
|
+
throw new Error('Tried to import a file that is not a NEX v2 file.');
|
|
241
220
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
let tags: string[] = [];
|
|
246
|
-
let etype = '__undefined';
|
|
247
|
-
if (startTransactionCallback) {
|
|
248
|
-
await startTransactionCallback();
|
|
221
|
+
|
|
222
|
+
if (transaction) {
|
|
223
|
+
await this.internalTransaction('nymph-import');
|
|
249
224
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
/^\s
|
|
257
|
-
|
|
258
|
-
const propMatch = text.match(/^\s*([^=]+)\s*=\s*(.*\S)\s*$/);
|
|
259
|
-
const uidMatch = text.match(/^\s*<([^>]+)>\[(\d+)\]\s*$/);
|
|
260
|
-
if (uidMatch) {
|
|
261
|
-
// Add the UID.
|
|
262
|
-
await saveUIDCallback(uidMatch[1], Number(uidMatch[2]));
|
|
263
|
-
} else if (entityMatch) {
|
|
264
|
-
// Save the current entity.
|
|
265
|
-
if (guid) {
|
|
266
|
-
await saveEntityCallback(guid, tags, sdata, etype);
|
|
267
|
-
guid = null;
|
|
268
|
-
tags = [];
|
|
269
|
-
sdata = {};
|
|
270
|
-
etype = '__undefined';
|
|
225
|
+
try {
|
|
226
|
+
let guid: string | null = null;
|
|
227
|
+
let sdata: SerializedEntityData = {};
|
|
228
|
+
let tags: string[] = [];
|
|
229
|
+
let etype = '__undefined';
|
|
230
|
+
for (let line of lines) {
|
|
231
|
+
if (line.match(/^\s*#/)) {
|
|
232
|
+
continue;
|
|
271
233
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
234
|
+
const entityMatch = line.match(
|
|
235
|
+
/^\s*{([0-9A-Fa-f]+)}<([-\w_]+)>\[([^\]]*)\]\s*$/,
|
|
236
|
+
);
|
|
237
|
+
const propMatch = line.match(/^\s*([^=]+)\s*=\s*(.*\S)\s*$/);
|
|
238
|
+
const uidMatch = line.match(/^\s*<([^>]+)>\[(\d+)\]\s*$/);
|
|
239
|
+
if (uidMatch) {
|
|
240
|
+
// Add the UID.
|
|
241
|
+
await this.importUID({
|
|
242
|
+
name: uidMatch[1],
|
|
243
|
+
value: Number(uidMatch[2]),
|
|
244
|
+
});
|
|
245
|
+
} else if (entityMatch) {
|
|
246
|
+
// Save the current entity.
|
|
247
|
+
if (guid) {
|
|
248
|
+
const cdate = Number(JSON.parse(sdata.cdate));
|
|
249
|
+
delete sdata.cdate;
|
|
250
|
+
const mdate = Number(JSON.parse(sdata.mdate));
|
|
251
|
+
delete sdata.mdate;
|
|
252
|
+
await this.importEntity({ guid, cdate, mdate, tags, sdata, etype });
|
|
253
|
+
guid = null;
|
|
254
|
+
tags = [];
|
|
255
|
+
sdata = {};
|
|
256
|
+
etype = '__undefined';
|
|
257
|
+
}
|
|
258
|
+
// Record the new entity's info.
|
|
259
|
+
guid = entityMatch[1];
|
|
260
|
+
etype = entityMatch[2];
|
|
261
|
+
tags = entityMatch[3].split(',');
|
|
262
|
+
} else if (propMatch) {
|
|
263
|
+
// Add the variable to the new entity.
|
|
264
|
+
if (guid) {
|
|
265
|
+
sdata[propMatch[1]] = propMatch[2];
|
|
266
|
+
}
|
|
280
267
|
}
|
|
268
|
+
// Clear the entity cache.
|
|
269
|
+
this.entityCache = {};
|
|
281
270
|
}
|
|
282
|
-
//
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
271
|
+
// Save the last entity.
|
|
272
|
+
if (guid) {
|
|
273
|
+
const cdate = Number(JSON.parse(sdata.cdate));
|
|
274
|
+
delete sdata.cdate;
|
|
275
|
+
const mdate = Number(JSON.parse(sdata.mdate));
|
|
276
|
+
delete sdata.mdate;
|
|
277
|
+
await this.importEntity({ guid, cdate, mdate, tags, sdata, etype });
|
|
278
|
+
}
|
|
279
|
+
if (transaction) {
|
|
280
|
+
await this.commit('nymph-import');
|
|
281
|
+
}
|
|
282
|
+
} catch (e: any) {
|
|
283
|
+
await this.rollback('nymph-import');
|
|
284
|
+
throw e;
|
|
291
285
|
}
|
|
292
286
|
return true;
|
|
293
287
|
}
|
|
294
288
|
|
|
289
|
+
public async importData(text: string, transaction?: boolean) {
|
|
290
|
+
return await this.importDataIterator(text.split('\n'), transaction);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public async import(filename: string, transaction?: boolean) {
|
|
294
|
+
let rl: ReadLines;
|
|
295
|
+
try {
|
|
296
|
+
rl = new ReadLines(filename);
|
|
297
|
+
} catch (e: any) {
|
|
298
|
+
throw new InvalidParametersError('Provided filename is unreadable.');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const lines = {
|
|
302
|
+
*[Symbol.iterator]() {
|
|
303
|
+
let line: false | Buffer;
|
|
304
|
+
while ((line = rl.next())) {
|
|
305
|
+
yield line.toString('utf8');
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
return await this.importDataIterator(lines, transaction);
|
|
311
|
+
}
|
|
312
|
+
|
|
295
313
|
public checkData(
|
|
296
314
|
data: EntityData,
|
|
297
315
|
sdata: SerializedEntityData,
|
|
298
316
|
selectors: Selector[],
|
|
299
317
|
guid: string | null = null,
|
|
300
|
-
tags: string[] | null = null
|
|
318
|
+
tags: string[] | null = null,
|
|
301
319
|
) {
|
|
302
|
-
|
|
320
|
+
try {
|
|
321
|
+
const formattedSelectors = this.formatSelectors(selectors).selectors;
|
|
303
322
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
323
|
+
for (const curSelector of formattedSelectors) {
|
|
324
|
+
const type = curSelector.type;
|
|
325
|
+
const typeIsNot = type === '!&' || type === '!|';
|
|
326
|
+
const typeIsOr = type === '|' || type === '!|';
|
|
327
|
+
let pass = !typeIsOr;
|
|
328
|
+
for (const k in curSelector) {
|
|
329
|
+
const key = k as keyof Selector;
|
|
330
|
+
const value = curSelector[key];
|
|
312
331
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
332
|
+
if (key === 'type' || value == null) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
316
335
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
xor(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
throw new Error("Can't use checkData on qref clauses.");
|
|
336
|
+
const clauseNot = key.substring(0, 1) === '!';
|
|
337
|
+
if (key === 'selector' || key === '!selector') {
|
|
338
|
+
const tmpArr = (
|
|
339
|
+
Array.isArray(value) ? value : [value]
|
|
340
|
+
) as Selector[];
|
|
341
|
+
pass = xor(
|
|
342
|
+
this.checkData(data, sdata, tmpArr, guid, tags),
|
|
343
|
+
xor(typeIsNot, clauseNot),
|
|
344
|
+
);
|
|
327
345
|
} else {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if
|
|
332
|
-
|
|
333
|
-
|
|
346
|
+
if (key === 'qref' || key === '!qref') {
|
|
347
|
+
throw new Error("Can't use checkData on qref clauses.");
|
|
348
|
+
} else {
|
|
349
|
+
// Check if it doesn't pass any for &, check if it passes any for |.
|
|
350
|
+
for (const curValue of value) {
|
|
351
|
+
if (curValue == null) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
334
354
|
|
|
335
|
-
if (
|
|
336
|
-
((key === 'guid' || key === '!guid') && guid == null) ||
|
|
337
|
-
((key === 'tag' || key === '!tag') && tags == null)
|
|
338
|
-
) {
|
|
339
|
-
// Skip because it has already been checked (by the query).
|
|
340
|
-
pass = true;
|
|
341
|
-
} else {
|
|
342
355
|
const propName = (curValue as string[])[0];
|
|
343
356
|
|
|
344
357
|
// Unserialize the data for this variable.
|
|
@@ -356,7 +369,7 @@ export default abstract class NymphDriver {
|
|
|
356
369
|
case '!tag':
|
|
357
370
|
pass = xor(
|
|
358
371
|
(tags ?? []).indexOf(propName) !== -1,
|
|
359
|
-
xor(typeIsNot, clauseNot)
|
|
372
|
+
xor(typeIsNot, clauseNot),
|
|
360
373
|
);
|
|
361
374
|
break;
|
|
362
375
|
case 'defined':
|
|
@@ -367,7 +380,7 @@ export default abstract class NymphDriver {
|
|
|
367
380
|
case '!truthy':
|
|
368
381
|
pass = xor(
|
|
369
382
|
propName in data && data[propName],
|
|
370
|
-
xor(typeIsNot, clauseNot)
|
|
383
|
+
xor(typeIsNot, clauseNot),
|
|
371
384
|
);
|
|
372
385
|
break;
|
|
373
386
|
case 'ref':
|
|
@@ -377,9 +390,9 @@ export default abstract class NymphDriver {
|
|
|
377
390
|
propName in data &&
|
|
378
391
|
this.entityReferenceSearch(
|
|
379
392
|
data[propName],
|
|
380
|
-
testRefValue
|
|
393
|
+
testRefValue,
|
|
381
394
|
),
|
|
382
|
-
xor(typeIsNot, clauseNot)
|
|
395
|
+
xor(typeIsNot, clauseNot),
|
|
383
396
|
);
|
|
384
397
|
break;
|
|
385
398
|
case 'equal':
|
|
@@ -391,7 +404,7 @@ export default abstract class NymphDriver {
|
|
|
391
404
|
propName in data &&
|
|
392
405
|
JSON.stringify(data[propName]) ===
|
|
393
406
|
JSON.stringify(testEqualValue),
|
|
394
|
-
xor(typeIsNot, clauseNot)
|
|
407
|
+
xor(typeIsNot, clauseNot),
|
|
395
408
|
);
|
|
396
409
|
break;
|
|
397
410
|
case 'contain':
|
|
@@ -402,9 +415,9 @@ export default abstract class NymphDriver {
|
|
|
402
415
|
pass = xor(
|
|
403
416
|
propName in data &&
|
|
404
417
|
JSON.stringify(data[propName]).indexOf(
|
|
405
|
-
JSON.stringify(testContainValue)
|
|
418
|
+
JSON.stringify(testContainValue),
|
|
406
419
|
) !== -1,
|
|
407
|
-
xor(typeIsNot, clauseNot)
|
|
420
|
+
xor(typeIsNot, clauseNot),
|
|
408
421
|
);
|
|
409
422
|
break;
|
|
410
423
|
case 'like':
|
|
@@ -419,9 +432,9 @@ export default abstract class NymphDriver {
|
|
|
419
432
|
escapeRegExp(testLikeValue)
|
|
420
433
|
.replace('%', () => '.*')
|
|
421
434
|
.replace('_', () => '.') +
|
|
422
|
-
'$'
|
|
435
|
+
'$',
|
|
423
436
|
).test(data[propName]),
|
|
424
|
-
xor(typeIsNot, clauseNot)
|
|
437
|
+
xor(typeIsNot, clauseNot),
|
|
425
438
|
);
|
|
426
439
|
break;
|
|
427
440
|
case 'match':
|
|
@@ -433,7 +446,7 @@ export default abstract class NymphDriver {
|
|
|
433
446
|
pass = xor(
|
|
434
447
|
propName in data &&
|
|
435
448
|
this.posixRegexMatch(testMatchValue, data[propName]),
|
|
436
|
-
xor(typeIsNot, clauseNot)
|
|
449
|
+
xor(typeIsNot, clauseNot),
|
|
437
450
|
);
|
|
438
451
|
break;
|
|
439
452
|
case 'imatch':
|
|
@@ -447,9 +460,9 @@ export default abstract class NymphDriver {
|
|
|
447
460
|
this.posixRegexMatch(
|
|
448
461
|
testIMatchValue,
|
|
449
462
|
data[propName],
|
|
450
|
-
true
|
|
463
|
+
true,
|
|
451
464
|
),
|
|
452
|
-
xor(typeIsNot, clauseNot)
|
|
465
|
+
xor(typeIsNot, clauseNot),
|
|
453
466
|
);
|
|
454
467
|
break;
|
|
455
468
|
case 'gt':
|
|
@@ -459,7 +472,7 @@ export default abstract class NymphDriver {
|
|
|
459
472
|
)[1] as number;
|
|
460
473
|
pass = xor(
|
|
461
474
|
propName in data && data[propName] > testGTValue,
|
|
462
|
-
xor(typeIsNot, clauseNot)
|
|
475
|
+
xor(typeIsNot, clauseNot),
|
|
463
476
|
);
|
|
464
477
|
break;
|
|
465
478
|
case 'gte':
|
|
@@ -469,7 +482,7 @@ export default abstract class NymphDriver {
|
|
|
469
482
|
)[1] as number;
|
|
470
483
|
pass = xor(
|
|
471
484
|
propName in data && data[propName] >= testGTEValue,
|
|
472
|
-
xor(typeIsNot, clauseNot)
|
|
485
|
+
xor(typeIsNot, clauseNot),
|
|
473
486
|
);
|
|
474
487
|
break;
|
|
475
488
|
case 'lt':
|
|
@@ -479,7 +492,7 @@ export default abstract class NymphDriver {
|
|
|
479
492
|
)[1] as number;
|
|
480
493
|
pass = xor(
|
|
481
494
|
propName in data && data[propName] < testLTValue,
|
|
482
|
-
xor(typeIsNot, clauseNot)
|
|
495
|
+
xor(typeIsNot, clauseNot),
|
|
483
496
|
);
|
|
484
497
|
break;
|
|
485
498
|
case 'lte':
|
|
@@ -489,26 +502,33 @@ export default abstract class NymphDriver {
|
|
|
489
502
|
)[1] as number;
|
|
490
503
|
pass = xor(
|
|
491
504
|
propName in data && data[propName] <= testLTEValue,
|
|
492
|
-
xor(typeIsNot, clauseNot)
|
|
505
|
+
xor(typeIsNot, clauseNot),
|
|
493
506
|
);
|
|
494
507
|
break;
|
|
495
508
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
509
|
+
|
|
510
|
+
if (!xor(typeIsOr, pass)) {
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
499
513
|
}
|
|
500
514
|
}
|
|
501
515
|
}
|
|
516
|
+
if (!xor(typeIsOr, pass)) {
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
502
519
|
}
|
|
503
|
-
if (!
|
|
504
|
-
|
|
520
|
+
if (!pass) {
|
|
521
|
+
return false;
|
|
505
522
|
}
|
|
506
523
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
524
|
+
return true;
|
|
525
|
+
} catch (e: any) {
|
|
526
|
+
this.nymph.config.debugError(
|
|
527
|
+
'nymph',
|
|
528
|
+
`Failed to check entity data: ${e}`,
|
|
529
|
+
);
|
|
530
|
+
throw e;
|
|
510
531
|
}
|
|
511
|
-
return true;
|
|
512
532
|
}
|
|
513
533
|
|
|
514
534
|
/**
|
|
@@ -547,7 +567,7 @@ export default abstract class NymphDriver {
|
|
|
547
567
|
| EntityInterface
|
|
548
568
|
| EntityReference
|
|
549
569
|
| string
|
|
550
|
-
| (EntityInterface | EntityReference | string)[]
|
|
570
|
+
| (EntityInterface | EntityReference | string)[],
|
|
551
571
|
) {
|
|
552
572
|
// Get the GUID, if the passed $entity is an object.
|
|
553
573
|
const guids: string[] = [];
|
|
@@ -590,7 +610,7 @@ export default abstract class NymphDriver {
|
|
|
590
610
|
|
|
591
611
|
public formatSelectors(
|
|
592
612
|
selectors: Selector[],
|
|
593
|
-
options: Options = {}
|
|
613
|
+
options: Options = {},
|
|
594
614
|
): {
|
|
595
615
|
selectors: FormattedSelector[];
|
|
596
616
|
qrefs: [Options, ...FormattedSelector[]][];
|
|
@@ -625,10 +645,9 @@ export default abstract class NymphDriver {
|
|
|
625
645
|
for (let i = 0; i < tmpArr.length; i++) {
|
|
626
646
|
const name = tmpArr[i][0];
|
|
627
647
|
const [qrefOptions, ...qrefSelectors] = tmpArr[i][1];
|
|
628
|
-
const QrefEntityClass =
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
: qrefOptions.class ?? this.nymph.getEntityClass('Entity');
|
|
648
|
+
const QrefEntityClass = qrefOptions.class
|
|
649
|
+
? this.nymph.getEntityClass(qrefOptions.class)
|
|
650
|
+
: this.nymph.getEntityClass('Entity');
|
|
632
651
|
const newOptions = {
|
|
633
652
|
...qrefOptions,
|
|
634
653
|
class: QrefEntityClass,
|
|
@@ -637,7 +656,7 @@ export default abstract class NymphDriver {
|
|
|
637
656
|
const newSelectors = this.formatSelectors(qrefSelectors, options);
|
|
638
657
|
qrefs.push(
|
|
639
658
|
[newOptions, ...newSelectors.selectors],
|
|
640
|
-
...newSelectors.qrefs
|
|
659
|
+
...newSelectors.qrefs,
|
|
641
660
|
);
|
|
642
661
|
formatArr[i] = [name, [newOptions, ...newSelectors.selectors]];
|
|
643
662
|
}
|
|
@@ -685,12 +704,12 @@ export default abstract class NymphDriver {
|
|
|
685
704
|
|
|
686
705
|
protected iterateSelectorsForQuery(
|
|
687
706
|
selectors: FormattedSelector[],
|
|
688
|
-
callback: (
|
|
689
|
-
key: string
|
|
690
|
-
value: any
|
|
691
|
-
typeIsOr: boolean
|
|
692
|
-
typeIsNot: boolean
|
|
693
|
-
) => string
|
|
707
|
+
callback: (data: {
|
|
708
|
+
key: string;
|
|
709
|
+
value: any;
|
|
710
|
+
typeIsOr: boolean;
|
|
711
|
+
typeIsNot: boolean;
|
|
712
|
+
}) => string,
|
|
694
713
|
) {
|
|
695
714
|
const queryParts = [];
|
|
696
715
|
for (const curSelector of selectors) {
|
|
@@ -703,7 +722,7 @@ export default abstract class NymphDriver {
|
|
|
703
722
|
if (key === 'type') {
|
|
704
723
|
continue;
|
|
705
724
|
}
|
|
706
|
-
let curQuery = callback(key, value, typeIsOr, typeIsNot);
|
|
725
|
+
let curQuery = callback({ key, value, typeIsOr, typeIsNot });
|
|
707
726
|
if (curQuery) {
|
|
708
727
|
if (curSelectorQuery) {
|
|
709
728
|
curSelectorQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
@@ -719,71 +738,14 @@ export default abstract class NymphDriver {
|
|
|
719
738
|
return queryParts;
|
|
720
739
|
}
|
|
721
740
|
|
|
722
|
-
|
|
723
|
-
* Get the first entity to match all options/selectors, synchronously.
|
|
724
|
-
*
|
|
725
|
-
* This should really only be used internally by the Entity class. It's a bad
|
|
726
|
-
* idea to get entities synchronously. The Entity class uses this to load
|
|
727
|
-
* sleeping references.
|
|
728
|
-
*
|
|
729
|
-
* @param options The options.
|
|
730
|
-
* @param selectors Unlimited optional selectors to search for, or a single GUID. If none are given, all entities are searched for the given options.
|
|
731
|
-
* @returns An entity, or null on failure or nothing found.
|
|
732
|
-
*/
|
|
733
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
734
|
-
options: Options<T> & { return: 'count' },
|
|
735
|
-
...selectors: Selector[]
|
|
736
|
-
): number;
|
|
737
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
738
|
-
options: Options<T> & { return: 'guid' },
|
|
739
|
-
...selectors: Selector[]
|
|
740
|
-
): string | null;
|
|
741
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
742
|
-
options: Options<T>,
|
|
743
|
-
...selectors: Selector[]
|
|
744
|
-
): ReturnType<T['factorySync']> | null;
|
|
745
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
746
|
-
options: Options<T> & { return: 'count' },
|
|
747
|
-
guid: string
|
|
748
|
-
): number;
|
|
749
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
750
|
-
options: Options<T> & { return: 'guid' },
|
|
751
|
-
guid: string
|
|
752
|
-
): string | null;
|
|
753
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
754
|
-
options: Options<T>,
|
|
755
|
-
guid: string
|
|
756
|
-
): ReturnType<T['factorySync']> | null;
|
|
757
|
-
public getEntitySync<T extends EntityConstructor = EntityConstructor>(
|
|
758
|
-
options: Options<T> = {},
|
|
759
|
-
...selectors: Selector[] | string[]
|
|
760
|
-
): ReturnType<T['factorySync']> | string | number | null {
|
|
761
|
-
// Set up options and selectors.
|
|
762
|
-
if (typeof selectors[0] === 'string') {
|
|
763
|
-
selectors = [{ type: '&', guid: selectors[0] }];
|
|
764
|
-
}
|
|
765
|
-
options.limit = 1;
|
|
766
|
-
const entities = this.getEntitiesSync(
|
|
767
|
-
options,
|
|
768
|
-
...(selectors as Selector[])
|
|
769
|
-
);
|
|
770
|
-
if (options.return === 'count') {
|
|
771
|
-
return entities as unknown as number;
|
|
772
|
-
}
|
|
773
|
-
if (!entities || !entities.length) {
|
|
774
|
-
return null;
|
|
775
|
-
}
|
|
776
|
-
return entities[0];
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
741
|
+
protected getEntitiesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
780
742
|
options: Options<T> & { return: 'count' },
|
|
781
743
|
selectors: Selector[],
|
|
782
|
-
performQueryCallback: (
|
|
783
|
-
options: Options<T
|
|
784
|
-
|
|
785
|
-
etype: string
|
|
786
|
-
) => {
|
|
744
|
+
performQueryCallback: (data: {
|
|
745
|
+
options: Options<T>;
|
|
746
|
+
selectors: FormattedSelector[];
|
|
747
|
+
etype: string;
|
|
748
|
+
}) => {
|
|
787
749
|
result: any;
|
|
788
750
|
},
|
|
789
751
|
rowFetchCallback: () => any,
|
|
@@ -798,16 +760,16 @@ export default abstract class NymphDriver {
|
|
|
798
760
|
getDataNameAndSValueCallback: (row: any) => {
|
|
799
761
|
name: string;
|
|
800
762
|
svalue: string;
|
|
801
|
-
}
|
|
763
|
+
},
|
|
802
764
|
): { result: any; process: () => number | Error };
|
|
803
|
-
protected
|
|
765
|
+
protected getEntitiesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
804
766
|
options: Options<T> & { return: 'guid' },
|
|
805
767
|
selectors: Selector[],
|
|
806
|
-
performQueryCallback: (
|
|
807
|
-
options: Options<T
|
|
808
|
-
|
|
809
|
-
etype: string
|
|
810
|
-
) => {
|
|
768
|
+
performQueryCallback: (data: {
|
|
769
|
+
options: Options<T>;
|
|
770
|
+
selectors: FormattedSelector[];
|
|
771
|
+
etype: string;
|
|
772
|
+
}) => {
|
|
811
773
|
result: any;
|
|
812
774
|
},
|
|
813
775
|
rowFetchCallback: () => any,
|
|
@@ -822,16 +784,16 @@ export default abstract class NymphDriver {
|
|
|
822
784
|
getDataNameAndSValueCallback: (row: any) => {
|
|
823
785
|
name: string;
|
|
824
786
|
svalue: string;
|
|
825
|
-
}
|
|
787
|
+
},
|
|
826
788
|
): { result: any; process: () => string[] | Error };
|
|
827
|
-
protected
|
|
789
|
+
protected getEntitiesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
828
790
|
options: Options<T>,
|
|
829
791
|
selectors: Selector[],
|
|
830
|
-
performQueryCallback: (
|
|
831
|
-
options: Options<T
|
|
832
|
-
|
|
833
|
-
etype: string
|
|
834
|
-
) => {
|
|
792
|
+
performQueryCallback: (data: {
|
|
793
|
+
options: Options<T>;
|
|
794
|
+
selectors: FormattedSelector[];
|
|
795
|
+
etype: string;
|
|
796
|
+
}) => {
|
|
835
797
|
result: any;
|
|
836
798
|
},
|
|
837
799
|
rowFetchCallback: () => any,
|
|
@@ -846,16 +808,19 @@ export default abstract class NymphDriver {
|
|
|
846
808
|
getDataNameAndSValueCallback: (row: any) => {
|
|
847
809
|
name: string;
|
|
848
810
|
svalue: string;
|
|
849
|
-
}
|
|
850
|
-
): {
|
|
851
|
-
|
|
811
|
+
},
|
|
812
|
+
): {
|
|
813
|
+
result: any;
|
|
814
|
+
process: () => EntityInstanceType<T>[] | Error;
|
|
815
|
+
};
|
|
816
|
+
protected getEntitiesRowLike<T extends EntityConstructor = EntityConstructor>(
|
|
852
817
|
options: Options<T>,
|
|
853
818
|
selectors: Selector[],
|
|
854
|
-
performQueryCallback: (
|
|
855
|
-
options: Options<T
|
|
856
|
-
|
|
857
|
-
etype: string
|
|
858
|
-
) => {
|
|
819
|
+
performQueryCallback: (data: {
|
|
820
|
+
options: Options<T>;
|
|
821
|
+
selectors: FormattedSelector[];
|
|
822
|
+
etype: string;
|
|
823
|
+
}) => {
|
|
859
824
|
result: any;
|
|
860
825
|
},
|
|
861
826
|
rowFetchCallback: () => any,
|
|
@@ -870,10 +835,10 @@ export default abstract class NymphDriver {
|
|
|
870
835
|
getDataNameAndSValueCallback: (row: any) => {
|
|
871
836
|
name: string;
|
|
872
837
|
svalue: string;
|
|
873
|
-
}
|
|
838
|
+
},
|
|
874
839
|
): {
|
|
875
840
|
result: any;
|
|
876
|
-
process: () =>
|
|
841
|
+
process: () => EntityInstanceType<T>[] | string[] | number | Error;
|
|
877
842
|
} {
|
|
878
843
|
if (!this.isConnected()) {
|
|
879
844
|
throw new UnableToConnectError('not connected to DB');
|
|
@@ -886,12 +851,12 @@ export default abstract class NymphDriver {
|
|
|
886
851
|
['&', '!&', '|', '!|'].indexOf(selector.type) === -1
|
|
887
852
|
) {
|
|
888
853
|
throw new InvalidParametersError(
|
|
889
|
-
'Invalid query selector passed: ' + JSON.stringify(selector)
|
|
854
|
+
'Invalid query selector passed: ' + JSON.stringify(selector),
|
|
890
855
|
);
|
|
891
856
|
}
|
|
892
857
|
}
|
|
893
858
|
|
|
894
|
-
let entities:
|
|
859
|
+
let entities: EntityInstanceType<T>[] | string[] = [];
|
|
895
860
|
let count = 0;
|
|
896
861
|
const EntityClass =
|
|
897
862
|
options.class ?? (this.nymph.getEntityClass('Entity') as T);
|
|
@@ -901,6 +866,7 @@ export default abstract class NymphDriver {
|
|
|
901
866
|
if (
|
|
902
867
|
this.nymph.config.cache &&
|
|
903
868
|
!options.skipCache &&
|
|
869
|
+
selectors.length &&
|
|
904
870
|
'guid' in selectors[0] &&
|
|
905
871
|
typeof selectors[0].guid === 'number'
|
|
906
872
|
) {
|
|
@@ -912,10 +878,10 @@ export default abstract class NymphDriver {
|
|
|
912
878
|
(Object.keys(selectors[0]).length === 2 ||
|
|
913
879
|
(Object.keys(selectors[0]).length === 3 && 'tag' in selectors[0]))
|
|
914
880
|
) {
|
|
915
|
-
const entity = this.pullCache<
|
|
881
|
+
const entity = this.pullCache<EntityInstanceType<T>>(
|
|
916
882
|
selectors[0]['guid'],
|
|
917
883
|
EntityClass.class,
|
|
918
|
-
!!options.skipAc
|
|
884
|
+
!!options.skipAc,
|
|
919
885
|
);
|
|
920
886
|
if (
|
|
921
887
|
entity != null &&
|
|
@@ -924,7 +890,7 @@ export default abstract class NymphDriver {
|
|
|
924
890
|
entity.hasTag(
|
|
925
891
|
...(Array.isArray(selectors[0].tag)
|
|
926
892
|
? selectors[0].tag
|
|
927
|
-
: [selectors[0].tag])
|
|
893
|
+
: [selectors[0].tag]),
|
|
928
894
|
))
|
|
929
895
|
) {
|
|
930
896
|
const guid = entity.guid;
|
|
@@ -946,15 +912,16 @@ export default abstract class NymphDriver {
|
|
|
946
912
|
try {
|
|
947
913
|
const formattedSelectors = this.formatSelectors(selectors, options);
|
|
948
914
|
this.nymph.runQueryCallbacks(options, formattedSelectors.selectors);
|
|
949
|
-
for (let
|
|
950
|
-
const [options, ...selectors] =
|
|
915
|
+
for (let i = 0; i < formattedSelectors.qrefs.length; i++) {
|
|
916
|
+
const [options, ...selectors] = formattedSelectors.qrefs[i];
|
|
951
917
|
this.nymph.runQueryCallbacks(options, selectors);
|
|
918
|
+
formattedSelectors.qrefs[i] = [options, ...selectors];
|
|
952
919
|
}
|
|
953
|
-
const { result } = performQueryCallback(
|
|
920
|
+
const { result } = performQueryCallback({
|
|
954
921
|
options,
|
|
955
|
-
formattedSelectors.selectors,
|
|
956
|
-
etype
|
|
957
|
-
);
|
|
922
|
+
selectors: formattedSelectors.selectors,
|
|
923
|
+
etype,
|
|
924
|
+
});
|
|
958
925
|
|
|
959
926
|
return {
|
|
960
927
|
result,
|
|
@@ -994,9 +961,7 @@ export default abstract class NymphDriver {
|
|
|
994
961
|
// Make sure that $row is incremented :)
|
|
995
962
|
row = rowFetchCallback();
|
|
996
963
|
}
|
|
997
|
-
const entity = EntityClass.factorySync() as
|
|
998
|
-
T['factorySync']
|
|
999
|
-
>;
|
|
964
|
+
const entity = EntityClass.factorySync() as EntityInstanceType<T>;
|
|
1000
965
|
entity.$nymph = this.nymph;
|
|
1001
966
|
if (options.skipAc != null) {
|
|
1002
967
|
entity.$useSkipAc(!!options.skipAc);
|
|
@@ -1036,34 +1001,37 @@ export default abstract class NymphDriver {
|
|
|
1036
1001
|
|
|
1037
1002
|
protected async saveEntityRowLike(
|
|
1038
1003
|
entity: EntityInterface,
|
|
1039
|
-
saveNewEntityCallback: (
|
|
1040
|
-
entity: EntityInterface
|
|
1041
|
-
guid: string
|
|
1042
|
-
tags: string[]
|
|
1043
|
-
data: EntityData
|
|
1044
|
-
sdata: SerializedEntityData
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1004
|
+
saveNewEntityCallback: (data: {
|
|
1005
|
+
entity: EntityInterface;
|
|
1006
|
+
guid: string;
|
|
1007
|
+
tags: string[];
|
|
1008
|
+
data: EntityData;
|
|
1009
|
+
sdata: SerializedEntityData;
|
|
1010
|
+
uniques: string[];
|
|
1011
|
+
cdate: number;
|
|
1012
|
+
etype: string;
|
|
1013
|
+
}) => Promise<boolean>,
|
|
1014
|
+
saveExistingEntityCallback: (data: {
|
|
1015
|
+
entity: EntityInterface;
|
|
1016
|
+
guid: string;
|
|
1017
|
+
tags: string[];
|
|
1018
|
+
data: EntityData;
|
|
1019
|
+
sdata: SerializedEntityData;
|
|
1020
|
+
uniques: string[];
|
|
1021
|
+
mdate: number;
|
|
1022
|
+
etype: string;
|
|
1023
|
+
}) => Promise<boolean>,
|
|
1057
1024
|
startTransactionCallback: (() => Promise<void>) | null = null,
|
|
1058
1025
|
commitTransactionCallback:
|
|
1059
1026
|
| ((success: boolean) => Promise<boolean>)
|
|
1060
|
-
| null = null
|
|
1027
|
+
| null = null,
|
|
1061
1028
|
) {
|
|
1062
1029
|
// Get a modified date.
|
|
1063
1030
|
const mdate = Date.now();
|
|
1064
1031
|
const tags = difference(entity.tags, ['']);
|
|
1065
1032
|
const data = entity.$getData();
|
|
1066
1033
|
const sdata = entity.$getSData();
|
|
1034
|
+
const uniques = await entity.$getUniques();
|
|
1067
1035
|
const EntityClass = entity.constructor as EntityConstructor;
|
|
1068
1036
|
const etype = EntityClass.ETYPE;
|
|
1069
1037
|
if (startTransactionCallback) {
|
|
@@ -1073,15 +1041,16 @@ export default abstract class NymphDriver {
|
|
|
1073
1041
|
if (entity.guid == null) {
|
|
1074
1042
|
const cdate = mdate;
|
|
1075
1043
|
const newId = guid();
|
|
1076
|
-
success = await saveNewEntityCallback(
|
|
1044
|
+
success = await saveNewEntityCallback({
|
|
1077
1045
|
entity,
|
|
1078
|
-
newId,
|
|
1046
|
+
guid: newId,
|
|
1079
1047
|
tags,
|
|
1080
1048
|
data,
|
|
1081
1049
|
sdata,
|
|
1050
|
+
uniques,
|
|
1082
1051
|
cdate,
|
|
1083
|
-
etype
|
|
1084
|
-
);
|
|
1052
|
+
etype,
|
|
1053
|
+
});
|
|
1085
1054
|
if (success) {
|
|
1086
1055
|
entity.guid = newId;
|
|
1087
1056
|
entity.cdate = cdate;
|
|
@@ -1092,15 +1061,16 @@ export default abstract class NymphDriver {
|
|
|
1092
1061
|
if (this.nymph.config.cache) {
|
|
1093
1062
|
this.cleanCache(entity.guid);
|
|
1094
1063
|
}
|
|
1095
|
-
success = await saveExistingEntityCallback(
|
|
1064
|
+
success = await saveExistingEntityCallback({
|
|
1096
1065
|
entity,
|
|
1097
|
-
entity.guid,
|
|
1066
|
+
guid: entity.guid,
|
|
1098
1067
|
tags,
|
|
1099
1068
|
data,
|
|
1100
1069
|
sdata,
|
|
1070
|
+
uniques,
|
|
1101
1071
|
mdate,
|
|
1102
|
-
etype
|
|
1103
|
-
);
|
|
1072
|
+
etype,
|
|
1073
|
+
});
|
|
1104
1074
|
if (success) {
|
|
1105
1075
|
entity.mdate = mdate;
|
|
1106
1076
|
}
|
|
@@ -1116,7 +1086,7 @@ export default abstract class NymphDriver {
|
|
|
1116
1086
|
entity.mdate as number,
|
|
1117
1087
|
entity.tags,
|
|
1118
1088
|
data,
|
|
1119
|
-
sdata
|
|
1089
|
+
sdata,
|
|
1120
1090
|
);
|
|
1121
1091
|
}
|
|
1122
1092
|
return success;
|
|
@@ -1130,10 +1100,10 @@ export default abstract class NymphDriver {
|
|
|
1130
1100
|
* @param useSkipAc Whether to tell the entity to use skip_ac.
|
|
1131
1101
|
* @returns The entity or null if it's not cached.
|
|
1132
1102
|
*/
|
|
1133
|
-
protected pullCache<T extends
|
|
1103
|
+
protected pullCache<T extends Entity>(
|
|
1134
1104
|
guid: string,
|
|
1135
1105
|
className: string,
|
|
1136
|
-
useSkipAc = false
|
|
1106
|
+
useSkipAc = false,
|
|
1137
1107
|
): T | null {
|
|
1138
1108
|
// Increment the entity access count.
|
|
1139
1109
|
if (!(guid in this.entityCount)) {
|
|
@@ -1151,7 +1121,7 @@ export default abstract class NymphDriver {
|
|
|
1151
1121
|
entity.tags = this.entityCache[guid]['tags'];
|
|
1152
1122
|
entity.$putData(
|
|
1153
1123
|
this.entityCache[guid]['data'],
|
|
1154
|
-
this.entityCache[guid]['sdata']
|
|
1124
|
+
this.entityCache[guid]['sdata'],
|
|
1155
1125
|
);
|
|
1156
1126
|
return entity;
|
|
1157
1127
|
}
|
|
@@ -1175,7 +1145,7 @@ export default abstract class NymphDriver {
|
|
|
1175
1145
|
mdate: number,
|
|
1176
1146
|
tags: string[],
|
|
1177
1147
|
data: EntityData,
|
|
1178
|
-
sdata: SerializedEntityData
|
|
1148
|
+
sdata: SerializedEntityData,
|
|
1179
1149
|
) {
|
|
1180
1150
|
if (guid == null) {
|
|
1181
1151
|
return;
|
|
@@ -1204,7 +1174,7 @@ export default abstract class NymphDriver {
|
|
|
1204
1174
|
// Find which entity has been accessed the least.
|
|
1205
1175
|
const least =
|
|
1206
1176
|
Object.entries(this.entityCount)
|
|
1207
|
-
.sort(([
|
|
1177
|
+
.sort(([_guidA, countA], [_guidB, countB]) => countA - countB)
|
|
1208
1178
|
.pop()?.[0] ?? null;
|
|
1209
1179
|
if (least == null) {
|
|
1210
1180
|
// This should never happen.
|