@snowtop/ent 0.1.0-alpha99 → 0.1.0
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/action/action.d.ts +8 -1
- package/action/executor.d.ts +16 -3
- package/action/executor.js +83 -27
- package/action/index.d.ts +2 -1
- package/action/operations.d.ts +126 -0
- package/action/operations.js +686 -0
- package/action/orchestrator.d.ts +22 -8
- package/action/orchestrator.js +278 -67
- package/core/base.d.ts +34 -24
- package/core/clause.d.ts +62 -79
- package/core/clause.js +77 -5
- package/core/config.d.ts +5 -1
- package/core/config.js +3 -0
- package/core/const.d.ts +3 -0
- package/core/const.js +6 -0
- package/core/context.d.ts +4 -3
- package/core/context.js +2 -1
- package/core/db.d.ts +1 -0
- package/core/db.js +7 -7
- package/core/ent.d.ts +53 -105
- package/core/ent.js +104 -599
- package/core/global_schema.d.ts +7 -0
- package/core/global_schema.js +51 -0
- package/core/loaders/assoc_count_loader.d.ts +4 -2
- package/core/loaders/assoc_count_loader.js +10 -2
- package/core/loaders/assoc_edge_loader.d.ts +2 -3
- package/core/loaders/assoc_edge_loader.js +16 -7
- package/core/loaders/index.d.ts +0 -1
- package/core/loaders/index.js +1 -3
- package/core/loaders/loader.d.ts +3 -3
- package/core/loaders/loader.js +3 -20
- package/core/loaders/object_loader.d.ts +30 -10
- package/core/loaders/object_loader.js +179 -40
- package/core/loaders/query_loader.d.ts +4 -4
- package/core/loaders/query_loader.js +14 -19
- package/core/loaders/raw_count_loader.d.ts +1 -0
- package/core/loaders/raw_count_loader.js +3 -2
- package/core/privacy.d.ts +19 -10
- package/core/privacy.js +47 -26
- package/core/query/assoc_query.js +1 -1
- package/core/query/custom_clause_query.d.ts +6 -3
- package/core/query/custom_clause_query.js +36 -9
- package/core/query/custom_query.d.ts +3 -1
- package/core/query/custom_query.js +29 -6
- package/core/query/query.d.ts +12 -2
- package/core/query/query.js +67 -38
- package/core/query/shared_assoc_test.js +151 -10
- package/core/query/shared_test.d.ts +2 -2
- package/core/query/shared_test.js +90 -30
- package/core/query_impl.d.ts +8 -0
- package/core/query_impl.js +28 -0
- package/core/viewer.d.ts +2 -0
- package/core/viewer.js +2 -0
- package/graphql/graphql.d.ts +103 -19
- package/graphql/graphql.js +169 -134
- package/graphql/graphql_field_helpers.d.ts +9 -3
- package/graphql/graphql_field_helpers.js +22 -2
- package/graphql/index.d.ts +2 -1
- package/graphql/index.js +5 -2
- package/graphql/scalars/orderby_direction.d.ts +2 -0
- package/graphql/scalars/orderby_direction.js +15 -0
- package/imports/dataz/example1/_auth.js +128 -47
- package/imports/dataz/example1/_viewer.js +87 -39
- package/imports/index.d.ts +1 -1
- package/imports/index.js +2 -2
- package/index.d.ts +12 -1
- package/index.js +18 -6
- package/package.json +20 -17
- package/parse_schema/parse.d.ts +10 -4
- package/parse_schema/parse.js +70 -24
- package/schema/base_schema.d.ts +8 -0
- package/schema/base_schema.js +11 -0
- package/schema/field.d.ts +6 -3
- package/schema/field.js +72 -17
- package/schema/index.d.ts +1 -1
- package/schema/index.js +2 -1
- package/schema/json_field.d.ts +3 -3
- package/schema/json_field.js +4 -1
- package/schema/schema.d.ts +42 -5
- package/schema/schema.js +35 -41
- package/schema/struct_field.d.ts +8 -6
- package/schema/struct_field.js +67 -8
- package/schema/union_field.d.ts +1 -1
- package/scripts/custom_compiler.js +4 -4
- package/scripts/custom_graphql.js +105 -75
- package/scripts/move_types.js +4 -1
- package/scripts/read_schema.js +2 -2
- package/testutils/action/complex_schemas.d.ts +1 -1
- package/testutils/action/complex_schemas.js +10 -3
- package/testutils/builder.d.ts +3 -0
- package/testutils/builder.js +6 -0
- package/testutils/db/temp_db.d.ts +9 -1
- package/testutils/db/temp_db.js +82 -14
- package/testutils/db_mock.js +1 -3
- package/testutils/ent-graphql-tests/index.d.ts +1 -1
- package/testutils/ent-graphql-tests/index.js +30 -19
- package/testutils/fake_comms.js +1 -1
- package/testutils/fake_data/fake_contact.d.ts +1 -1
- package/testutils/fake_data/fake_tag.d.ts +1 -1
- package/testutils/fake_data/fake_user.d.ts +3 -3
- package/testutils/fake_data/fake_user.js +15 -4
- package/testutils/fake_data/tag_query.js +8 -3
- package/testutils/fake_data/test_helpers.d.ts +3 -2
- package/testutils/fake_data/test_helpers.js +4 -4
- package/testutils/fake_data/user_query.d.ts +5 -2
- package/testutils/fake_data/user_query.js +19 -2
- package/testutils/fake_log.js +1 -1
- package/tsc/ast.js +2 -1
- package/tsc/move_generated.js +2 -2
- package/tsc/transform.d.ts +2 -2
- package/tsc/transform.js +4 -3
- package/tsc/transform_ent.js +2 -1
- package/tsc/transform_schema.js +4 -3
- package/core/loaders/index_loader.d.ts +0 -14
- package/core/loaders/index_loader.js +0 -27
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assocTests = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
4
5
|
const ent_1 = require("../ent");
|
|
5
6
|
const viewer_1 = require("../viewer");
|
|
6
7
|
const jest_date_mock_1 = require("jest-date-mock");
|
|
7
8
|
const index_1 = require("../../testutils/fake_data/index");
|
|
8
9
|
const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
|
|
9
10
|
const clause_1 = require("../clause");
|
|
11
|
+
const builder_1 = require("../../testutils/builder");
|
|
12
|
+
const luxon_1 = require("luxon");
|
|
13
|
+
const convert_1 = require("../convert");
|
|
10
14
|
function assocTests(ml, global = false) {
|
|
11
15
|
ml.mock();
|
|
12
16
|
describe("custom edge", () => {
|
|
@@ -52,7 +56,7 @@ function assocTests(ml, global = false) {
|
|
|
52
56
|
let execArray = /^SELECT (.+) FROM (.+) WHERE (.+)?/.exec(query.query);
|
|
53
57
|
return execArray?.[3];
|
|
54
58
|
}
|
|
55
|
-
function verifyQuery({ length = 1, numQueries = 1, limit = ent_1.
|
|
59
|
+
function verifyQuery({ length = 1, numQueries = 1, limit = (0, ent_1.getDefaultLimit)(), disablePaginationBump = false, }) {
|
|
56
60
|
expect(ml.logs.length).toBe(length);
|
|
57
61
|
for (let i = 0; i < numQueries; i++) {
|
|
58
62
|
const whereClause = getWhereClause(ml.logs[i]);
|
|
@@ -118,7 +122,7 @@ function assocTests(ml, global = false) {
|
|
|
118
122
|
verifyQuery({
|
|
119
123
|
length: this.dataz.length,
|
|
120
124
|
numQueries: this.dataz.length,
|
|
121
|
-
limit: this.limit || ent_1.
|
|
125
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
// rawCount isn't affected by filters...
|
|
@@ -141,7 +145,7 @@ function assocTests(ml, global = false) {
|
|
|
141
145
|
verifyQuery({
|
|
142
146
|
length: this.dataz.length,
|
|
143
147
|
numQueries: this.dataz.length,
|
|
144
|
-
limit: this.limit || ent_1.
|
|
148
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
145
149
|
});
|
|
146
150
|
}
|
|
147
151
|
async testEdges() {
|
|
@@ -154,7 +158,7 @@ function assocTests(ml, global = false) {
|
|
|
154
158
|
verifyQuery({
|
|
155
159
|
length: this.dataz.length,
|
|
156
160
|
numQueries: this.dataz.length,
|
|
157
|
-
limit: this.limit || ent_1.
|
|
161
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
158
162
|
});
|
|
159
163
|
}
|
|
160
164
|
async testEnts() {
|
|
@@ -178,7 +182,7 @@ function assocTests(ml, global = false) {
|
|
|
178
182
|
// and then twice to fetch all the nodes for the contacts
|
|
179
183
|
length: this.dataz.length + this.dataz.length + this.dataz.length * 2,
|
|
180
184
|
numQueries: this.dataz.length,
|
|
181
|
-
limit: this.limit || ent_1.
|
|
185
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
182
186
|
});
|
|
183
187
|
}
|
|
184
188
|
}
|
|
@@ -464,7 +468,7 @@ function assocTests(ml, global = false) {
|
|
|
464
468
|
verifyQuery({
|
|
465
469
|
length: 1,
|
|
466
470
|
numQueries: 1,
|
|
467
|
-
limit: this.limit || ent_1.
|
|
471
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
468
472
|
});
|
|
469
473
|
}
|
|
470
474
|
// rawCount isn't affected by filters...
|
|
@@ -479,7 +483,7 @@ function assocTests(ml, global = false) {
|
|
|
479
483
|
verifyQuery({
|
|
480
484
|
length: 1,
|
|
481
485
|
numQueries: 1,
|
|
482
|
-
limit: this.limit || ent_1.
|
|
486
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
483
487
|
});
|
|
484
488
|
}
|
|
485
489
|
async testEdges() {
|
|
@@ -500,7 +504,7 @@ function assocTests(ml, global = false) {
|
|
|
500
504
|
verifyQuery({
|
|
501
505
|
length: 1,
|
|
502
506
|
numQueries: 1,
|
|
503
|
-
limit: this.limit || ent_1.
|
|
507
|
+
limit: this.limit || (0, ent_1.getDefaultLimit)(),
|
|
504
508
|
});
|
|
505
509
|
}
|
|
506
510
|
async testEnts() {
|
|
@@ -524,7 +528,7 @@ function assocTests(ml, global = false) {
|
|
|
524
528
|
// // 1 for edges, 1 for users, 1 for events
|
|
525
529
|
// length: 3,
|
|
526
530
|
// numQueries: 3,
|
|
527
|
-
// limit: this.limit ||
|
|
531
|
+
// limit: this.limit || getDefaultLimit(),
|
|
528
532
|
// });
|
|
529
533
|
}
|
|
530
534
|
}
|
|
@@ -632,7 +636,7 @@ function assocTests(ml, global = false) {
|
|
|
632
636
|
expect(countMap.get(user.id)).toBe(friendRequests.length);
|
|
633
637
|
expect(countMap.get(user2.id)).toBe(0);
|
|
634
638
|
});
|
|
635
|
-
test("count", async () => {
|
|
639
|
+
test("raw count", async () => {
|
|
636
640
|
const countMap = await getQuery().queryAllRawCount();
|
|
637
641
|
expect(countMap.size).toBe(2);
|
|
638
642
|
expect(countMap.get(user.id)).toBe(friendRequests.length);
|
|
@@ -659,5 +663,142 @@ function assocTests(ml, global = false) {
|
|
|
659
663
|
expect(entsMapFromUserVCToken.get(user2.id)?.length).toBe(0);
|
|
660
664
|
});
|
|
661
665
|
});
|
|
666
|
+
if (!global) {
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
// global only tests here
|
|
670
|
+
describe("deleted edges", () => {
|
|
671
|
+
let user;
|
|
672
|
+
let friendRequests;
|
|
673
|
+
let user2;
|
|
674
|
+
let postDeletedCount;
|
|
675
|
+
beforeEach(async () => {
|
|
676
|
+
[user, friendRequests] = await (0, test_helpers_1.createUserPlusFriendRequests)();
|
|
677
|
+
user2 = await (0, test_helpers_1.createTestUser)();
|
|
678
|
+
postDeletedCount = Math.floor(friendRequests.length / 2);
|
|
679
|
+
});
|
|
680
|
+
async function deleteEdges() {
|
|
681
|
+
const action = new builder_1.SimpleAction(user.viewer, index_1.FakeUserSchema, new Map(), base_1.WriteOperation.Edit, user);
|
|
682
|
+
for (let i = 0; i < friendRequests.length; i++) {
|
|
683
|
+
if (i % 2 == 0) {
|
|
684
|
+
action.builder.orchestrator.removeInboundEdge(friendRequests[i].id, index_1.EdgeType.UserToFriendRequests);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
await action.saveX();
|
|
688
|
+
}
|
|
689
|
+
function getQuery(viewer) {
|
|
690
|
+
return index_1.UserToIncomingFriendRequestsQuery.query(viewer, user.id);
|
|
691
|
+
}
|
|
692
|
+
test("ids", async () => {
|
|
693
|
+
const ids = await getQuery(user.viewer).queryIDs();
|
|
694
|
+
expect(ids.length).toBe(friendRequests.length);
|
|
695
|
+
});
|
|
696
|
+
test("ids after deleted", async () => {
|
|
697
|
+
await deleteEdges();
|
|
698
|
+
const idsFromUser = await getQuery(user.viewer).queryIDs();
|
|
699
|
+
expect(idsFromUser.length).toBe(postDeletedCount);
|
|
700
|
+
});
|
|
701
|
+
test("ids deleted. fetch deleted anyways", async () => {
|
|
702
|
+
await deleteEdges();
|
|
703
|
+
const idsFromUser = await getQuery(user.viewer)
|
|
704
|
+
.withoutTransformations()
|
|
705
|
+
.queryIDs();
|
|
706
|
+
expect(idsFromUser.length).toBe(friendRequests.length);
|
|
707
|
+
});
|
|
708
|
+
test("count", async () => {
|
|
709
|
+
const count = await getQuery(user.viewer).queryCount();
|
|
710
|
+
expect(count).toBe(friendRequests.length);
|
|
711
|
+
});
|
|
712
|
+
test("count after deleted", async () => {
|
|
713
|
+
await deleteEdges();
|
|
714
|
+
const count = await getQuery(user.viewer).queryCount();
|
|
715
|
+
expect(count).toBe(postDeletedCount);
|
|
716
|
+
});
|
|
717
|
+
test("count after deleted. fetch deleted", async () => {
|
|
718
|
+
await deleteEdges();
|
|
719
|
+
const count = await getQuery(user.viewer)
|
|
720
|
+
.withoutTransformations()
|
|
721
|
+
.queryCount();
|
|
722
|
+
expect(count).toBe(friendRequests.length);
|
|
723
|
+
});
|
|
724
|
+
test("raw count", async () => {
|
|
725
|
+
const count = await getQuery(user.viewer).queryCount();
|
|
726
|
+
expect(count).toBe(friendRequests.length);
|
|
727
|
+
});
|
|
728
|
+
test("raw count after deleted", async () => {
|
|
729
|
+
await deleteEdges();
|
|
730
|
+
const count = await getQuery(user.viewer).queryRawCount();
|
|
731
|
+
expect(count).toBe(postDeletedCount);
|
|
732
|
+
});
|
|
733
|
+
test("raw count after deleted. fetch deleted", async () => {
|
|
734
|
+
await deleteEdges();
|
|
735
|
+
const count = await getQuery(user.viewer)
|
|
736
|
+
.withoutTransformations()
|
|
737
|
+
.queryRawCount();
|
|
738
|
+
expect(count).toBe(friendRequests.length);
|
|
739
|
+
});
|
|
740
|
+
test("edges", async () => {
|
|
741
|
+
const edges = await getQuery(user.viewer).queryEdges();
|
|
742
|
+
expect(edges.length).toBe(friendRequests.length);
|
|
743
|
+
for (const edge of edges) {
|
|
744
|
+
expect(edge.deleted_at).toBeNull();
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
test("edges after deleted", async () => {
|
|
748
|
+
await deleteEdges();
|
|
749
|
+
const edges = await getQuery(user.viewer).queryEdges();
|
|
750
|
+
expect(edges.length).toBe(postDeletedCount);
|
|
751
|
+
for (const edge of edges) {
|
|
752
|
+
expect(edge.deleted_at).toBeNull();
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
test("edges after deleted. fetch deleted", async () => {
|
|
756
|
+
await deleteEdges();
|
|
757
|
+
const edges = await getQuery(user.viewer)
|
|
758
|
+
.withoutTransformations()
|
|
759
|
+
.queryEdges();
|
|
760
|
+
expect(edges.length).toBe(friendRequests.length);
|
|
761
|
+
let notDeletedAtCt = 0;
|
|
762
|
+
for (const edge of edges) {
|
|
763
|
+
if (edge.deleted_at === null) {
|
|
764
|
+
notDeletedAtCt++;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
expect(luxon_1.DateTime.fromJSDate((0, convert_1.convertDate)(edge.deleted_at)).isValid).toBe(true);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
expect(notDeletedAtCt).toBe(postDeletedCount);
|
|
771
|
+
});
|
|
772
|
+
test("ents", async () => {
|
|
773
|
+
const viewer = new index_1.ViewerWithAccessToken(user.id, {
|
|
774
|
+
tokens: {
|
|
775
|
+
allow_incoming_friend_request: true,
|
|
776
|
+
},
|
|
777
|
+
});
|
|
778
|
+
const ents = await getQuery(viewer).queryEnts();
|
|
779
|
+
expect(ents.length).toBe(friendRequests.length);
|
|
780
|
+
});
|
|
781
|
+
test("ents after deleted", async () => {
|
|
782
|
+
await deleteEdges();
|
|
783
|
+
const viewer = new index_1.ViewerWithAccessToken(user.id, {
|
|
784
|
+
tokens: {
|
|
785
|
+
allow_incoming_friend_request: true,
|
|
786
|
+
},
|
|
787
|
+
});
|
|
788
|
+
const ents = await getQuery(viewer).queryEnts();
|
|
789
|
+
expect(ents.length).toBe(postDeletedCount);
|
|
790
|
+
});
|
|
791
|
+
test("ents after deleted. fetch deleted", async () => {
|
|
792
|
+
await deleteEdges();
|
|
793
|
+
const viewer = new index_1.ViewerWithAccessToken(user.id, {
|
|
794
|
+
tokens: {
|
|
795
|
+
allow_incoming_friend_request: true,
|
|
796
|
+
always_allow_user: true,
|
|
797
|
+
},
|
|
798
|
+
});
|
|
799
|
+
const ents = await getQuery(viewer).withoutTransformations().queryEnts();
|
|
800
|
+
expect(ents.length).toBe(friendRequests.length);
|
|
801
|
+
});
|
|
802
|
+
});
|
|
662
803
|
}
|
|
663
804
|
exports.assocTests = assocTests;
|
|
@@ -3,6 +3,7 @@ import { FakeUser, FakeContact } from "../../testutils/fake_data/index";
|
|
|
3
3
|
import { EdgeQuery } from "./query";
|
|
4
4
|
import { MockLogs } from "../../testutils/mock_log";
|
|
5
5
|
import { Clause } from "../clause";
|
|
6
|
+
import { OrderBy } from "../query_impl";
|
|
6
7
|
interface options<TData extends Data> {
|
|
7
8
|
newQuery: (v: Viewer, user: FakeUser) => EdgeQuery<FakeUser, FakeContact, TData>;
|
|
8
9
|
tableName: string;
|
|
@@ -10,11 +11,10 @@ interface options<TData extends Data> {
|
|
|
10
11
|
ml: MockLogs;
|
|
11
12
|
entsLength?: number;
|
|
12
13
|
clause: Clause;
|
|
13
|
-
sortCol: string;
|
|
14
14
|
livePostgresDB?: boolean;
|
|
15
15
|
sqlite?: boolean;
|
|
16
16
|
globalSchema?: boolean;
|
|
17
|
-
orderby:
|
|
17
|
+
orderby: OrderBy;
|
|
18
18
|
rawDataVerify?(user: FakeUser): Promise<void>;
|
|
19
19
|
}
|
|
20
20
|
export declare const commonTests: <TData extends Data>(opts: options<TData>) => void;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commonTests = void 0;
|
|
4
4
|
const ent_1 = require("../ent");
|
|
5
|
+
const global_schema_1 = require("../global_schema");
|
|
5
6
|
const viewer_1 = require("../viewer");
|
|
6
7
|
const index_1 = require("../../testutils/fake_data/index");
|
|
7
8
|
const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
|
|
@@ -12,6 +13,7 @@ const test_edge_global_schema_1 = require("../../testutils/test_edge_global_sche
|
|
|
12
13
|
const builder_1 = require("../../testutils/builder");
|
|
13
14
|
const action_1 = require("../../action");
|
|
14
15
|
const clause_1 = require("../clause");
|
|
16
|
+
const query_impl_1 = require("../query_impl");
|
|
15
17
|
function getWhereClause(query) {
|
|
16
18
|
const idx = query.query.indexOf("WHERE");
|
|
17
19
|
if (idx !== -1) {
|
|
@@ -146,7 +148,7 @@ const commonTests = (opts) => {
|
|
|
146
148
|
this.verifyEnts(ents);
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
|
-
function verifyQuery(filter, { length = 1, numQueries = 1, limit = ent_1.
|
|
151
|
+
function verifyQuery(filter, { length = 1, numQueries = 1, limit = (0, ent_1.getDefaultLimit)(), disablePaginationBump = false, orderby = opts.orderby, }) {
|
|
150
152
|
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
151
153
|
expect(ml.logs.length).toBe(length);
|
|
152
154
|
for (let i = 0; i < numQueries; i++) {
|
|
@@ -154,7 +156,7 @@ const commonTests = (opts) => {
|
|
|
154
156
|
let expLimit = disablePaginationBump ? limit : limit + 1;
|
|
155
157
|
expect(whereClause, `${i}`).toBe(
|
|
156
158
|
// default limit
|
|
157
|
-
`${opts.clause.clause(1)} ORDER BY ${
|
|
159
|
+
`${opts.clause.clause(1)} ORDER BY ${(0, query_impl_1.getOrderByPhrase)(orderby)}, ${uniqCol} ${orderby[0].direction} LIMIT ${expLimit}`);
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
function verifyCountQuery({ length = 1, numQueries = 1 }) {
|
|
@@ -169,7 +171,7 @@ const commonTests = (opts) => {
|
|
|
169
171
|
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
170
172
|
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
171
173
|
let parts = opts.clause.clause(1).split(" AND ");
|
|
172
|
-
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(opts.
|
|
174
|
+
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(opts.orderby[0].column, opts.orderby[0].direction === "DESC" ? "<" : ">", opts.tableName, uniqCol, "").clause(opts.clause.values().length + 1);
|
|
173
175
|
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
174
176
|
parts = parts
|
|
175
177
|
.slice(0, parts.length - 1)
|
|
@@ -178,24 +180,14 @@ const commonTests = (opts) => {
|
|
|
178
180
|
else {
|
|
179
181
|
parts.push(cmp);
|
|
180
182
|
}
|
|
181
|
-
expect(getWhereClause(ml.logs[0])).toBe(`${parts.join(" AND ")} ORDER BY ${
|
|
183
|
+
expect(getWhereClause(ml.logs[0])).toBe(`${parts.join(" AND ")} ORDER BY ${(0, query_impl_1.getOrderByPhrase)(opts.orderby)}, ${uniqCol} ${opts.orderby[0].direction} LIMIT ${limit + 1}`);
|
|
182
184
|
}
|
|
183
|
-
function verifyLastBeforeCursorQuery(filter, length = 1, limit = 3) {
|
|
185
|
+
function verifyLastBeforeCursorQuery(filter, { length = 1, limit = 3, orderby = opts.orderby }) {
|
|
184
186
|
// cache showing up in a few because of cross runs...
|
|
185
187
|
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
186
188
|
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
187
|
-
let op = "";
|
|
188
|
-
let orderby = "";
|
|
189
|
-
if (opts.orderby === "DESC") {
|
|
190
|
-
op = ">";
|
|
191
|
-
orderby = "ASC";
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
op = "<";
|
|
195
|
-
orderby = "DESC";
|
|
196
|
-
}
|
|
197
189
|
let parts = opts.clause.clause(1).split(" AND ");
|
|
198
|
-
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(
|
|
190
|
+
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(orderby[0].column, orderby[0].direction === "ASC" ? ">" : "<", opts.tableName, uniqCol, "").clause(opts.clause.values().length + 1);
|
|
199
191
|
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
200
192
|
parts = parts
|
|
201
193
|
.slice(0, parts.length - 1)
|
|
@@ -206,7 +198,7 @@ const commonTests = (opts) => {
|
|
|
206
198
|
}
|
|
207
199
|
expect(getWhereClause(ml.logs[0])).toBe(
|
|
208
200
|
// extra fetched for pagination
|
|
209
|
-
`${parts.join(" AND ")} ORDER BY ${
|
|
201
|
+
`${parts.join(" AND ")} ORDER BY ${(0, query_impl_1.getOrderByPhrase)(orderby)}, ${uniqCol} ${orderby[0].direction} LIMIT ${limit + 1}`);
|
|
210
202
|
}
|
|
211
203
|
function getViewer() {
|
|
212
204
|
return new viewer_1.LoggedOutViewer();
|
|
@@ -273,12 +265,17 @@ const commonTests = (opts) => {
|
|
|
273
265
|
expect(pagination?.hasPreviousPage, `${i}`).toBe(undefined);
|
|
274
266
|
expect(pagination?.hasNextPage, `${i}`).toBe(undefined);
|
|
275
267
|
}
|
|
268
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
276
269
|
if (cursor) {
|
|
277
|
-
verifyLastBeforeCursorQuery(query,
|
|
270
|
+
verifyLastBeforeCursorQuery(query, {
|
|
271
|
+
length: 1,
|
|
272
|
+
limit: pageLength,
|
|
273
|
+
orderby,
|
|
274
|
+
});
|
|
278
275
|
}
|
|
279
276
|
else {
|
|
280
277
|
verifyQuery(query, {
|
|
281
|
-
orderby
|
|
278
|
+
orderby,
|
|
282
279
|
limit: pageLength,
|
|
283
280
|
});
|
|
284
281
|
}
|
|
@@ -289,7 +286,7 @@ const commonTests = (opts) => {
|
|
|
289
286
|
return { verify, getCursor };
|
|
290
287
|
}
|
|
291
288
|
if (opts.globalSchema) {
|
|
292
|
-
(0,
|
|
289
|
+
(0, global_schema_1.setGlobalSchema)(test_edge_global_schema_1.testEdgeGlobalSchema);
|
|
293
290
|
}
|
|
294
291
|
let tdb;
|
|
295
292
|
if (opts.sqlite) {
|
|
@@ -316,7 +313,7 @@ const commonTests = (opts) => {
|
|
|
316
313
|
}, opts.newQuery, (contacts) => {
|
|
317
314
|
// nothing to do here
|
|
318
315
|
// reverse because edges are most recent first
|
|
319
|
-
if (opts.orderby === "DESC") {
|
|
316
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
320
317
|
return contacts.reverse();
|
|
321
318
|
}
|
|
322
319
|
return contacts;
|
|
@@ -354,6 +351,68 @@ const commonTests = (opts) => {
|
|
|
354
351
|
await filter.testDataCache();
|
|
355
352
|
});
|
|
356
353
|
});
|
|
354
|
+
describe("override default limit", () => {
|
|
355
|
+
const filter = new TestQueryFilter((q) => {
|
|
356
|
+
// no filters
|
|
357
|
+
return q;
|
|
358
|
+
}, opts.newQuery, (contacts) => {
|
|
359
|
+
// nothing to do here
|
|
360
|
+
// reverse because edges are most recent first
|
|
361
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
362
|
+
return contacts.reverse();
|
|
363
|
+
}
|
|
364
|
+
return contacts;
|
|
365
|
+
}, getViewer());
|
|
366
|
+
const OUR_DEFAULT_LIMIT = 10;
|
|
367
|
+
beforeAll(async () => {
|
|
368
|
+
(0, ent_1.setDefaultLimit)(OUR_DEFAULT_LIMIT);
|
|
369
|
+
});
|
|
370
|
+
afterAll(async () => {
|
|
371
|
+
//set it back to real default
|
|
372
|
+
(0, ent_1.setDefaultLimit)(1000);
|
|
373
|
+
});
|
|
374
|
+
beforeEach(async () => {
|
|
375
|
+
await filter.createData();
|
|
376
|
+
});
|
|
377
|
+
test("ids", async () => {
|
|
378
|
+
await filter.testIDs();
|
|
379
|
+
verifyQuery(filter, {
|
|
380
|
+
limit: OUR_DEFAULT_LIMIT,
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
test("rawCount", async () => {
|
|
384
|
+
await filter.testRawCount();
|
|
385
|
+
verifyCountQuery({});
|
|
386
|
+
});
|
|
387
|
+
test("count", async () => {
|
|
388
|
+
await filter.testCount();
|
|
389
|
+
verifyQuery(filter, {
|
|
390
|
+
limit: OUR_DEFAULT_LIMIT,
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
test("edges", async () => {
|
|
394
|
+
await filter.testEdges();
|
|
395
|
+
verifyQuery(filter, {
|
|
396
|
+
limit: OUR_DEFAULT_LIMIT,
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
test("ents", async () => {
|
|
400
|
+
await filter.testEnts();
|
|
401
|
+
verifyQuery(filter, {
|
|
402
|
+
length: opts.entsLength,
|
|
403
|
+
limit: OUR_DEFAULT_LIMIT,
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
test("all", async () => {
|
|
407
|
+
await filter.testAll();
|
|
408
|
+
});
|
|
409
|
+
test("ents cache", async () => {
|
|
410
|
+
await filter.testEntsCache();
|
|
411
|
+
});
|
|
412
|
+
test("data cache", async () => {
|
|
413
|
+
await filter.testDataCache();
|
|
414
|
+
});
|
|
415
|
+
});
|
|
357
416
|
describe("after delete", () => {
|
|
358
417
|
const filter = new TestQueryFilter((q) => {
|
|
359
418
|
// no filters
|
|
@@ -415,7 +474,7 @@ const commonTests = (opts) => {
|
|
|
415
474
|
// no filters
|
|
416
475
|
return q.first(N);
|
|
417
476
|
}, opts.newQuery, (contacts) => {
|
|
418
|
-
if (opts.orderby === "DESC") {
|
|
477
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
419
478
|
return contacts.reverse().slice(0, N);
|
|
420
479
|
}
|
|
421
480
|
return contacts.slice(0, N);
|
|
@@ -459,14 +518,14 @@ const commonTests = (opts) => {
|
|
|
459
518
|
// no filters
|
|
460
519
|
return q.last(N);
|
|
461
520
|
}, opts.newQuery, (contacts) => {
|
|
462
|
-
if (opts.orderby === "DESC") {
|
|
521
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
463
522
|
return contacts.slice(0, N);
|
|
464
523
|
}
|
|
465
524
|
else {
|
|
466
525
|
return contacts.reverse().slice(0, N);
|
|
467
526
|
}
|
|
468
527
|
}, getViewer());
|
|
469
|
-
const orderby = opts.orderby
|
|
528
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
470
529
|
beforeEach(async () => {
|
|
471
530
|
await filter.createData();
|
|
472
531
|
});
|
|
@@ -513,7 +572,7 @@ const commonTests = (opts) => {
|
|
|
513
572
|
const filter = new TestQueryFilter((q, user, contacts) => {
|
|
514
573
|
return q.first(N, getCursorFrom(contacts, idx));
|
|
515
574
|
}, opts.newQuery, (contacts) => {
|
|
516
|
-
if (opts.orderby === "DESC") {
|
|
575
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
517
576
|
// < check so we shouldn't get that index
|
|
518
577
|
return contacts.reverse().slice(idx + 1, idx + N);
|
|
519
578
|
}
|
|
@@ -575,11 +634,12 @@ const commonTests = (opts) => {
|
|
|
575
634
|
return q.last(N, getCursorFrom(contacts, idx));
|
|
576
635
|
}, opts.newQuery, (contacts) => {
|
|
577
636
|
// > check so we don't want that index
|
|
578
|
-
if (opts.orderby === "DESC") {
|
|
637
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
579
638
|
return contacts.reverse().slice(0, idx).reverse(); // because of order returned
|
|
580
639
|
}
|
|
581
640
|
return contacts.slice(0, idx).reverse(); // because of order returned
|
|
582
641
|
}, getViewer());
|
|
642
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
583
643
|
beforeAll(async () => {
|
|
584
644
|
if (opts.livePostgresDB || opts.sqlite) {
|
|
585
645
|
await filter.createData();
|
|
@@ -590,7 +650,7 @@ const commonTests = (opts) => {
|
|
|
590
650
|
});
|
|
591
651
|
test("ids", async () => {
|
|
592
652
|
await filter.testIDs();
|
|
593
|
-
verifyLastBeforeCursorQuery(filter);
|
|
653
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
594
654
|
});
|
|
595
655
|
test("rawCount", async () => {
|
|
596
656
|
await filter.testRawCount();
|
|
@@ -598,15 +658,15 @@ const commonTests = (opts) => {
|
|
|
598
658
|
});
|
|
599
659
|
test("count", async () => {
|
|
600
660
|
await filter.testCount();
|
|
601
|
-
verifyLastBeforeCursorQuery(filter);
|
|
661
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
602
662
|
});
|
|
603
663
|
test("edges", async () => {
|
|
604
664
|
await filter.testEdges();
|
|
605
|
-
verifyLastBeforeCursorQuery(filter);
|
|
665
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
606
666
|
});
|
|
607
667
|
test("ents", async () => {
|
|
608
668
|
await filter.testEnts();
|
|
609
|
-
verifyLastBeforeCursorQuery(filter,
|
|
669
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
610
670
|
});
|
|
611
671
|
test("all", async () => {
|
|
612
672
|
await filter.testAll();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface OrderByOption {
|
|
2
|
+
column: string;
|
|
3
|
+
direction: "ASC" | "DESC";
|
|
4
|
+
nullsPlacement?: "first" | "last";
|
|
5
|
+
}
|
|
6
|
+
export type OrderBy = OrderByOption[];
|
|
7
|
+
export declare function getOrderByPhrase(orderby: OrderBy): string;
|
|
8
|
+
export declare function reverseOrderBy(orderby: OrderBy): OrderBy;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reverseOrderBy = exports.getOrderByPhrase = void 0;
|
|
4
|
+
function getOrderByPhrase(orderby) {
|
|
5
|
+
return orderby
|
|
6
|
+
.map((v) => {
|
|
7
|
+
let nullsPlacement = "";
|
|
8
|
+
switch (v.nullsPlacement) {
|
|
9
|
+
case "first":
|
|
10
|
+
nullsPlacement = " NULLS FIRST";
|
|
11
|
+
break;
|
|
12
|
+
case "last":
|
|
13
|
+
nullsPlacement = " NULLS LAST";
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
return `${v.column} ${v.direction}${nullsPlacement}`;
|
|
17
|
+
})
|
|
18
|
+
.join(", ");
|
|
19
|
+
}
|
|
20
|
+
exports.getOrderByPhrase = getOrderByPhrase;
|
|
21
|
+
function reverseOrderBy(orderby) {
|
|
22
|
+
return orderby.map((o) => {
|
|
23
|
+
const o2 = { ...o };
|
|
24
|
+
o2.direction = o.direction === "ASC" ? "DESC" : "ASC";
|
|
25
|
+
return o2;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
exports.reverseOrderBy = reverseOrderBy;
|
package/core/viewer.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ID, Ent, Viewer, Context } from "./base";
|
|
2
2
|
export declare class LoggedOutViewer implements Viewer {
|
|
3
3
|
context?: Context<Viewer<Ent<any> | null, ID | null>> | undefined;
|
|
4
|
+
marker: string;
|
|
4
5
|
constructor(context?: Context<Viewer<Ent<any> | null, ID | null>> | undefined);
|
|
5
6
|
viewerID: null;
|
|
6
7
|
viewer(): Promise<null>;
|
|
@@ -12,6 +13,7 @@ export interface IDViewerOptions {
|
|
|
12
13
|
ent?: Ent | null;
|
|
13
14
|
}
|
|
14
15
|
export declare class IDViewer implements Viewer {
|
|
16
|
+
marker: string;
|
|
15
17
|
viewerID: ID;
|
|
16
18
|
private ent;
|
|
17
19
|
context?: Context;
|
package/core/viewer.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.IDViewer = exports.LoggedOutViewer = void 0;
|
|
|
4
4
|
class LoggedOutViewer {
|
|
5
5
|
constructor(context) {
|
|
6
6
|
this.context = context;
|
|
7
|
+
this.marker = "loggedout";
|
|
7
8
|
this.viewerID = null;
|
|
8
9
|
}
|
|
9
10
|
async viewer() {
|
|
@@ -16,6 +17,7 @@ class LoggedOutViewer {
|
|
|
16
17
|
exports.LoggedOutViewer = LoggedOutViewer;
|
|
17
18
|
class IDViewer {
|
|
18
19
|
constructor(args, opts) {
|
|
20
|
+
this.marker = "idviewer";
|
|
19
21
|
this.ent = null;
|
|
20
22
|
if (typeof args === "object") {
|
|
21
23
|
this.viewerID = args.viewerID;
|