@snowtop/ent 0.1.0 → 0.1.2

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.
@@ -390,7 +390,8 @@ class EdgeOperation {
390
390
  // maybe when actions exist?
391
391
  fields["time"] = new Date().toISOString();
392
392
  }
393
- const onConflictFields = ["data"];
393
+ // update time if we're trying to insert a row with the same id1, edge_type, id2
394
+ const onConflictFields = ["data", "time"];
394
395
  const extraEdgeFields = (0, global_schema_1.__getGlobalSchema)()?.extraEdgeFields;
395
396
  if (extraEdgeFields) {
396
397
  for (const name in extraEdgeFields) {
@@ -24,6 +24,9 @@ export declare abstract class AssocEdgeQueryBase<TSource extends Ent<TViewer>, T
24
24
  protected loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
25
25
  queryID2(id2: ID): Promise<TEdge | undefined>;
26
26
  queryAllID2(id2: ID): Promise<Map<ID, TEdge>>;
27
+ __beforeBETA(time: Date): this;
28
+ __afterBETA(time: Date): this;
29
+ __withinBeta(start: Date, end: Date): this;
27
30
  }
28
31
  export interface EdgeQueryCtr<TSource extends Ent, TDest extends Ent, TEdge extends AssocEdge> {
29
32
  new (viewer: Viewer, src: EdgeQuerySource<TSource>): EdgeQuery<TSource, TDest, TEdge>;
@@ -1,8 +1,32 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.AssocEdgeQueryBase = void 0;
4
27
  const ent_1 = require("../ent");
5
28
  const query_1 = require("./query");
29
+ const clause = __importStar(require("../clause"));
6
30
  // would be nice to someday have an API for assoc asc
7
31
  class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
8
32
  constructor(viewer, src, countLoaderFactory, dataLoaderFactory,
@@ -150,5 +174,52 @@ class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
150
174
  }));
151
175
  return m;
152
176
  }
177
+ __beforeBETA(time) {
178
+ this.__assertNoFiltersBETA("before");
179
+ this.__addCustomFilterBETA(new BeforeFilter(time));
180
+ return this;
181
+ }
182
+ __afterBETA(time) {
183
+ this.__assertNoFiltersBETA("after");
184
+ this.__addCustomFilterBETA(new AfterFilter(time));
185
+ return this;
186
+ }
187
+ // start is inclusive, end is exclusive
188
+ __withinBeta(start, end) {
189
+ this.__assertNoFiltersBETA("after");
190
+ this.__addCustomFilterBETA(new WithinFilter(start, end));
191
+ return this;
192
+ }
153
193
  }
154
194
  exports.AssocEdgeQueryBase = AssocEdgeQueryBase;
195
+ class BeforeFilter {
196
+ constructor(time) {
197
+ this.time = time;
198
+ }
199
+ query(options) {
200
+ const cls = clause.Less("time", this.time);
201
+ options.clause = clause.AndOptional(options.clause, cls);
202
+ return options;
203
+ }
204
+ }
205
+ class AfterFilter {
206
+ constructor(time) {
207
+ this.time = time;
208
+ }
209
+ query(options) {
210
+ const cls = clause.Greater("time", this.time);
211
+ options.clause = clause.AndOptional(options.clause, cls);
212
+ return options;
213
+ }
214
+ }
215
+ class WithinFilter {
216
+ constructor(start, end) {
217
+ this.start = start;
218
+ this.end = end;
219
+ }
220
+ query(options) {
221
+ const cls = clause.And(clause.GreaterEq("time", this.start), clause.Less("time", this.end));
222
+ options.clause = clause.AndOptional(options.clause, cls);
223
+ return options;
224
+ }
225
+ }
@@ -47,12 +47,15 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
47
47
  private sortCol;
48
48
  private cursorCol;
49
49
  private edgeQueryOptions;
50
+ private limitAdded;
50
51
  constructor(viewer: Viewer, sortCol: string, cursorCol: string);
51
52
  constructor(viewer: Viewer, options: EdgeQueryOptions);
52
53
  protected getSortCol(): string;
53
54
  getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
54
55
  abstract sourceEnt(id: ID): Promise<Ent | null>;
55
56
  first(n: number, after?: string): this;
57
+ __addCustomFilterBETA(filter: EdgeQueryFilter<TEdge>): void;
58
+ protected __assertNoFiltersBETA(name: string): void;
56
59
  last(n: number, before?: string): this;
57
60
  private querySingleEdge;
58
61
  readonly queryEdges: () => Promise<TEdge[]>;
@@ -110,7 +110,7 @@ class FirstFilter {
110
110
  const res = this.edgeQuery.getTableName();
111
111
  const tableName = (0, types_1.isPromise)(res) ? await res : res;
112
112
  // inner col time
113
- options.clause = clause.PaginationMultipleColsSubQuery(this.sortCol, less ? "<" : ">", tableName, this.options.cursorCol, this.offset);
113
+ options.clause = clause.AndOptional(options.clause, clause.PaginationMultipleColsSubQuery(this.sortCol, less ? "<" : ">", tableName, this.options.cursorCol, this.offset));
114
114
  }
115
115
  }
116
116
  else {
@@ -119,7 +119,7 @@ class FirstFilter {
119
119
  let val = this.options.sortColTime
120
120
  ? new Date(this.offset).toISOString()
121
121
  : this.offset;
122
- options.clause = clauseFn(this.sortCol, val);
122
+ options.clause = clause.AndOptional(options.clause, clauseFn(this.sortCol, val));
123
123
  }
124
124
  }
125
125
  options.orderby = orderby;
@@ -177,7 +177,7 @@ class LastFilter {
177
177
  const tableName = (0, types_1.isPromise)(res) ? await res : res;
178
178
  if (this.offset) {
179
179
  // inner col time
180
- options.clause = clause.PaginationMultipleColsSubQuery(this.sortCol, greater ? ">" : "<", tableName, this.options.cursorCol, this.offset);
180
+ options.clause = clause.AndOptional(options.clause, clause.PaginationMultipleColsSubQuery(this.sortCol, greater ? ">" : "<", tableName, this.options.cursorCol, this.offset));
181
181
  }
182
182
  // we also sort cursor col in same direction. (direction doesn't matter)
183
183
  orderby.push({
@@ -191,7 +191,7 @@ class LastFilter {
191
191
  let val = this.options.sortColTime
192
192
  ? new Date(this.offset).toISOString()
193
193
  : this.offset;
194
- options.clause = clauseFn(this.sortCol, val);
194
+ options.clause = clause.AndOptional(options.clause, clauseFn(this.sortCol, val));
195
195
  }
196
196
  }
197
197
  options.orderby = orderby;
@@ -209,6 +209,7 @@ class BaseEdgeQuery {
209
209
  this.pagination = new Map();
210
210
  this.idMap = new Map();
211
211
  this.idsToFetch = [];
212
+ this.limitAdded = false;
212
213
  // this is basically just raw rows
213
214
  this.queryEdges = async () => {
214
215
  return await this.querySingleEdge("queryEdges");
@@ -306,6 +307,7 @@ class BaseEdgeQuery {
306
307
  return privacy_1.AlwaysAllowPrivacyPolicy;
307
308
  }
308
309
  first(n, after) {
310
+ this.limitAdded = true;
309
311
  this.assertQueryNotDispatched("first");
310
312
  this.filters.push(new FirstFilter({
311
313
  limit: n,
@@ -317,7 +319,18 @@ class BaseEdgeQuery {
317
319
  }));
318
320
  return this;
319
321
  }
322
+ // API subject to change
323
+ // TODO https://github.com/lolopinto/ent/issues/685
324
+ __addCustomFilterBETA(filter) {
325
+ this.filters.push(filter);
326
+ }
327
+ __assertNoFiltersBETA(name) {
328
+ if (this.filters.length !== 0) {
329
+ throw new Error(`${name} must be the first filter called`);
330
+ }
331
+ }
320
332
  last(n, before) {
333
+ this.limitAdded = true;
321
334
  this.assertQueryNotDispatched("last");
322
335
  this.filters.push(new LastFilter({
323
336
  limit: n,
@@ -378,8 +391,9 @@ class BaseEdgeQuery {
378
391
  }
379
392
  async loadEdges() {
380
393
  const idsInfo = await this.genIDInfosToFetch();
381
- if (!this.filters.length) {
382
- // if no filter, we add the firstN filter to ensure we get pagination info
394
+ // we need first even if other filters are included...
395
+ if (!this.limitAdded) {
396
+ // if no limit filter, we add the firstN filter to ensure we get pagination info
383
397
  this.first((0, ent_1.getDefaultLimit)());
384
398
  }
385
399
  let options = this._defaultEdgeQueryableOptions ?? {};
@@ -11,6 +11,7 @@ const clause_1 = require("../clause");
11
11
  const builder_1 = require("../../testutils/builder");
12
12
  const luxon_1 = require("luxon");
13
13
  const convert_1 = require("../convert");
14
+ const test_context_1 = require("../../testutils/context/test_context");
14
15
  function assocTests(ml, global = false) {
15
16
  ml.mock();
16
17
  describe("custom edge", () => {
@@ -56,21 +57,21 @@ function assocTests(ml, global = false) {
56
57
  let execArray = /^SELECT (.+) FROM (.+) WHERE (.+)?/.exec(query.query);
57
58
  return execArray?.[3];
58
59
  }
59
- function verifyQuery({ length = 1, numQueries = 1, limit = (0, ent_1.getDefaultLimit)(), disablePaginationBump = false, }) {
60
+ function verifyQuery({ length = 1, numQueries = 1, limit = (0, ent_1.getDefaultLimit)(), extraClause = undefined, disablePaginationBump = false, logsStart = 0, direction = "DESC", }) {
61
+ const clses = [(0, clause_1.Eq)("id1", ""), (0, clause_1.Eq)("edge_type", "")];
62
+ if (extraClause) {
63
+ clses.push(extraClause);
64
+ }
65
+ if (global) {
66
+ clses.push((0, clause_1.Eq)("deleted_at", null));
67
+ }
60
68
  expect(ml.logs.length).toBe(length);
61
- for (let i = 0; i < numQueries; i++) {
69
+ for (let i = logsStart; i < numQueries; i++) {
62
70
  const whereClause = getWhereClause(ml.logs[i]);
63
71
  let expLimit = disablePaginationBump ? limit : limit + 1;
64
- if (global) {
65
- expect(whereClause, `${i}`).toBe(
66
- // default limit
67
- `${(0, clause_1.And)((0, clause_1.Eq)("id1", ""), (0, clause_1.Eq)("edge_type", ""), (0, clause_1.Eq)("deleted_at", null)).clause(1)} ORDER BY time DESC, id2 DESC LIMIT ${expLimit}`);
68
- }
69
- else {
70
- expect(whereClause, `${i}`).toBe(
71
- // default limit
72
- `${(0, clause_1.And)((0, clause_1.Eq)("id1", ""), (0, clause_1.Eq)("edge_type", "")).clause(1)} ORDER BY time DESC, id2 DESC LIMIT ${expLimit}`);
73
- }
72
+ expect(whereClause, `${i}`).toBe(
73
+ // default limit
74
+ `${(0, clause_1.And)(...clses).clause(1)} ORDER BY time ${direction}, id2 ${direction} LIMIT ${expLimit}`);
74
75
  }
75
76
  }
76
77
  function verifyCountQuery({ length = 1, numQueries = 1 }) {
@@ -663,6 +664,290 @@ function assocTests(ml, global = false) {
663
664
  expect(entsMapFromUserVCToken.get(user2.id)?.length).toBe(0);
664
665
  });
665
666
  });
667
+ describe("time based queries", () => {
668
+ let user;
669
+ let contacts;
670
+ let ctx;
671
+ beforeEach(async () => {
672
+ ctx = new test_context_1.TestContext();
673
+ [user, contacts] = await (0, test_helpers_1.createAllContacts)({ ctx });
674
+ const sortedTimes = contacts.map((c) => c.createdAt.getTime());
675
+ expect(sortedTimes[1] - sortedTimes[0]).toBe(86400);
676
+ expect(contacts.length).toBe(5);
677
+ ml.clear();
678
+ // to prime the cache
679
+ await index_1.FakeUser.load(user.viewer, user.id);
680
+ });
681
+ function getQuery(viewer) {
682
+ return index_1.UserToContactsQuery.query(viewer, user.id);
683
+ }
684
+ test("ids", async () => {
685
+ const ids = await getQuery(user.viewer).queryIDs();
686
+ expect(ids.length).toBe(contacts.length);
687
+ });
688
+ test("before", async () => {
689
+ const ids = await getQuery(user.viewer)
690
+ .__beforeBETA(contacts[2].createdAt)
691
+ .queryIDs();
692
+ expect(ids.length).toBe(2);
693
+ expect(ids).toEqual([contacts[1].id, contacts[0].id]);
694
+ verifyQuery({
695
+ length: 2,
696
+ extraClause: (0, clause_1.Less)("time", contacts[2].createdAt),
697
+ // there's a load for user we don't care about here so just skip it...
698
+ logsStart: 1,
699
+ numQueries: 2,
700
+ });
701
+ });
702
+ test("before + first", async () => {
703
+ const ids = await getQuery(user.viewer)
704
+ .__beforeBETA(contacts[2].createdAt)
705
+ .first(1)
706
+ .queryIDs();
707
+ expect(ids.length).toBe(1);
708
+ expect(ids).toEqual([contacts[1].id]);
709
+ verifyQuery({
710
+ length: 2,
711
+ limit: 1,
712
+ extraClause: (0, clause_1.Less)("time", contacts[2].createdAt),
713
+ // there's a load for user we don't care about here so just skip it...
714
+ logsStart: 1,
715
+ numQueries: 2,
716
+ });
717
+ });
718
+ test("before + last", async () => {
719
+ const ids = await getQuery(user.viewer)
720
+ .__beforeBETA(contacts[2].createdAt)
721
+ .last(1)
722
+ .queryIDs();
723
+ expect(ids.length).toBe(1);
724
+ expect(ids).toEqual([contacts[0].id]);
725
+ verifyQuery({
726
+ length: 2,
727
+ limit: 1,
728
+ extraClause: (0, clause_1.Less)("time", contacts[2].createdAt),
729
+ // there's a load for user we don't care about here so just skip it...
730
+ logsStart: 1,
731
+ numQueries: 2,
732
+ direction: "ASC",
733
+ });
734
+ });
735
+ test("before + first with pagination", async () => {
736
+ const query = getQuery(user.viewer);
737
+ const edges = await query
738
+ .__beforeBETA(contacts[2].createdAt)
739
+ .first(1)
740
+ .queryEdges();
741
+ const pagination = query.paginationInfo();
742
+ expect(edges.length).toBe(1);
743
+ expect(edges.map((edge) => edge.id2)).toEqual([contacts[1].id]);
744
+ verifyQuery({
745
+ length: 2,
746
+ limit: 1,
747
+ extraClause: (0, clause_1.Less)("time", contacts[2].createdAt),
748
+ // there's a load for user we don't care about here so just skip it...
749
+ logsStart: 1,
750
+ numQueries: 2,
751
+ });
752
+ const info = pagination.get(user.id);
753
+ expect(info.hasNextPage).toBe(true);
754
+ expect(info.hasPreviousPage).toBe(false);
755
+ ml.clear();
756
+ const query2 = getQuery(user.viewer);
757
+ const edges2 = await query2
758
+ .__beforeBETA(contacts[2].createdAt)
759
+ .first(1, info.endCursor)
760
+ .queryEdges();
761
+ const pagination2 = query2.paginationInfo();
762
+ expect(edges2.length).toBe(1);
763
+ expect(edges2.map((edge) => edge.id2)).toEqual([contacts[0].id]);
764
+ // complicated pagination query. ignore verifying for now
765
+ // verifyFirstAfterCursorQuery in shared_test handles this...
766
+ const info2 = pagination2.get(user.id) ?? {
767
+ hasNextPage: false,
768
+ hasPreviousPage: false,
769
+ };
770
+ expect(info2.hasNextPage).toBe(false);
771
+ expect(info2.hasPreviousPage).toBe(false);
772
+ });
773
+ test("after", async () => {
774
+ const ids = await getQuery(user.viewer)
775
+ .__afterBETA(contacts[2].createdAt)
776
+ .queryIDs();
777
+ expect(ids.length).toBe(2);
778
+ expect(ids).toEqual([contacts[4].id, contacts[3].id]);
779
+ verifyQuery({
780
+ length: 2,
781
+ extraClause: (0, clause_1.Greater)("time", contacts[2].createdAt),
782
+ // there's a load for user we don't care about here so just skip it...
783
+ logsStart: 1,
784
+ numQueries: 2,
785
+ });
786
+ });
787
+ test("after + first", async () => {
788
+ const ids = await getQuery(user.viewer)
789
+ .__afterBETA(contacts[2].createdAt)
790
+ .first(1)
791
+ .queryIDs();
792
+ expect(ids.length).toBe(1);
793
+ expect(ids).toEqual([contacts[4].id]);
794
+ verifyQuery({
795
+ length: 2,
796
+ limit: 1,
797
+ extraClause: (0, clause_1.Greater)("time", contacts[2].createdAt),
798
+ // there's a load for user we don't care about here so just skip it...
799
+ logsStart: 1,
800
+ numQueries: 2,
801
+ });
802
+ });
803
+ test("after + last", async () => {
804
+ const ids = await getQuery(user.viewer)
805
+ .__afterBETA(contacts[2].createdAt)
806
+ .last(1)
807
+ .queryIDs();
808
+ expect(ids.length).toBe(1);
809
+ expect(ids).toEqual([contacts[3].id]);
810
+ verifyQuery({
811
+ length: 2,
812
+ limit: 1,
813
+ extraClause: (0, clause_1.Greater)("time", contacts[2].createdAt),
814
+ // there's a load for user we don't care about here so just skip it...
815
+ logsStart: 1,
816
+ numQueries: 2,
817
+ direction: "ASC",
818
+ });
819
+ });
820
+ test("within", async () => {
821
+ const ids = await getQuery(user.viewer)
822
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
823
+ .queryIDs();
824
+ expect(ids.length).toBe(3);
825
+ expect(ids).toEqual([contacts[3].id, contacts[2].id, contacts[1].id]);
826
+ verifyQuery({
827
+ length: 2,
828
+ extraClause: (0, clause_1.And)((0, clause_1.GreaterEq)("time", contacts[1].createdAt), (0, clause_1.Less)("time", contacts[4].createdAt)),
829
+ // there's a load for user we don't care about here so just skip it...
830
+ logsStart: 1,
831
+ numQueries: 2,
832
+ });
833
+ });
834
+ test("within + first", async () => {
835
+ const ids = await getQuery(user.viewer)
836
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
837
+ .first(2)
838
+ .queryIDs();
839
+ expect(ids.length).toBe(2);
840
+ expect(ids).toEqual([contacts[3].id, contacts[2].id]);
841
+ verifyQuery({
842
+ length: 2,
843
+ limit: 2,
844
+ extraClause: (0, clause_1.And)((0, clause_1.GreaterEq)("time", contacts[1].createdAt), (0, clause_1.Less)("time", contacts[4].createdAt)),
845
+ // there's a load for user we don't care about here so just skip it...
846
+ logsStart: 1,
847
+ numQueries: 2,
848
+ });
849
+ });
850
+ test("within + last", async () => {
851
+ const ids = await getQuery(user.viewer)
852
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
853
+ .last(2)
854
+ .queryIDs();
855
+ expect(ids.length).toBe(2);
856
+ expect(ids).toEqual([contacts[1].id, contacts[2].id]);
857
+ verifyQuery({
858
+ length: 2,
859
+ limit: 2,
860
+ extraClause: (0, clause_1.And)((0, clause_1.GreaterEq)("time", contacts[1].createdAt), (0, clause_1.Less)("time", contacts[4].createdAt)),
861
+ // there's a load for user we don't care about here so just skip it...
862
+ logsStart: 1,
863
+ numQueries: 2,
864
+ direction: "ASC",
865
+ });
866
+ });
867
+ test("within + first with pagination", async () => {
868
+ const query = getQuery(user.viewer);
869
+ const edges = await query
870
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
871
+ .first(2)
872
+ .queryEdges();
873
+ const pagination = query.paginationInfo();
874
+ expect(edges.length).toBe(2);
875
+ expect(edges.map((edge) => edge.id2)).toEqual([
876
+ contacts[3].id,
877
+ contacts[2].id,
878
+ ]);
879
+ verifyQuery({
880
+ length: 2,
881
+ limit: 2,
882
+ extraClause: (0, clause_1.And)((0, clause_1.GreaterEq)("time", contacts[1].createdAt), (0, clause_1.Less)("time", contacts[4].createdAt)),
883
+ // there's a load for user we don't care about here so just skip it...
884
+ logsStart: 1,
885
+ numQueries: 2,
886
+ });
887
+ const info = pagination.get(user.id);
888
+ expect(info.hasNextPage).toBe(true);
889
+ expect(info.hasPreviousPage).toBe(false);
890
+ ml.clear();
891
+ const query2 = getQuery(user.viewer);
892
+ const edges2 = await query2
893
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
894
+ .first(2, info.endCursor)
895
+ .queryEdges();
896
+ const pagination2 = query2.paginationInfo();
897
+ expect(edges2.length).toBe(1);
898
+ expect(edges2.map((edge) => edge.id2)).toEqual([contacts[1].id]);
899
+ // complicated pagination query. ignore verifying for now
900
+ // verifyFirstAfterCursorQuery in shared_test handles this...
901
+ const info2 = pagination2.get(user.id) ?? {
902
+ hasNextPage: false,
903
+ hasPreviousPage: false,
904
+ };
905
+ expect(info2.hasNextPage).toBe(false);
906
+ expect(info2.hasPreviousPage).toBe(false);
907
+ });
908
+ test("within + last with pagination", async () => {
909
+ const query = getQuery(user.viewer);
910
+ const edges = await query
911
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
912
+ .last(2)
913
+ .queryEdges();
914
+ const pagination = query.paginationInfo();
915
+ expect(edges.length).toBe(2);
916
+ expect(edges.map((edge) => edge.id2)).toEqual([
917
+ contacts[1].id,
918
+ contacts[2].id,
919
+ ]);
920
+ verifyQuery({
921
+ length: 2,
922
+ limit: 2,
923
+ extraClause: (0, clause_1.And)((0, clause_1.GreaterEq)("time", contacts[1].createdAt), (0, clause_1.Less)("time", contacts[4].createdAt)),
924
+ // there's a load for user we don't care about here so just skip it...
925
+ logsStart: 1,
926
+ numQueries: 2,
927
+ direction: "ASC",
928
+ });
929
+ const info = pagination.get(user.id);
930
+ expect(info.hasNextPage).toBe(false);
931
+ expect(info.hasPreviousPage).toBe(true);
932
+ ml.clear();
933
+ const query2 = getQuery(user.viewer);
934
+ const edges2 = await query2
935
+ .__withinBeta(contacts[1].createdAt, contacts[4].createdAt)
936
+ .last(2, info.endCursor)
937
+ .queryEdges();
938
+ const pagination2 = query2.paginationInfo();
939
+ expect(edges2.length).toBe(1);
940
+ expect(edges2.map((edge) => edge.id2)).toEqual([contacts[3].id]);
941
+ // complicated pagination query. ignore verifying for now
942
+ // verifyFirstAfterCursorQuery in shared_test handles this...
943
+ const info2 = pagination2.get(user.id) ?? {
944
+ hasNextPage: false,
945
+ hasPreviousPage: false,
946
+ };
947
+ expect(info2.hasNextPage).toBe(false);
948
+ expect(info2.hasPreviousPage).toBe(false);
949
+ });
950
+ });
666
951
  if (!global) {
667
952
  return;
668
953
  }
@@ -697,11 +697,11 @@ const commonTests = (opts) => {
697
697
  user = u;
698
698
  const [_, contacts2] = await (0, test_helpers_1.createAllContacts)({
699
699
  user,
700
- start: contacts[contacts.length - 1].createdAt.getTime() - 100,
700
+ start: contacts[contacts.length - 1].createdAt.getTime() - 86400,
701
701
  });
702
702
  await (0, test_helpers_1.createAllContacts)({
703
703
  user,
704
- start: contacts2[contacts.length - 1].createdAt.getTime() - 100,
704
+ start: contacts2[contacts.length - 1].createdAt.getTime() - 86400,
705
705
  });
706
706
  const edges = await opts.newQuery(getViewer(), user).queryEdges();
707
707
  // confirm there are duplicates...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -102,7 +102,8 @@ async function createAllContacts(opts) {
102
102
  let userInputs = exports.inputs.slice(0, slice || exports.inputs.length);
103
103
  const contacts = await Promise.all(userInputs.map(async (input) => {
104
104
  // just to make times deterministic so that tests can consistently work
105
- (0, jest_date_mock_1.advanceBy)(100);
105
+ // doing a day so we can do time range queries more easily
106
+ (0, jest_date_mock_1.advanceBy)(86400);
106
107
  const builder = (0, _1.getContactBuilder)(userr.viewer, getContactInput(userr, input));
107
108
  // add edge from user to contact
108
109
  builder.orchestrator.addInboundEdge(userr.id, _1.EdgeType.UserToContacts, const_1.NodeType.FakeUser, {