@nymphjs/nymph 1.0.0-alpha.32 → 1.0.0-alpha.36

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.
@@ -9,6 +9,7 @@ import {
9
9
  EntityConstructor,
10
10
  EntityData,
11
11
  EntityInterface,
12
+ EntityReference,
12
13
  SerializedEntityData,
13
14
  } from '../Entity.types';
14
15
  import { InvalidParametersError, UnableToConnectError } from '../errors';
@@ -69,6 +70,10 @@ export default abstract class NymphDriver {
69
70
  protected abstract exportEntities(
70
71
  writeLine: (line: string) => void
71
72
  ): Promise<void>;
73
+ abstract getEntities<T extends EntityConstructor = EntityConstructor>(
74
+ options: Options<T> & { return: 'count' },
75
+ ...selectors: Selector[]
76
+ ): Promise<number>;
72
77
  abstract getEntities<T extends EntityConstructor = EntityConstructor>(
73
78
  options: Options<T> & { return: 'guid' },
74
79
  ...selectors: Selector[]
@@ -80,7 +85,13 @@ export default abstract class NymphDriver {
80
85
  abstract getEntities<T extends EntityConstructor = EntityConstructor>(
81
86
  options?: Options<T>,
82
87
  ...selectors: Selector[]
83
- ): Promise<ReturnType<T['factorySync']>[] | string[]>;
88
+ ): Promise<ReturnType<T['factorySync']>[] | string[] | number>;
89
+ protected abstract getEntitiesSync<
90
+ T extends EntityConstructor = EntityConstructor
91
+ >(
92
+ options: Options<T> & { return: 'count' },
93
+ ...selectors: Selector[]
94
+ ): number;
84
95
  protected abstract getEntitiesSync<
85
96
  T extends EntityConstructor = EntityConstructor
86
97
  >(
@@ -98,7 +109,7 @@ export default abstract class NymphDriver {
98
109
  >(
99
110
  options?: Options<T>,
100
111
  ...selectors: Selector[]
101
- ): ReturnType<T['factorySync']>[] | string[];
112
+ ): ReturnType<T['factorySync']>[] | string[] | number;
102
113
  abstract getUID(name: string): Promise<number | null>;
103
114
  abstract import(filename: string): Promise<boolean>;
104
115
  abstract newUID(name: string): Promise<number | null>;
@@ -516,16 +527,26 @@ export default abstract class NymphDriver {
516
527
  */
517
528
  protected entityReferenceSearch(
518
529
  value: any,
519
- entity: EntityInterface | string | (EntityInterface | string)[]
530
+ entity:
531
+ | EntityInterface
532
+ | EntityReference
533
+ | string
534
+ | (EntityInterface | EntityReference | string)[]
520
535
  ) {
521
536
  // Get the GUID, if the passed $entity is an object.
522
537
  const guids: string[] = [];
523
538
  if (Array.isArray(entity)) {
524
- for (const curEntity of entity) {
525
- if (typeof curEntity === 'string') {
526
- guids.push(curEntity);
527
- } else if (typeof curEntity.guid === 'string') {
528
- guids.push(curEntity.guid);
539
+ if (entity[0] === 'nymph_entity_reference') {
540
+ guids.push(value[1]);
541
+ } else {
542
+ for (const curEntity of entity) {
543
+ if (typeof curEntity === 'string') {
544
+ guids.push(curEntity);
545
+ } else if (Array.isArray(curEntity)) {
546
+ guids.push(curEntity[1]);
547
+ } else if (typeof curEntity.guid === 'string') {
548
+ guids.push(curEntity.guid);
549
+ }
529
550
  }
530
551
  }
531
552
  } else if (typeof entity === 'string') {
@@ -684,6 +705,10 @@ export default abstract class NymphDriver {
684
705
  * @param selectors Unlimited optional selectors to search for, or a single GUID. If none are given, all entities are searched for the given options.
685
706
  * @returns An entity, or null on failure or nothing found.
686
707
  */
708
+ public getEntitySync<T extends EntityConstructor = EntityConstructor>(
709
+ options: Options<T> & { return: 'count' },
710
+ ...selectors: Selector[]
711
+ ): number;
687
712
  public getEntitySync<T extends EntityConstructor = EntityConstructor>(
688
713
  options: Options<T> & { return: 'guid' },
689
714
  ...selectors: Selector[]
@@ -692,6 +717,10 @@ export default abstract class NymphDriver {
692
717
  options: Options<T>,
693
718
  ...selectors: Selector[]
694
719
  ): ReturnType<T['factorySync']> | null;
720
+ public getEntitySync<T extends EntityConstructor = EntityConstructor>(
721
+ options: Options<T> & { return: 'count' },
722
+ guid: string
723
+ ): number;
695
724
  public getEntitySync<T extends EntityConstructor = EntityConstructor>(
696
725
  options: Options<T> & { return: 'guid' },
697
726
  guid: string
@@ -703,7 +732,7 @@ export default abstract class NymphDriver {
703
732
  public getEntitySync<T extends EntityConstructor = EntityConstructor>(
704
733
  options: Options<T> = {},
705
734
  ...selectors: Selector[] | string[]
706
- ): ReturnType<T['factorySync']> | string | null {
735
+ ): ReturnType<T['factorySync']> | string | number | null {
707
736
  // Set up options and selectors.
708
737
  if (typeof selectors[0] === 'string') {
709
738
  selectors = [{ type: '&', guid: selectors[0] }];
@@ -713,12 +742,39 @@ export default abstract class NymphDriver {
713
742
  options,
714
743
  ...(selectors as Selector[])
715
744
  );
745
+ if (options.return === 'count') {
746
+ return entities as unknown as number;
747
+ }
716
748
  if (!entities || !entities.length) {
717
749
  return null;
718
750
  }
719
751
  return entities[0];
720
752
  }
721
753
 
754
+ protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
755
+ options: Options<T> & { return: 'count' },
756
+ selectors: Selector[],
757
+ performQueryCallback: (
758
+ options: Options<T>,
759
+ formattedSelectors: FormattedSelector[],
760
+ etype: string
761
+ ) => {
762
+ result: any;
763
+ },
764
+ rowFetchCallback: () => any,
765
+ freeResultCallback: () => void,
766
+ getCountCallback: (row: any) => number,
767
+ getGUIDCallback: (row: any) => string,
768
+ getTagsAndDatesCallback: (row: any) => {
769
+ tags: string[];
770
+ cdate: number;
771
+ mdate: number;
772
+ },
773
+ getDataNameAndSValueCallback: (row: any) => {
774
+ name: string;
775
+ svalue: string;
776
+ }
777
+ ): { result: any; process: () => number };
722
778
  protected getEntitesRowLike<T extends EntityConstructor = EntityConstructor>(
723
779
  options: Options<T> & { return: 'guid' },
724
780
  selectors: Selector[],
@@ -731,6 +787,7 @@ export default abstract class NymphDriver {
731
787
  },
732
788
  rowFetchCallback: () => any,
733
789
  freeResultCallback: () => void,
790
+ getCountCallback: (row: any) => number,
734
791
  getGUIDCallback: (row: any) => string,
735
792
  getTagsAndDatesCallback: (row: any) => {
736
793
  tags: string[];
@@ -754,6 +811,7 @@ export default abstract class NymphDriver {
754
811
  },
755
812
  rowFetchCallback: () => any,
756
813
  freeResultCallback: () => void,
814
+ getCountCallback: (row: any) => number,
757
815
  getGUIDCallback: (row: any) => string,
758
816
  getTagsAndDatesCallback: (row: any) => {
759
817
  tags: string[];
@@ -777,6 +835,7 @@ export default abstract class NymphDriver {
777
835
  },
778
836
  rowFetchCallback: () => any,
779
837
  freeResultCallback: () => void,
838
+ getCountCallback: (row: any) => number,
780
839
  getGUIDCallback: (row: any) => string,
781
840
  getTagsAndDatesCallback: (row: any) => {
782
841
  tags: string[];
@@ -787,7 +846,10 @@ export default abstract class NymphDriver {
787
846
  name: string;
788
847
  svalue: string;
789
848
  }
790
- ): { result: any; process: () => ReturnType<T['factorySync']>[] | string[] } {
849
+ ): {
850
+ result: any;
851
+ process: () => ReturnType<T['factorySync']>[] | string[] | number;
852
+ } {
791
853
  if (!this.isConnected()) {
792
854
  throw new UnableToConnectError('not connected to DB');
793
855
  }
@@ -805,6 +867,7 @@ export default abstract class NymphDriver {
805
867
  }
806
868
 
807
869
  let entities: ReturnType<T['factorySync']>[] | string[] = [];
870
+ let count = 0;
808
871
  const EntityClass =
809
872
  options.class ?? (this.nymph.getEntityClass('Entity') as T);
810
873
  const etype = EntityClass.ETYPE;
@@ -842,7 +905,14 @@ export default abstract class NymphDriver {
842
905
  const guid = entity.guid;
843
906
  return {
844
907
  result: Promise.resolve(null),
845
- process: () => (options.return === 'guid' ? [guid] : [entity]),
908
+ process: () =>
909
+ options.return === 'count'
910
+ ? guid
911
+ ? 1
912
+ : 0
913
+ : options.return === 'guid'
914
+ ? [guid]
915
+ : [entity],
846
916
  };
847
917
  }
848
918
  }
@@ -856,7 +926,12 @@ export default abstract class NymphDriver {
856
926
  result,
857
927
  process: () => {
858
928
  let row = rowFetchCallback();
859
- if (options.return === 'guid') {
929
+ if (options.return === 'count') {
930
+ while (row != null) {
931
+ count += getCountCallback(row);
932
+ row = rowFetchCallback();
933
+ }
934
+ } else if (options.return === 'guid') {
860
935
  while (row != null) {
861
936
  (entities as string[]).push(getGUIDCallback(row));
862
937
  row = rowFetchCallback();
@@ -912,7 +987,7 @@ export default abstract class NymphDriver {
912
987
 
913
988
  freeResultCallback();
914
989
 
915
- return entities;
990
+ return options.return === 'count' ? count : entities;
916
991
  },
917
992
  };
918
993
  }
@@ -1319,6 +1319,55 @@ This one's zip code is 92064.`;
1319
1319
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1320
1320
  });
1321
1321
 
1322
+ it('count return', async () => {
1323
+ await createTestEntities();
1324
+
1325
+ const result = await nymph.getEntities({ class: TestModel });
1326
+
1327
+ // Testing count return...
1328
+ const resultCount = await nymph.getEntities({
1329
+ class: TestModel,
1330
+ return: 'count',
1331
+ });
1332
+ expect(resultCount).toBeGreaterThanOrEqual(1);
1333
+ expect(resultCount).toEqual(result.length);
1334
+
1335
+ const resultSelectors = await nymph.getEntities(
1336
+ { class: TestModel },
1337
+ { type: '&', ref: ['reference', refGuid] }
1338
+ );
1339
+
1340
+ // Testing count return with selectors...
1341
+ const resultSelectorsCount = await nymph.getEntities(
1342
+ { class: TestModel, return: 'count' },
1343
+ { type: '&', ref: ['reference', refGuid] }
1344
+ );
1345
+ expect(resultSelectorsCount).toBeGreaterThanOrEqual(1);
1346
+ expect(resultSelectorsCount).toEqual(resultSelectors.length);
1347
+
1348
+ // Testing count return with limit...
1349
+ const resultSelectorsLimit = await nymph.getEntities({
1350
+ class: TestModel,
1351
+ limit: 1,
1352
+ return: 'count',
1353
+ });
1354
+ expect(resultSelectorsLimit).toEqual(1);
1355
+
1356
+ // Testing count return with limit...
1357
+ const resultSelectorsSingle = await nymph.getEntity({
1358
+ class: TestModel,
1359
+ return: 'count',
1360
+ });
1361
+ expect(resultSelectorsSingle).toEqual(1);
1362
+
1363
+ // Testing empty count...
1364
+ const resultSelectorsEmpty = await nymph.getEntities(
1365
+ { class: TestModel, return: 'count' },
1366
+ { type: '&', ref: ['reference', newGUID()] }
1367
+ );
1368
+ expect(resultSelectorsEmpty).toEqual(0);
1369
+ });
1370
+
1322
1371
  it('guid return', async () => {
1323
1372
  await createTestEntities();
1324
1373
 
package/src/utils.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import Entity from './Entity';
2
2
  import { EntityReference } from './Entity.types';
3
3
  import Nymph from './Nymph';
4
+ import { Options, Selector } from './Nymph.types';
4
5
 
5
6
  export function xor(a: any, b: any): boolean {
6
7
  return !!(a && !b) || (!a && b);
@@ -14,6 +15,64 @@ export function uniqueStrings(array: string[]) {
14
15
  return Object.keys(obj);
15
16
  }
16
17
 
18
+ export function classNamesToEntityConstructors(
19
+ nymph: Nymph,
20
+ selectors: Selector[]
21
+ ): Selector[] {
22
+ const newSelectors: Selector[] = [];
23
+
24
+ for (const curSelector of selectors) {
25
+ const newSelector: Selector = { type: curSelector.type };
26
+
27
+ for (const k in curSelector) {
28
+ const key = k as keyof Selector;
29
+ const value = curSelector[key];
30
+
31
+ if (key === 'type') {
32
+ continue;
33
+ }
34
+
35
+ if (value === undefined) {
36
+ continue;
37
+ }
38
+
39
+ if (key === 'qref' || key === '!qref') {
40
+ const tmpArr = (
41
+ Array.isArray(((value as Selector['qref']) ?? [])[0])
42
+ ? value
43
+ : [value]
44
+ ) as [string, [Options, ...Selector[]]][];
45
+ for (let i = 0; i < tmpArr.length; i++) {
46
+ const name = tmpArr[i][0];
47
+ const [qrefOptions, ...selectors] = tmpArr[i][1];
48
+ const QrefEntityClass =
49
+ typeof qrefOptions.class === 'string'
50
+ ? nymph.getEntityClass(qrefOptions.class)
51
+ : qrefOptions.class ?? nymph.getEntityClass('Entity');
52
+ const options = { ...qrefOptions, class: QrefEntityClass };
53
+ if (!newSelector[key]) {
54
+ newSelector[key] = [];
55
+ }
56
+ (newSelector[key] as [string, [Options, ...Selector[]]][]).push([
57
+ name,
58
+ [options, ...classNamesToEntityConstructors(nymph, selectors)],
59
+ ]);
60
+ }
61
+ } else if (key === 'selector' || key === '!selector') {
62
+ const tmpArr = (Array.isArray(value) ? value : [value]) as Selector[];
63
+ newSelector[key] = classNamesToEntityConstructors(nymph, tmpArr);
64
+ } else {
65
+ // @ts-ignore: ts doesn't know what value is here.
66
+ newSelector[key] = value;
67
+ }
68
+ }
69
+
70
+ newSelectors.push(newSelector);
71
+ }
72
+
73
+ return newSelectors;
74
+ }
75
+
17
76
  export function entitiesToReferences(item: any): any {
18
77
  if (item instanceof Entity && typeof item.$toReference === 'function') {
19
78
  // Convert entities to references.