@nymphjs/nymph 1.0.0-beta.0 → 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 +58 -0
- package/README.md +4 -2
- package/dist/Entity.js +65 -67
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +83 -94
- 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 +154 -204
- 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 +204 -205
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/testArtifacts.js +526 -553
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/testArtifacts.js +4 -23
- package/dist/testArtifacts.js.map +1 -1
- package/dist/testMocks.d.ts +3 -1
- package/dist/testMocks.js +41 -53
- package/dist/testMocks.js.map +1 -1
- package/dist/utils.js +3 -4
- package/dist/utils.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/tsconfig.json +2 -0
|
@@ -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(
|
|
@@ -3,16 +3,20 @@ import strtotime from 'locutus/php/datetime/strtotime';
|
|
|
3
3
|
import { guid } from '@nymphjs/guid';
|
|
4
4
|
|
|
5
5
|
import type Nymph from '../Nymph';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
TestBModel as TestBModelClass,
|
|
8
|
+
TestModel as TestModelClass,
|
|
9
|
+
TestModelData,
|
|
10
|
+
} from '../testArtifacts';
|
|
7
11
|
|
|
8
12
|
export function QueriesTest(
|
|
9
13
|
nymph: Nymph,
|
|
10
14
|
it: (name: string, fn: () => void) => void
|
|
11
15
|
) {
|
|
12
|
-
nymph.addEntityClass(
|
|
13
|
-
nymph.addEntityClass(
|
|
16
|
+
const TestModel = nymph.addEntityClass(TestModelClass);
|
|
17
|
+
const TestBModel = nymph.addEntityClass(TestBModelClass);
|
|
14
18
|
|
|
15
|
-
let testEntity:
|
|
19
|
+
let testEntity: TestModelClass & TestModelData;
|
|
16
20
|
let testGuid: string;
|
|
17
21
|
let refGuid: string;
|
|
18
22
|
let createdMultiple = false;
|
|
@@ -43,7 +47,7 @@ This one's zip code is 92064.`;
|
|
|
43
47
|
expect(testEntity.guid).not.toBeNull();
|
|
44
48
|
testGuid = testEntity.guid as string;
|
|
45
49
|
|
|
46
|
-
const entityReferenceTest:
|
|
50
|
+
const entityReferenceTest: TestModelClass & TestModelData = new TestModel();
|
|
47
51
|
entityReferenceTest.string = 'wrong';
|
|
48
52
|
entityReferenceTest.timestamp = strtotime('-2 days') * 1000;
|
|
49
53
|
expect(await entityReferenceTest.$save()).toEqual(true);
|
|
@@ -59,7 +63,7 @@ This one's zip code is 92064.`;
|
|
|
59
63
|
testEntity = nymph.driver.getEntitySync(
|
|
60
64
|
{ class: TestModel },
|
|
61
65
|
testGuid
|
|
62
|
-
) as
|
|
66
|
+
) as TestModelClass & TestModelData;
|
|
63
67
|
expect(testEntity).toBeInstanceOf(TestModel);
|
|
64
68
|
expect(testEntity.guid).toEqual(testGuid);
|
|
65
69
|
|
|
@@ -67,7 +71,7 @@ This one's zip code is 92064.`;
|
|
|
67
71
|
testEntity = (await nymph.getEntity(
|
|
68
72
|
{ class: TestModel },
|
|
69
73
|
testGuid
|
|
70
|
-
)) as
|
|
74
|
+
)) as TestModelClass & TestModelData;
|
|
71
75
|
expect(testEntity).toBeInstanceOf(TestModel);
|
|
72
76
|
expect(testEntity.guid).toEqual(testGuid);
|
|
73
77
|
}
|
|
@@ -191,7 +195,7 @@ This one's zip code is 92064.`;
|
|
|
191
195
|
testEntity = (await transaction.getEntity(
|
|
192
196
|
{ class: TestModel },
|
|
193
197
|
testGuid
|
|
194
|
-
)) as
|
|
198
|
+
)) as TestModelClass & TestModelData;
|
|
195
199
|
|
|
196
200
|
expect(testEntity.guid).toEqual(testGuid);
|
|
197
201
|
|
|
@@ -1728,9 +1732,6 @@ export function UIDTest(
|
|
|
1728
1732
|
nymph: Nymph,
|
|
1729
1733
|
it: (name: string, fn: () => void) => void
|
|
1730
1734
|
) {
|
|
1731
|
-
nymph.addEntityClass(TestModel);
|
|
1732
|
-
nymph.addEntityClass(TestBModel);
|
|
1733
|
-
|
|
1734
1735
|
it('delete old test data', async () => {
|
|
1735
1736
|
expect(await nymph.deleteUID('TestUID')).toEqual(true);
|
|
1736
1737
|
expect(await nymph.deleteUID('NewUID')).toEqual(true);
|
|
@@ -1772,8 +1773,8 @@ export function ExportImportTest(
|
|
|
1772
1773
|
nymph: Nymph,
|
|
1773
1774
|
it: (name: string, fn: () => void) => void
|
|
1774
1775
|
) {
|
|
1775
|
-
nymph.addEntityClass(
|
|
1776
|
-
nymph.addEntityClass(
|
|
1776
|
+
const TestModel = nymph.addEntityClass(TestModelClass);
|
|
1777
|
+
const TestBModel = nymph.addEntityClass(TestBModelClass);
|
|
1777
1778
|
|
|
1778
1779
|
async function deleteTestData() {
|
|
1779
1780
|
let all = await nymph.getEntities({ class: TestModel });
|
package/src/testMocks.ts
CHANGED
|
@@ -59,24 +59,31 @@ export class MockNymph {
|
|
|
59
59
|
private entityClasses: { [k: string]: EntityConstructor } = {};
|
|
60
60
|
public driver: MockNymphDriver;
|
|
61
61
|
public Tilmeld: any = undefined;
|
|
62
|
+
public Entity: typeof Entity;
|
|
62
63
|
|
|
63
64
|
public constructor() {
|
|
64
65
|
this.driver = new MockNymphDriver(this);
|
|
65
66
|
|
|
66
67
|
// class NymphEntity extends Entity {}
|
|
67
|
-
this.addEntityClass(Entity);
|
|
68
|
+
this.Entity = this.addEntityClass(Entity);
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
public addEntityClass(entityClass:
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
public addEntityClass<T extends EntityConstructor>(entityClass: T): T {
|
|
72
|
+
const nymph = this;
|
|
73
|
+
class NymphEntity extends entityClass {
|
|
74
|
+
static nymph: Nymph = nymph as unknown as Nymph;
|
|
75
|
+
|
|
76
|
+
constructor(...args: any[]) {
|
|
77
|
+
super(...args);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.entityClasses[entityClass.class] = NymphEntity;
|
|
81
|
+
return NymphEntity;
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
public getEntityClass(className: string): EntityConstructor {
|
|
76
85
|
if (className in this.entityClasses) {
|
|
77
|
-
|
|
78
|
-
EntityClass.nymph = this as unknown as Nymph;
|
|
79
|
-
return EntityClass;
|
|
86
|
+
return this.entityClasses[className];
|
|
80
87
|
}
|
|
81
88
|
throw new ClassNotAvailableError('Tried to use class: ' + className);
|
|
82
89
|
}
|