@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.
@@ -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
- ): FormattedSelector[] {
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
- this.nymph.runQueryCallbacks(newOptions, newSelectors);
619
- formatArr[i] = [name, [newOptions, ...newSelectors]];
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
- newSelector[key] = this.formatSelectors(tmpArr, options);
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
- const formattedSelectors = this.formatSelectors(selectors, options);
922
- this.nymph.runQueryCallbacks(options, formattedSelectors);
923
- const { result } = performQueryCallback(options, formattedSelectors, etype);
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
- return {
926
- result,
927
- process: () => {
928
- let row = rowFetchCallback();
929
- if (options.return === 'count') {
930
- while (row != null) {
931
- count += getCountCallback(row);
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
- const entity = EntityClass.factorySync() as ReturnType<
964
- T['factorySync']
965
- >;
966
- entity.$nymph = this.nymph;
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
- entity.$putData(data, sdata);
979
- this.putDataCounter--;
980
- if (this.nymph.config.cache) {
981
- this.pushCache(guid, cdate, mdate, tags, data, sdata);
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
- freeResultCallback();
1022
+ freeResultCallback();
989
1023
 
990
- return options.return === 'count' ? count : entities;
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 { TestBModel, TestModel, TestModelData } from '../testArtifacts';
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(TestModel);
13
- nymph.addEntityClass(TestBModel);
16
+ const TestModel = nymph.addEntityClass(TestModelClass);
17
+ const TestBModel = nymph.addEntityClass(TestBModelClass);
14
18
 
15
- let testEntity: TestModel & TestModelData;
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: TestModel & TestModelData = new TestModel();
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 TestModel & TestModelData;
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 TestModel & TestModelData;
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 TestModel & TestModelData;
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(TestModel);
1776
- nymph.addEntityClass(TestBModel);
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: EntityConstructor) {
71
- this.entityClasses[entityClass.class] = entityClass;
72
- entityClass.nymph = this as unknown as Nymph;
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
- const EntityClass = this.entityClasses[className];
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
  }
package/tsconfig.json CHANGED
@@ -2,6 +2,8 @@
2
2
  "extends": "@tsconfig/recommended/tsconfig.json",
3
3
 
4
4
  "compilerOptions": {
5
+ "lib": ["ES2021"],
6
+ "target": "ES2021",
5
7
  "noImplicitAny": true,
6
8
  "removeComments": true,
7
9
  "sourceMap": true,