@snowtop/ent 0.1.0-alpha151 → 0.1.0-alpha153
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/index.d.ts +1 -0
- package/action/operations.d.ts +3 -2
- package/action/operations.js +8 -6
- package/action/orchestrator.d.ts +5 -0
- package/action/orchestrator.js +37 -5
- package/core/base.d.ts +5 -3
- package/core/context.d.ts +2 -1
- package/core/context.js +2 -1
- package/core/ent.d.ts +3 -3
- package/core/ent.js +10 -4
- 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 +14 -4
- package/core/loaders/index_loader.d.ts +2 -1
- package/core/loaders/index_loader.js +1 -1
- package/core/loaders/query_loader.d.ts +3 -3
- package/core/loaders/query_loader.js +11 -16
- package/core/privacy.d.ts +19 -10
- package/core/privacy.js +33 -21
- package/core/query/assoc_query.js +1 -1
- package/core/query/custom_clause_query.d.ts +4 -2
- package/core/query/custom_clause_query.js +32 -15
- package/core/query/custom_query.d.ts +3 -1
- package/core/query/custom_query.js +28 -5
- package/core/query/query.d.ts +6 -4
- package/core/query/query.js +51 -46
- package/core/query/shared_assoc_test.js +142 -1
- package/core/query/shared_test.d.ts +2 -2
- package/core/query/shared_test.js +26 -29
- package/core/query_impl.d.ts +8 -0
- package/core/query_impl.js +28 -0
- package/graphql/index.d.ts +1 -1
- package/graphql/index.js +3 -1
- package/graphql/scalars/orderby_direction.js +2 -2
- package/package.json +1 -1
- package/parse_schema/parse.d.ts +1 -0
- package/parse_schema/parse.js +1 -0
- 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 +3 -3
- package/testutils/fake_data/user_query.d.ts +5 -2
- package/testutils/fake_data/user_query.js +19 -2
|
@@ -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", () => {
|
|
@@ -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;
|
|
@@ -13,6 +13,7 @@ const test_edge_global_schema_1 = require("../../testutils/test_edge_global_sche
|
|
|
13
13
|
const builder_1 = require("../../testutils/builder");
|
|
14
14
|
const action_1 = require("../../action");
|
|
15
15
|
const clause_1 = require("../clause");
|
|
16
|
+
const query_impl_1 = require("../query_impl");
|
|
16
17
|
function getWhereClause(query) {
|
|
17
18
|
const idx = query.query.indexOf("WHERE");
|
|
18
19
|
if (idx !== -1) {
|
|
@@ -155,7 +156,7 @@ const commonTests = (opts) => {
|
|
|
155
156
|
let expLimit = disablePaginationBump ? limit : limit + 1;
|
|
156
157
|
expect(whereClause, `${i}`).toBe(
|
|
157
158
|
// default limit
|
|
158
|
-
`${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}`);
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
function verifyCountQuery({ length = 1, numQueries = 1 }) {
|
|
@@ -170,7 +171,7 @@ const commonTests = (opts) => {
|
|
|
170
171
|
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
171
172
|
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
172
173
|
let parts = opts.clause.clause(1).split(" AND ");
|
|
173
|
-
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);
|
|
174
175
|
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
175
176
|
parts = parts
|
|
176
177
|
.slice(0, parts.length - 1)
|
|
@@ -179,24 +180,14 @@ const commonTests = (opts) => {
|
|
|
179
180
|
else {
|
|
180
181
|
parts.push(cmp);
|
|
181
182
|
}
|
|
182
|
-
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}`);
|
|
183
184
|
}
|
|
184
|
-
function verifyLastBeforeCursorQuery(filter, length = 1, limit = 3) {
|
|
185
|
+
function verifyLastBeforeCursorQuery(filter, { length = 1, limit = 3, orderby = opts.orderby }) {
|
|
185
186
|
// cache showing up in a few because of cross runs...
|
|
186
187
|
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
187
188
|
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
188
|
-
let op = "";
|
|
189
|
-
let orderby = "";
|
|
190
|
-
if (opts.orderby === "DESC") {
|
|
191
|
-
op = ">";
|
|
192
|
-
orderby = "ASC";
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
op = "<";
|
|
196
|
-
orderby = "DESC";
|
|
197
|
-
}
|
|
198
189
|
let parts = opts.clause.clause(1).split(" AND ");
|
|
199
|
-
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);
|
|
200
191
|
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
201
192
|
parts = parts
|
|
202
193
|
.slice(0, parts.length - 1)
|
|
@@ -207,7 +198,7 @@ const commonTests = (opts) => {
|
|
|
207
198
|
}
|
|
208
199
|
expect(getWhereClause(ml.logs[0])).toBe(
|
|
209
200
|
// extra fetched for pagination
|
|
210
|
-
`${parts.join(" AND ")} ORDER BY ${
|
|
201
|
+
`${parts.join(" AND ")} ORDER BY ${(0, query_impl_1.getOrderByPhrase)(orderby)}, ${uniqCol} ${orderby[0].direction} LIMIT ${limit + 1}`);
|
|
211
202
|
}
|
|
212
203
|
function getViewer() {
|
|
213
204
|
return new viewer_1.LoggedOutViewer();
|
|
@@ -274,12 +265,17 @@ const commonTests = (opts) => {
|
|
|
274
265
|
expect(pagination?.hasPreviousPage, `${i}`).toBe(undefined);
|
|
275
266
|
expect(pagination?.hasNextPage, `${i}`).toBe(undefined);
|
|
276
267
|
}
|
|
268
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
277
269
|
if (cursor) {
|
|
278
|
-
verifyLastBeforeCursorQuery(query,
|
|
270
|
+
verifyLastBeforeCursorQuery(query, {
|
|
271
|
+
length: 1,
|
|
272
|
+
limit: pageLength,
|
|
273
|
+
orderby,
|
|
274
|
+
});
|
|
279
275
|
}
|
|
280
276
|
else {
|
|
281
277
|
verifyQuery(query, {
|
|
282
|
-
orderby
|
|
278
|
+
orderby,
|
|
283
279
|
limit: pageLength,
|
|
284
280
|
});
|
|
285
281
|
}
|
|
@@ -317,7 +313,7 @@ const commonTests = (opts) => {
|
|
|
317
313
|
}, opts.newQuery, (contacts) => {
|
|
318
314
|
// nothing to do here
|
|
319
315
|
// reverse because edges are most recent first
|
|
320
|
-
if (opts.orderby === "DESC") {
|
|
316
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
321
317
|
return contacts.reverse();
|
|
322
318
|
}
|
|
323
319
|
return contacts;
|
|
@@ -362,7 +358,7 @@ const commonTests = (opts) => {
|
|
|
362
358
|
}, opts.newQuery, (contacts) => {
|
|
363
359
|
// nothing to do here
|
|
364
360
|
// reverse because edges are most recent first
|
|
365
|
-
if (opts.orderby === "DESC") {
|
|
361
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
366
362
|
return contacts.reverse();
|
|
367
363
|
}
|
|
368
364
|
return contacts;
|
|
@@ -478,7 +474,7 @@ const commonTests = (opts) => {
|
|
|
478
474
|
// no filters
|
|
479
475
|
return q.first(N);
|
|
480
476
|
}, opts.newQuery, (contacts) => {
|
|
481
|
-
if (opts.orderby === "DESC") {
|
|
477
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
482
478
|
return contacts.reverse().slice(0, N);
|
|
483
479
|
}
|
|
484
480
|
return contacts.slice(0, N);
|
|
@@ -522,14 +518,14 @@ const commonTests = (opts) => {
|
|
|
522
518
|
// no filters
|
|
523
519
|
return q.last(N);
|
|
524
520
|
}, opts.newQuery, (contacts) => {
|
|
525
|
-
if (opts.orderby === "DESC") {
|
|
521
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
526
522
|
return contacts.slice(0, N);
|
|
527
523
|
}
|
|
528
524
|
else {
|
|
529
525
|
return contacts.reverse().slice(0, N);
|
|
530
526
|
}
|
|
531
527
|
}, getViewer());
|
|
532
|
-
const orderby = opts.orderby
|
|
528
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
533
529
|
beforeEach(async () => {
|
|
534
530
|
await filter.createData();
|
|
535
531
|
});
|
|
@@ -576,7 +572,7 @@ const commonTests = (opts) => {
|
|
|
576
572
|
const filter = new TestQueryFilter((q, user, contacts) => {
|
|
577
573
|
return q.first(N, getCursorFrom(contacts, idx));
|
|
578
574
|
}, opts.newQuery, (contacts) => {
|
|
579
|
-
if (opts.orderby === "DESC") {
|
|
575
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
580
576
|
// < check so we shouldn't get that index
|
|
581
577
|
return contacts.reverse().slice(idx + 1, idx + N);
|
|
582
578
|
}
|
|
@@ -638,11 +634,12 @@ const commonTests = (opts) => {
|
|
|
638
634
|
return q.last(N, getCursorFrom(contacts, idx));
|
|
639
635
|
}, opts.newQuery, (contacts) => {
|
|
640
636
|
// > check so we don't want that index
|
|
641
|
-
if (opts.orderby === "DESC") {
|
|
637
|
+
if (opts.orderby[0].direction === "DESC") {
|
|
642
638
|
return contacts.reverse().slice(0, idx).reverse(); // because of order returned
|
|
643
639
|
}
|
|
644
640
|
return contacts.slice(0, idx).reverse(); // because of order returned
|
|
645
641
|
}, getViewer());
|
|
642
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(opts.orderby);
|
|
646
643
|
beforeAll(async () => {
|
|
647
644
|
if (opts.livePostgresDB || opts.sqlite) {
|
|
648
645
|
await filter.createData();
|
|
@@ -653,7 +650,7 @@ const commonTests = (opts) => {
|
|
|
653
650
|
});
|
|
654
651
|
test("ids", async () => {
|
|
655
652
|
await filter.testIDs();
|
|
656
|
-
verifyLastBeforeCursorQuery(filter);
|
|
653
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
657
654
|
});
|
|
658
655
|
test("rawCount", async () => {
|
|
659
656
|
await filter.testRawCount();
|
|
@@ -661,15 +658,15 @@ const commonTests = (opts) => {
|
|
|
661
658
|
});
|
|
662
659
|
test("count", async () => {
|
|
663
660
|
await filter.testCount();
|
|
664
|
-
verifyLastBeforeCursorQuery(filter);
|
|
661
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
665
662
|
});
|
|
666
663
|
test("edges", async () => {
|
|
667
664
|
await filter.testEdges();
|
|
668
|
-
verifyLastBeforeCursorQuery(filter);
|
|
665
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
669
666
|
});
|
|
670
667
|
test("ents", async () => {
|
|
671
668
|
await filter.testEnts();
|
|
672
|
-
verifyLastBeforeCursorQuery(filter,
|
|
669
|
+
verifyLastBeforeCursorQuery(filter, { orderby });
|
|
673
670
|
});
|
|
674
671
|
test("all", async () => {
|
|
675
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/graphql/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { gqlFieldOptions, gqlObjectOptions, gqlField, gqlArgType, gqlInputObjectType, gqlObjectType, gqlQuery, gqlMutation, gqlContextType, gqlConnection, GraphQLConnection, GQLCapture, gqlFileUpload, CustomType, } from "./graphql";
|
|
1
|
+
export { gqlFieldOptions, gqlObjectOptions, gqlField, gqlArgType, gqlInputObjectType, gqlObjectType, gqlQuery, gqlMutation, gqlContextType, gqlConnection, GraphQLConnection, GQLCapture, gqlFileUpload, CustomType, gqlInterfaceType, gqlUnionType, } from "./graphql";
|
|
2
2
|
export { GraphQLTime } from "./scalars/time";
|
|
3
3
|
export { GraphQLOrderByDirection } from "./scalars/orderby_direction";
|
|
4
4
|
export { GraphQLPageInfo } from "./query/page_info";
|
package/graphql/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.transformUnionTypes = exports.encodeGQLID = exports.mustDecodeNullableIDFromGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = exports.GraphQLEdgeInterface = exports.GraphQLConnectionInterface = exports.GraphQLNodeInterface = exports.GraphQLConnectionType = exports.GraphQLEdgeType = exports.GraphQLEdgeConnection = exports.GraphQLPageInfo = exports.GraphQLOrderByDirection = exports.GraphQLTime = exports.gqlFileUpload = exports.GQLCapture = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlField = void 0;
|
|
3
|
+
exports.transformUnionTypes = exports.encodeGQLID = exports.mustDecodeNullableIDFromGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = exports.GraphQLEdgeInterface = exports.GraphQLConnectionInterface = exports.GraphQLNodeInterface = exports.GraphQLConnectionType = exports.GraphQLEdgeType = exports.GraphQLEdgeConnection = exports.GraphQLPageInfo = exports.GraphQLOrderByDirection = exports.GraphQLTime = exports.gqlUnionType = exports.gqlInterfaceType = exports.gqlFileUpload = exports.GQLCapture = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlField = void 0;
|
|
4
4
|
var graphql_1 = require("./graphql");
|
|
5
5
|
Object.defineProperty(exports, "gqlField", { enumerable: true, get: function () { return graphql_1.gqlField; } });
|
|
6
6
|
Object.defineProperty(exports, "gqlArgType", { enumerable: true, get: function () { return graphql_1.gqlArgType; } });
|
|
@@ -12,6 +12,8 @@ Object.defineProperty(exports, "gqlContextType", { enumerable: true, get: functi
|
|
|
12
12
|
Object.defineProperty(exports, "gqlConnection", { enumerable: true, get: function () { return graphql_1.gqlConnection; } });
|
|
13
13
|
Object.defineProperty(exports, "GQLCapture", { enumerable: true, get: function () { return graphql_1.GQLCapture; } });
|
|
14
14
|
Object.defineProperty(exports, "gqlFileUpload", { enumerable: true, get: function () { return graphql_1.gqlFileUpload; } });
|
|
15
|
+
Object.defineProperty(exports, "gqlInterfaceType", { enumerable: true, get: function () { return graphql_1.gqlInterfaceType; } });
|
|
16
|
+
Object.defineProperty(exports, "gqlUnionType", { enumerable: true, get: function () { return graphql_1.gqlUnionType; } });
|
|
15
17
|
var time_1 = require("./scalars/time");
|
|
16
18
|
Object.defineProperty(exports, "GraphQLTime", { enumerable: true, get: function () { return time_1.GraphQLTime; } });
|
|
17
19
|
var orderby_direction_1 = require("./scalars/orderby_direction");
|
package/package.json
CHANGED
package/parse_schema/parse.d.ts
CHANGED
package/parse_schema/parse.js
CHANGED
|
@@ -372,6 +372,7 @@ async function parseGlobalSchema(s) {
|
|
|
372
372
|
s.transformEdgeRead !== undefined ||
|
|
373
373
|
s.transformEdgeWrite !== undefined ||
|
|
374
374
|
s.fields !== undefined,
|
|
375
|
+
transformsEdges: !!s.transformEdgeRead || !!s.transformEdgeWrite,
|
|
375
376
|
};
|
|
376
377
|
if (s.extraEdgeFields) {
|
|
377
378
|
ret.extraEdgeFields = await processFields(s.extraEdgeFields);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.userPhoneNumberLoader = exports.userEmailLoader = exports.userLoader = exports.createUser = exports.getUserAction = exports.getUserBuilder = exports.FakeUserSchema = exports.FakeUser = exports.ViewerWithAccessToken = void 0;
|
|
4
|
+
const base_1 = require("../../core/base");
|
|
4
5
|
const ent_1 = require("../../core/ent");
|
|
5
6
|
const privacy_1 = require("../../core/privacy");
|
|
6
7
|
const builder_1 = require("../builder");
|
|
@@ -28,9 +29,17 @@ class FakeUser {
|
|
|
28
29
|
return {
|
|
29
30
|
rules: [
|
|
30
31
|
privacy_1.AllowIfViewerRule,
|
|
31
|
-
|
|
32
|
+
{
|
|
33
|
+
async apply(v, ent) {
|
|
34
|
+
if (!(v instanceof ViewerWithAccessToken)) {
|
|
35
|
+
return (0, base_1.Skip)();
|
|
36
|
+
}
|
|
37
|
+
return v.hasToken("always_allow_user") ? (0, base_1.Allow)() : (0, base_1.Skip)();
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
// can view user if friends
|
|
32
41
|
new privacy_1.AllowIfViewerInboundEdgeExistsRule(internal_1.EdgeType.UserToFriends),
|
|
33
|
-
//can view user if following
|
|
42
|
+
// can view user if following
|
|
34
43
|
new privacy_1.AllowIfViewerInboundEdgeExistsRule(internal_1.EdgeType.UserToFollowing),
|
|
35
44
|
new privacy_1.AllowIfConditionAppliesRule((viewer, ent) => {
|
|
36
45
|
if (!(viewer instanceof ViewerWithAccessToken)) {
|
|
@@ -113,9 +122,11 @@ function getUserAction(viewer, input) {
|
|
|
113
122
|
m.set(key, input[key]);
|
|
114
123
|
}
|
|
115
124
|
const action = new builder_1.SimpleAction(viewer, exports.FakeUserSchema, m, action_1.WriteOperation.Insert, null);
|
|
116
|
-
action.viewerForEntLoad = (data) => {
|
|
125
|
+
action.viewerForEntLoad = (data, context) => {
|
|
117
126
|
// load the created ent using a VC of the newly created user.
|
|
118
|
-
return new viewer_1.IDViewer(data.id
|
|
127
|
+
return new viewer_1.IDViewer(data.id, {
|
|
128
|
+
context,
|
|
129
|
+
});
|
|
119
130
|
};
|
|
120
131
|
return action;
|
|
121
132
|
}
|
|
@@ -11,7 +11,7 @@ class UserToTagsFkeyQuery extends custom_query_1.CustomEdgeQueryBase {
|
|
|
11
11
|
groupCol: "owner_id",
|
|
12
12
|
name: "user_to_tags",
|
|
13
13
|
sortColumn: "canonical_name",
|
|
14
|
-
|
|
14
|
+
primarySortColIsUnique: true,
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
static query(viewer, src) {
|
|
@@ -29,8 +29,13 @@ class UserToTagsFkeyQueryAsc extends custom_query_1.CustomEdgeQueryBase {
|
|
|
29
29
|
loadEntOptions: internal_1.FakeTag.loaderOptions(),
|
|
30
30
|
groupCol: "owner_id",
|
|
31
31
|
name: "user_to_tags_asc",
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
orderby: [
|
|
33
|
+
{
|
|
34
|
+
column: "canonical_name",
|
|
35
|
+
direction: "ASC",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
primarySortColIsUnique: true,
|
|
34
39
|
});
|
|
35
40
|
}
|
|
36
41
|
static query(viewer, src) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Data, Ent } from "../../core/base";
|
|
1
|
+
import { Context, Data, Ent } from "../../core/base";
|
|
2
2
|
import { AssocEdge } from "../../core/ent";
|
|
3
3
|
import { TempDB } from "../db/temp_db";
|
|
4
4
|
import { FakeUser, UserCreateInput, ContactCreateInput, FakeContact } from ".";
|
|
@@ -7,13 +7,14 @@ import { BuilderSchema } from "../builder";
|
|
|
7
7
|
export declare function getContactInput(user: FakeUser, input?: Partial<ContactCreateInput>): ContactCreateInput;
|
|
8
8
|
export declare function getUserInput(input?: Partial<UserCreateInput>): UserCreateInput;
|
|
9
9
|
export declare function getEventInput(user: FakeUser, input?: Partial<EventCreateInput>): EventCreateInput;
|
|
10
|
-
export declare function createTestUser(input?: Partial<UserCreateInput
|
|
10
|
+
export declare function createTestUser(input?: Partial<UserCreateInput>, ctx?: Context): Promise<FakeUser>;
|
|
11
11
|
export declare const inputs: Partial<ContactCreateInput>[];
|
|
12
12
|
interface createContactOptions {
|
|
13
13
|
input?: Partial<UserCreateInput>;
|
|
14
14
|
slice?: number;
|
|
15
15
|
user?: FakeUser;
|
|
16
16
|
start?: number;
|
|
17
|
+
ctx?: Context;
|
|
17
18
|
}
|
|
18
19
|
export declare function createAllContacts(opts?: createContactOptions): Promise<[FakeUser, FakeContact[]]>;
|
|
19
20
|
export declare function createUserPlusFriendRequests(input?: Partial<UserCreateInput>, slice?: number): Promise<[FakeUser, FakeUser[]]>;
|
|
@@ -53,8 +53,8 @@ function getEventInput(user, input) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
exports.getEventInput = getEventInput;
|
|
56
|
-
async function createTestUser(input) {
|
|
57
|
-
const user = await (0, _1.createUser)(new viewer_1.LoggedOutViewer(), {
|
|
56
|
+
async function createTestUser(input, ctx) {
|
|
57
|
+
const user = await (0, _1.createUser)(new viewer_1.LoggedOutViewer(ctx), {
|
|
58
58
|
firstName: "Jon",
|
|
59
59
|
lastName: "Snow",
|
|
60
60
|
password: "12345678",
|
|
@@ -93,7 +93,7 @@ exports.inputs = [
|
|
|
93
93
|
async function createAllContacts(opts) {
|
|
94
94
|
let { input, slice, user } = opts || {};
|
|
95
95
|
if (!user) {
|
|
96
|
-
user = await createTestUser(input);
|
|
96
|
+
user = await createTestUser(input, opts?.ctx);
|
|
97
97
|
}
|
|
98
98
|
const userr = user;
|
|
99
99
|
if (opts?.start) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ent, ID, Viewer } from "../../core/base";
|
|
1
|
+
import { Data, Ent, ID, Viewer } from "../../core/base";
|
|
2
2
|
import { CustomEdgeQueryBase } from "../../core/query/custom_query";
|
|
3
3
|
import { AssocEdge } from "../../core/ent";
|
|
4
4
|
import * as clause from "../../core/clause";
|
|
@@ -39,6 +39,8 @@ export declare class UserToFriendsQuery extends AssocEdgeQueryBase<FakeUser, Fak
|
|
|
39
39
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
40
40
|
}
|
|
41
41
|
export declare class CustomEdge extends AssocEdge {
|
|
42
|
+
deleted_at: Date | null;
|
|
43
|
+
constructor(data: Data);
|
|
42
44
|
loadUser(viewer: Viewer): Promise<FakeUser | null>;
|
|
43
45
|
}
|
|
44
46
|
export declare class UserToCustomEdgeQuery extends AssocEdgeQueryBase<FakeUser, FakeUser, CustomEdge> {
|
|
@@ -60,7 +62,7 @@ export declare class UserToFriendRequestsQuery extends AssocEdgeQueryBase<FakeUs
|
|
|
60
62
|
queryEventsAttending(): UserToEventsAttendingQuery;
|
|
61
63
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
62
64
|
}
|
|
63
|
-
export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBase<FakeUser, FakeUser,
|
|
65
|
+
export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBase<FakeUser, FakeUser, CustomEdge> {
|
|
64
66
|
constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeUser>);
|
|
65
67
|
getPrivacyPolicy(): import("../../core/base").PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
|
|
66
68
|
sourceEnt(id: ID): Promise<FakeUser | null>;
|
|
@@ -70,6 +72,7 @@ export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBas
|
|
|
70
72
|
queryHostedEvents(): UserToHostedEventsQuery;
|
|
71
73
|
queryEventsAttending(): UserToEventsAttendingQuery;
|
|
72
74
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
75
|
+
withoutTransformations(): this;
|
|
73
76
|
}
|
|
74
77
|
export declare class UserToEventsAttendingQuery extends AssocEdgeQueryBase<FakeUser, FakeEvent, AssocEdge> {
|
|
75
78
|
constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeEvent>);
|