@snowtop/ent 0.0.2 → 0.0.3-5.alpha.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.
- package/action/action.d.ts +6 -6
- package/action/action.js +2 -2
- package/action/executor.d.ts +7 -12
- package/action/executor.js +39 -33
- package/action/experimental_action.d.ts +4 -2
- package/action/experimental_action.js +27 -2
- package/action/index.d.ts +1 -1
- package/action/orchestrator.d.ts +14 -6
- package/action/orchestrator.js +188 -99
- package/action/privacy.js +4 -4
- package/auth/auth.js +2 -2
- package/core/base.d.ts +6 -0
- package/core/base.js +12 -9
- package/core/clause.d.ts +1 -0
- package/core/clause.js +6 -2
- package/core/config.d.ts +20 -0
- package/core/config.js +2 -2
- package/core/context.js +3 -3
- package/core/convert.d.ts +4 -0
- package/core/convert.js +25 -2
- package/core/db.d.ts +18 -1
- package/core/db.js +4 -7
- package/core/ent.d.ts +17 -10
- package/core/ent.js +38 -15
- package/core/loaders/assoc_count_loader.js +5 -5
- package/core/loaders/assoc_edge_loader.js +10 -10
- package/core/loaders/loader.js +3 -3
- package/core/loaders/object_loader.js +6 -6
- package/core/loaders/query_loader.js +7 -7
- package/core/loaders/raw_count_loader.js +4 -4
- package/core/logger.js +2 -2
- package/core/privacy.d.ts +21 -1
- package/core/privacy.js +91 -47
- package/core/query/assoc_query.d.ts +12 -12
- package/core/query/assoc_query.js +86 -51
- package/core/query/custom_query.d.ts +10 -7
- package/core/query/custom_query.js +29 -3
- package/core/query/query.d.ts +24 -8
- package/core/query/query.js +41 -4
- package/core/query/shared_assoc_test.js +257 -13
- package/core/query/shared_test.d.ts +1 -1
- package/core/query/shared_test.js +11 -11
- package/core/viewer.js +1 -0
- package/graphql/builtins/connection.js +4 -3
- package/graphql/builtins/edge.js +3 -2
- package/graphql/builtins/node.js +2 -1
- package/graphql/graphql.d.ts +2 -0
- package/graphql/graphql.js +83 -61
- package/graphql/index.d.ts +1 -1
- package/graphql/index.js +2 -1
- package/graphql/node_resolver.d.ts +1 -0
- package/graphql/node_resolver.js +14 -1
- package/graphql/query/connection_type.d.ts +5 -4
- package/graphql/query/connection_type.js +6 -6
- package/graphql/query/edge_connection.d.ts +7 -7
- package/graphql/query/page_info.js +5 -4
- package/graphql/query/shared_assoc_test.js +9 -9
- package/graphql/query/shared_edge_connection.d.ts +1 -1
- package/graphql/query/shared_edge_connection.js +4 -4
- package/graphql/scalars/time.js +1 -1
- package/imports/dataz/example1/_auth.js +8 -8
- package/imports/dataz/example1/_viewer.js +4 -4
- package/imports/index.d.ts +1 -1
- package/imports/index.js +3 -5
- package/index.d.ts +2 -1
- package/index.js +6 -2
- package/package.json +17 -10
- package/parse_schema/parse.d.ts +48 -0
- package/parse_schema/parse.js +160 -0
- package/schema/base_schema.d.ts +2 -0
- package/schema/base_schema.js +17 -7
- package/schema/field.d.ts +52 -15
- package/schema/field.js +234 -47
- package/schema/index.d.ts +1 -0
- package/schema/index.js +1 -0
- package/schema/json_field.d.ts +17 -0
- package/schema/json_field.js +48 -0
- package/schema/schema.d.ts +39 -4
- package/schema/schema.js +2 -0
- package/scripts/custom_compiler.js +8 -10
- package/scripts/custom_graphql.js +45 -10
- package/scripts/read_schema.js +6 -108
- package/testutils/builder.d.ts +6 -3
- package/testutils/builder.js +31 -15
- package/testutils/db/test_db.d.ts +16 -8
- package/testutils/db/test_db.js +65 -9
- package/testutils/db_mock.js +5 -5
- package/testutils/ent-graphql-tests/index.d.ts +1 -0
- package/testutils/ent-graphql-tests/index.js +13 -13
- package/testutils/fake_comms.d.ts +1 -0
- package/testutils/fake_comms.js +4 -0
- package/testutils/fake_data/const.d.ts +5 -1
- package/testutils/fake_data/const.js +19 -1
- package/testutils/fake_data/events_query.d.ts +16 -11
- package/testutils/fake_data/events_query.js +15 -0
- package/testutils/fake_data/fake_contact.js +9 -9
- package/testutils/fake_data/fake_event.js +14 -14
- package/testutils/fake_data/fake_user.js +12 -10
- package/testutils/fake_data/test_helpers.d.ts +5 -1
- package/testutils/fake_data/test_helpers.js +49 -16
- package/testutils/fake_data/user_query.d.ts +25 -9
- package/testutils/fake_data/user_query.js +52 -5
- package/testutils/parse_sql.js +19 -3
- package/testutils/write.js +6 -6
package/core/query/query.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data } from "../base";
|
|
2
|
-
export interface EdgeQuery<
|
|
1
|
+
import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data, PrivacyPolicy } from "../base";
|
|
2
|
+
export interface EdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> {
|
|
3
3
|
queryEdges(): Promise<TEdge[]>;
|
|
4
4
|
queryAllEdges(): Promise<Map<ID, TEdge[]>>;
|
|
5
5
|
queryIDs(): Promise<ID[]>;
|
|
@@ -8,13 +8,15 @@ export interface EdgeQuery<T extends Ent, TEdge extends Data> {
|
|
|
8
8
|
queryAllCount(): Promise<Map<ID, number>>;
|
|
9
9
|
queryRawCount(): Promise<number>;
|
|
10
10
|
queryAllRawCount(): Promise<Map<ID, number>>;
|
|
11
|
-
queryEnts(): Promise<
|
|
12
|
-
queryAllEnts(): Promise<Map<ID,
|
|
13
|
-
first(n: number, after?: string): EdgeQuery<
|
|
14
|
-
last(n: number, before?: string): EdgeQuery<
|
|
11
|
+
queryEnts(): Promise<TDest[]>;
|
|
12
|
+
queryAllEnts(): Promise<Map<ID, TDest[]>>;
|
|
13
|
+
first(n: number, after?: string): EdgeQuery<TSource, TDest, TEdge>;
|
|
14
|
+
last(n: number, before?: string): EdgeQuery<TSource, TDest, TEdge>;
|
|
15
15
|
paginationInfo(): Map<ID, PaginationInfo>;
|
|
16
16
|
getCursor(row: TEdge): string;
|
|
17
17
|
dataToID(edge: TEdge): ID;
|
|
18
|
+
getPrivacyPolicy(): PrivacyPolicy;
|
|
19
|
+
sourceEnt(id: ID): Promise<Ent | null>;
|
|
18
20
|
}
|
|
19
21
|
export interface EdgeQueryFilter<T extends Data> {
|
|
20
22
|
filter?(id: ID, edges: T[]): T[];
|
|
@@ -27,7 +29,7 @@ export interface PaginationInfo {
|
|
|
27
29
|
startCursor: string;
|
|
28
30
|
endCursor: string;
|
|
29
31
|
}
|
|
30
|
-
export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Data> {
|
|
32
|
+
export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> implements EdgeQuery<TSource, TDest, TEdge> {
|
|
31
33
|
viewer: Viewer;
|
|
32
34
|
private sortCol;
|
|
33
35
|
private filters;
|
|
@@ -35,11 +37,18 @@ export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Dat
|
|
|
35
37
|
protected edges: Map<ID, TEdge[]>;
|
|
36
38
|
private pagination;
|
|
37
39
|
private memoizedloadEdges;
|
|
40
|
+
protected genIDInfosToFetch: () => Promise<IDInfo[]>;
|
|
41
|
+
private idMap;
|
|
42
|
+
private idsToFetch;
|
|
38
43
|
constructor(viewer: Viewer, sortCol: string);
|
|
44
|
+
getPrivacyPolicy(): PrivacyPolicy;
|
|
45
|
+
abstract sourceEnt(id: ID): Promise<Ent | null>;
|
|
39
46
|
first(n: number, after?: string): this;
|
|
40
47
|
last(n: number, before?: string): this;
|
|
41
48
|
private querySingleEdge;
|
|
42
49
|
readonly queryEdges: () => Promise<TEdge[]>;
|
|
50
|
+
abstract queryRawCount(): Promise<number>;
|
|
51
|
+
abstract queryAllRawCount(): Promise<Map<ID, number>>;
|
|
43
52
|
readonly queryAllEdges: () => Promise<Map<ID, TEdge[]>>;
|
|
44
53
|
abstract dataToID(edge: TEdge): ID;
|
|
45
54
|
readonly queryIDs: () => Promise<ID[]>;
|
|
@@ -52,7 +61,14 @@ export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Dat
|
|
|
52
61
|
paginationInfo(): Map<ID, PaginationInfo>;
|
|
53
62
|
private assertQueryDispatched;
|
|
54
63
|
private assertQueryNotDispatched;
|
|
55
|
-
protected abstract
|
|
64
|
+
protected abstract loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
|
|
65
|
+
protected abstract loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
|
|
66
|
+
private addID;
|
|
67
|
+
protected genIDInfosToFetchImpl(): Promise<IDInfo[]>;
|
|
56
68
|
private loadEdges;
|
|
57
69
|
getCursor(row: TEdge): string;
|
|
58
70
|
}
|
|
71
|
+
export interface IDInfo {
|
|
72
|
+
id: ID;
|
|
73
|
+
invalidated?: boolean;
|
|
74
|
+
}
|
package/core/query/query.js
CHANGED
|
@@ -26,6 +26,7 @@ exports.BaseEdgeQuery = void 0;
|
|
|
26
26
|
const ent_1 = require("../ent");
|
|
27
27
|
const clause = __importStar(require("../clause"));
|
|
28
28
|
const memoizee_1 = __importDefault(require("memoizee"));
|
|
29
|
+
const privacy_1 = require("../privacy");
|
|
29
30
|
// TODO can we generalize EdgeQuery to support any clause
|
|
30
31
|
function assertPositive(n) {
|
|
31
32
|
if (n < 0) {
|
|
@@ -173,6 +174,8 @@ class BaseEdgeQuery {
|
|
|
173
174
|
this.filters = [];
|
|
174
175
|
this.edges = new Map();
|
|
175
176
|
this.pagination = new Map();
|
|
177
|
+
this.idMap = new Map();
|
|
178
|
+
this.idsToFetch = [];
|
|
176
179
|
// this is basically just raw rows
|
|
177
180
|
this.queryEdges = async () => {
|
|
178
181
|
return await this.querySingleEdge("queryEdges");
|
|
@@ -223,7 +226,12 @@ class BaseEdgeQuery {
|
|
|
223
226
|
await Promise.all(promises);
|
|
224
227
|
return results;
|
|
225
228
|
};
|
|
226
|
-
this.memoizedloadEdges = memoizee_1.default(this.loadEdges.bind(this));
|
|
229
|
+
this.memoizedloadEdges = (0, memoizee_1.default)(this.loadEdges.bind(this));
|
|
230
|
+
this.genIDInfosToFetch = (0, memoizee_1.default)(this.genIDInfosToFetchImpl.bind(this));
|
|
231
|
+
}
|
|
232
|
+
getPrivacyPolicy() {
|
|
233
|
+
// default PrivacyPolicy is always allow. nothing to do here
|
|
234
|
+
return privacy_1.AlwaysAllowPrivacyPolicy;
|
|
227
235
|
}
|
|
228
236
|
first(n, after) {
|
|
229
237
|
this.assertQueryNotDispatched("first");
|
|
@@ -269,9 +277,23 @@ class BaseEdgeQuery {
|
|
|
269
277
|
throw new Error(`cannot call ${str} after query is dispatched`);
|
|
270
278
|
}
|
|
271
279
|
}
|
|
280
|
+
addID(id) {
|
|
281
|
+
if (typeof id === "object") {
|
|
282
|
+
this.idMap.set(id.id, id);
|
|
283
|
+
this.idsToFetch.push(id.id);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
this.idsToFetch.push(id);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async genIDInfosToFetchImpl() {
|
|
290
|
+
await this.loadRawIDs(this.addID.bind(this));
|
|
291
|
+
return applyPrivacyPolicyForEdgeQ(this.viewer, this, this.idsToFetch, this.idMap);
|
|
292
|
+
}
|
|
272
293
|
async loadEdges() {
|
|
273
|
-
|
|
294
|
+
const idsInfo = await this.genIDInfosToFetch();
|
|
274
295
|
if (!this.filters.length) {
|
|
296
|
+
// if no filter, we add the firstN filter to ensure we get pagination info
|
|
275
297
|
this.first(ent_1.DefaultLimit);
|
|
276
298
|
}
|
|
277
299
|
let options = {};
|
|
@@ -283,7 +305,7 @@ class BaseEdgeQuery {
|
|
|
283
305
|
options = filter.query(options);
|
|
284
306
|
}
|
|
285
307
|
});
|
|
286
|
-
await this.loadRawData(options);
|
|
308
|
+
await this.loadRawData(idsInfo, options);
|
|
287
309
|
// no filters. nothing to do here.
|
|
288
310
|
if (!this.filters.length) {
|
|
289
311
|
return this.edges;
|
|
@@ -307,7 +329,7 @@ class BaseEdgeQuery {
|
|
|
307
329
|
return this.edges;
|
|
308
330
|
}
|
|
309
331
|
getCursor(row) {
|
|
310
|
-
return ent_1.getCursor({
|
|
332
|
+
return (0, ent_1.getCursor)({
|
|
311
333
|
row,
|
|
312
334
|
col: this.sortCol,
|
|
313
335
|
conv: (datum) => {
|
|
@@ -324,3 +346,18 @@ class BaseEdgeQuery {
|
|
|
324
346
|
}
|
|
325
347
|
}
|
|
326
348
|
exports.BaseEdgeQuery = BaseEdgeQuery;
|
|
349
|
+
async function applyPrivacyPolicyForEdgeQ(viewer, edgeQ, ids, map) {
|
|
350
|
+
const result = [];
|
|
351
|
+
await Promise.all(ids.map(async (id) => {
|
|
352
|
+
let ent = map.get(id);
|
|
353
|
+
if (!ent) {
|
|
354
|
+
ent = await edgeQ.sourceEnt(id);
|
|
355
|
+
}
|
|
356
|
+
const r = await (0, privacy_1.applyPrivacyPolicy)(viewer, edgeQ.getPrivacyPolicy(), ent || undefined);
|
|
357
|
+
result.push({
|
|
358
|
+
id,
|
|
359
|
+
invalidated: !r,
|
|
360
|
+
});
|
|
361
|
+
}));
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
@@ -31,8 +31,8 @@ function assocTests() {
|
|
|
31
31
|
describe("custom edge", () => {
|
|
32
32
|
let user1, user2;
|
|
33
33
|
beforeEach(async () => {
|
|
34
|
-
user2 = await test_helpers_1.createTestUser();
|
|
35
|
-
const builder = index_1.getUserBuilder(new viewer_1.LoggedOutViewer(), test_helpers_1.getUserInput());
|
|
34
|
+
user2 = await (0, test_helpers_1.createTestUser)();
|
|
35
|
+
const builder = (0, index_1.getUserBuilder)(new viewer_1.LoggedOutViewer(), (0, test_helpers_1.getUserInput)());
|
|
36
36
|
builder.orchestrator.addOutboundEdge(user2.id, index_1.EdgeType.UserToCustomEdge, index_1.NodeType.FakeUser);
|
|
37
37
|
await builder.saveX();
|
|
38
38
|
user1 = await builder.editedEntX();
|
|
@@ -92,6 +92,8 @@ function assocTests() {
|
|
|
92
92
|
expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2`);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
+
// TODO need to test multi-ids with id1s that aren't visible...
|
|
96
|
+
// so 2 user's friend requests at the same time
|
|
95
97
|
class MultiIDsTestQueryFilter {
|
|
96
98
|
constructor(filter, ents, limit) {
|
|
97
99
|
this.filter = filter;
|
|
@@ -101,9 +103,9 @@ function assocTests() {
|
|
|
101
103
|
}
|
|
102
104
|
async beforeEach() {
|
|
103
105
|
let [user1, user2, user3] = await Promise.all([
|
|
104
|
-
test_helpers_1.createAllContacts({ firstName: "Jon", lastName: "Snow" }),
|
|
105
|
-
test_helpers_1.createAllContacts({ firstName: "Aegon", lastName: "Targaryen" }),
|
|
106
|
-
test_helpers_1.createAllContacts({ firstName: "Ned", lastName: "Stark" }),
|
|
106
|
+
(0, test_helpers_1.createAllContacts)({ firstName: "Jon", lastName: "Snow" }),
|
|
107
|
+
(0, test_helpers_1.createAllContacts)({ firstName: "Aegon", lastName: "Targaryen" }),
|
|
108
|
+
(0, test_helpers_1.createAllContacts)({ firstName: "Ned", lastName: "Stark" }),
|
|
107
109
|
]);
|
|
108
110
|
// modify contacts as needed
|
|
109
111
|
user1[1] = this.ents(user1[1]);
|
|
@@ -156,7 +158,7 @@ function assocTests() {
|
|
|
156
158
|
expect(edgesMap.size).toBe(this.dataz.length);
|
|
157
159
|
for (let i = 0; i < this.dataz.length; i++) {
|
|
158
160
|
let data = this.dataz[i];
|
|
159
|
-
test_helpers_1.verifyUserToContactEdges(data[0], edgesMap.get(data[0].id) || [], data[1]);
|
|
161
|
+
(0, test_helpers_1.verifyUserToContactEdges)(data[0], edgesMap.get(data[0].id) || [], data[1]);
|
|
160
162
|
}
|
|
161
163
|
verifyQuery({
|
|
162
164
|
length: this.dataz.length,
|
|
@@ -170,14 +172,14 @@ function assocTests() {
|
|
|
170
172
|
expect(entsMap.size).toBe(this.dataz.length);
|
|
171
173
|
for (let i = 0; i < this.dataz.length; i++) {
|
|
172
174
|
let data = this.dataz[i];
|
|
173
|
-
test_helpers_1.verifyUserToContacts(data[0], entsMap.get(data[0].id) || [], []);
|
|
175
|
+
(0, test_helpers_1.verifyUserToContacts)(data[0], entsMap.get(data[0].id) || [], []);
|
|
174
176
|
}
|
|
175
177
|
// privacy. only data for the first id is visible in this case
|
|
176
178
|
const entsMap2 = await this.getQuery(new viewer_1.IDViewer(this.dataz[0][0].id)).queryAllEnts();
|
|
177
179
|
expect(entsMap2.size).toBe(this.dataz.length);
|
|
178
180
|
for (let i = 0; i < this.dataz.length; i++) {
|
|
179
181
|
let data = this.dataz[i];
|
|
180
|
-
test_helpers_1.verifyUserToContacts(data[0], entsMap2.get(data[0].id) || [], i == 0 ? data[1] : []);
|
|
182
|
+
(0, test_helpers_1.verifyUserToContacts)(data[0], entsMap2.get(data[0].id) || [], i == 0 ? data[1] : []);
|
|
181
183
|
}
|
|
182
184
|
verifyQuery({
|
|
183
185
|
// extra query for the nodes
|
|
@@ -270,13 +272,13 @@ function assocTests() {
|
|
|
270
272
|
this.lastHopFilter = lastHopFilter;
|
|
271
273
|
}
|
|
272
274
|
async beforeEach() {
|
|
273
|
-
this.user = await test_helpers_1.createTestUser();
|
|
274
|
-
this.event = await test_helpers_1.createTestEvent(this.user);
|
|
275
|
-
this.event2 = await test_helpers_1.createTestEvent(this.user, { title: "Red Wedding" });
|
|
275
|
+
this.user = await (0, test_helpers_1.createTestUser)();
|
|
276
|
+
this.event = await (0, test_helpers_1.createTestEvent)(this.user);
|
|
277
|
+
this.event2 = await (0, test_helpers_1.createTestEvent)(this.user, { title: "Red Wedding" });
|
|
276
278
|
this.friends = await Promise.all(test_helpers_1.inputs.map(async (input) => {
|
|
277
279
|
// just to make times deterministic so that tests can consistently work
|
|
278
|
-
jest_date_mock_1.advanceBy(100);
|
|
279
|
-
const builder = index_1.getUserBuilder(this.user.viewer, test_helpers_1.getUserInput(input));
|
|
280
|
+
(0, jest_date_mock_1.advanceBy)(100);
|
|
281
|
+
const builder = (0, index_1.getUserBuilder)(this.user.viewer, (0, test_helpers_1.getUserInput)(input));
|
|
280
282
|
// add edge from user to contact
|
|
281
283
|
builder.orchestrator.addOutboundEdge(this.user.id, index_1.EdgeType.UserToFriends, index_1.NodeType.FakeUser, {
|
|
282
284
|
time: new Date(), // set time to advanceBy time
|
|
@@ -425,5 +427,247 @@ function assocTests() {
|
|
|
425
427
|
await filter.testEnts();
|
|
426
428
|
});
|
|
427
429
|
});
|
|
430
|
+
class PolymorphicID2sTestQueryFilter {
|
|
431
|
+
constructor(filter, ents, limit) {
|
|
432
|
+
this.filter = filter;
|
|
433
|
+
this.ents = ents;
|
|
434
|
+
this.limit = limit;
|
|
435
|
+
this.users = [];
|
|
436
|
+
this.events = [];
|
|
437
|
+
}
|
|
438
|
+
async beforeEach() {
|
|
439
|
+
this.users = [];
|
|
440
|
+
this.events = [];
|
|
441
|
+
this.user = await (0, test_helpers_1.createTestUser)();
|
|
442
|
+
for (let i = 0; i < 5; i++) {
|
|
443
|
+
(0, jest_date_mock_1.advanceBy)(100);
|
|
444
|
+
const builder = (0, index_1.getUserBuilder)(this.user.viewer, (0, test_helpers_1.getUserInput)());
|
|
445
|
+
builder.orchestrator.addOutboundEdge(this.user.id, index_1.EdgeType.ObjectToFollowedUsers, index_1.NodeType.FakeUser);
|
|
446
|
+
await builder.saveX();
|
|
447
|
+
const user2 = await builder.editedEntX();
|
|
448
|
+
this.users.push(user2);
|
|
449
|
+
}
|
|
450
|
+
for (let i = 0; i < 5; i++) {
|
|
451
|
+
(0, jest_date_mock_1.advanceBy)(100);
|
|
452
|
+
const builder = (0, index_1.getEventBuilder)(this.user.viewer, (0, test_helpers_1.getEventInput)(this.user));
|
|
453
|
+
builder.orchestrator.addOutboundEdge(this.user.id, index_1.EdgeType.ObjectToFollowedUsers, index_1.NodeType.FakeUser);
|
|
454
|
+
await builder.saveX();
|
|
455
|
+
const event = await builder.editedEntX();
|
|
456
|
+
this.events.push(event);
|
|
457
|
+
}
|
|
458
|
+
//order is users, then events
|
|
459
|
+
this.expCount = this.ents([...this.users, ...this.events]).length;
|
|
460
|
+
db_mock_1.QueryRecorder.clearQueries();
|
|
461
|
+
}
|
|
462
|
+
getQuery(viewer) {
|
|
463
|
+
return this.filter(index_1.UserToFollowingQuery.query(viewer || new viewer_1.IDViewer(this.user.id), this.user));
|
|
464
|
+
}
|
|
465
|
+
async testIDs() {
|
|
466
|
+
const ids = await this.getQuery().queryIDs();
|
|
467
|
+
expect(ids.length).toBe(this.expCount);
|
|
468
|
+
const expIDs = this.users
|
|
469
|
+
.map((user) => user.id)
|
|
470
|
+
.concat(this.events.map((event) => event.id))
|
|
471
|
+
.reverse();
|
|
472
|
+
expect(expIDs).toEqual(ids);
|
|
473
|
+
verifyQuery({
|
|
474
|
+
length: 1,
|
|
475
|
+
numQueries: 1,
|
|
476
|
+
limit: this.limit || ent_1.DefaultLimit,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
// rawCount isn't affected by filters...
|
|
480
|
+
async testRawCount() {
|
|
481
|
+
const count = await this.getQuery().queryRawCount();
|
|
482
|
+
expect(count).toBe(this.expCount);
|
|
483
|
+
verifyCountQuery({ numQueries: 1, length: 1 });
|
|
484
|
+
}
|
|
485
|
+
async testCount() {
|
|
486
|
+
const count = await this.getQuery().queryCount();
|
|
487
|
+
expect(count).toBe(this.expCount);
|
|
488
|
+
verifyQuery({
|
|
489
|
+
length: 1,
|
|
490
|
+
numQueries: 1,
|
|
491
|
+
limit: this.limit || ent_1.DefaultLimit,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
async testEdges() {
|
|
495
|
+
const edges = await this.getQuery().queryEdges();
|
|
496
|
+
expect(edges.length).toBe(this.expCount);
|
|
497
|
+
let userCount = 0;
|
|
498
|
+
let eventCount = 0;
|
|
499
|
+
edges.forEach((edge) => {
|
|
500
|
+
if (edge.id2Type === index_1.NodeType.FakeEvent) {
|
|
501
|
+
eventCount++;
|
|
502
|
+
}
|
|
503
|
+
if (edge.id2Type === index_1.NodeType.FakeUser) {
|
|
504
|
+
userCount++;
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
expect(userCount).toBe(this.expCount / 2);
|
|
508
|
+
expect(eventCount).toBe(this.expCount / 2);
|
|
509
|
+
verifyQuery({
|
|
510
|
+
length: 1,
|
|
511
|
+
numQueries: 1,
|
|
512
|
+
limit: this.limit || ent_1.DefaultLimit,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
async testEnts() {
|
|
516
|
+
// privacy...
|
|
517
|
+
const ents = await this.getQuery().queryEnts();
|
|
518
|
+
expect(ents.length).toBe(this.expCount);
|
|
519
|
+
let userCount = 0;
|
|
520
|
+
let eventCount = 0;
|
|
521
|
+
ents.forEach((ent) => {
|
|
522
|
+
if (ent instanceof index_1.FakeEvent) {
|
|
523
|
+
eventCount++;
|
|
524
|
+
}
|
|
525
|
+
if (ent instanceof index_1.FakeUser) {
|
|
526
|
+
userCount++;
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
expect(userCount).toBe(this.expCount / 2);
|
|
530
|
+
expect(eventCount).toBe(this.expCount / 2);
|
|
531
|
+
// when doing privacy checks, hard to say what will be fetched
|
|
532
|
+
// verifyQuery({
|
|
533
|
+
// // 1 for edges, 1 for users, 1 for events
|
|
534
|
+
// length: 3,
|
|
535
|
+
// numQueries: 3,
|
|
536
|
+
// limit: this.limit || DefaultLimit,
|
|
537
|
+
// });
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
describe("polymorphic id2s", () => {
|
|
541
|
+
const filter = new PolymorphicID2sTestQueryFilter((q) => {
|
|
542
|
+
// no filters
|
|
543
|
+
return q;
|
|
544
|
+
}, (ents) => {
|
|
545
|
+
// nothing to do here
|
|
546
|
+
// reverse because edges are most recent first
|
|
547
|
+
return ents.reverse();
|
|
548
|
+
});
|
|
549
|
+
// TODO not working when it's a beforeAll
|
|
550
|
+
// working with beforeEach but we should only need to create this data once
|
|
551
|
+
beforeEach(async () => {
|
|
552
|
+
await filter.beforeEach();
|
|
553
|
+
});
|
|
554
|
+
test("ids", async () => {
|
|
555
|
+
await filter.testIDs();
|
|
556
|
+
});
|
|
557
|
+
test("rawCount", async () => {
|
|
558
|
+
await filter.testRawCount();
|
|
559
|
+
});
|
|
560
|
+
test("count", async () => {
|
|
561
|
+
await filter.testCount();
|
|
562
|
+
});
|
|
563
|
+
test("edges", async () => {
|
|
564
|
+
await filter.testEdges();
|
|
565
|
+
});
|
|
566
|
+
test("ents", async () => {
|
|
567
|
+
await filter.testEnts();
|
|
568
|
+
});
|
|
569
|
+
});
|
|
570
|
+
describe("privacy", () => {
|
|
571
|
+
let user;
|
|
572
|
+
let friendRequests;
|
|
573
|
+
let user2;
|
|
574
|
+
beforeEach(async () => {
|
|
575
|
+
[user, friendRequests] = await (0, test_helpers_1.createUserPlusFriendRequests)();
|
|
576
|
+
user2 = await (0, test_helpers_1.createTestUser)();
|
|
577
|
+
});
|
|
578
|
+
function getQuery(viewer) {
|
|
579
|
+
return index_1.UserToIncomingFriendRequestsQuery.query(viewer, user.id);
|
|
580
|
+
}
|
|
581
|
+
test("ids", async () => {
|
|
582
|
+
const ids = await getQuery(user2.viewer).queryIDs();
|
|
583
|
+
expect(ids.length).toBe(0);
|
|
584
|
+
const idsFromUser = await getQuery(user.viewer).queryIDs();
|
|
585
|
+
expect(idsFromUser.length).toBe(friendRequests.length);
|
|
586
|
+
});
|
|
587
|
+
test("count", async () => {
|
|
588
|
+
const count = await getQuery(user2.viewer).queryCount();
|
|
589
|
+
expect(count).toBe(0);
|
|
590
|
+
const countFromUser = await getQuery(user.viewer).queryCount();
|
|
591
|
+
expect(countFromUser).toBe(friendRequests.length);
|
|
592
|
+
});
|
|
593
|
+
test("rawCount", async () => {
|
|
594
|
+
const rawCount = await getQuery(user2.viewer).queryRawCount();
|
|
595
|
+
expect(rawCount).toBe(0);
|
|
596
|
+
const rawCountFromUser = await getQuery(user.viewer).queryRawCount();
|
|
597
|
+
expect(rawCountFromUser).toBe(friendRequests.length);
|
|
598
|
+
});
|
|
599
|
+
test("edges", async () => {
|
|
600
|
+
const edges = await getQuery(user2.viewer).queryEdges();
|
|
601
|
+
expect(edges.length).toBe(0);
|
|
602
|
+
const edgesFromUser = await getQuery(user.viewer).queryEdges();
|
|
603
|
+
expect(edgesFromUser.length).toBe(friendRequests.length);
|
|
604
|
+
});
|
|
605
|
+
test("ents", async () => {
|
|
606
|
+
const ents = await getQuery(user2.viewer).queryEnts();
|
|
607
|
+
expect(ents.length).toBe(0);
|
|
608
|
+
const entsFromUser = await getQuery(user.viewer).queryEnts();
|
|
609
|
+
expect(entsFromUser.length).toBe(0);
|
|
610
|
+
const entsFromUserVCToken = await getQuery(new index_1.ViewerWithAccessToken(user.id, {
|
|
611
|
+
tokens: {
|
|
612
|
+
allow_incoming_friend_request: true,
|
|
613
|
+
},
|
|
614
|
+
})).queryEnts();
|
|
615
|
+
expect(entsFromUserVCToken.length).toBe(friendRequests.length);
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
describe("multi-ids privacy", () => {
|
|
619
|
+
let user;
|
|
620
|
+
let friendRequests;
|
|
621
|
+
let user2;
|
|
622
|
+
let friendRequests2;
|
|
623
|
+
beforeEach(async () => {
|
|
624
|
+
[user, friendRequests] = await (0, test_helpers_1.createUserPlusFriendRequests)();
|
|
625
|
+
[user2, friendRequests2] = await (0, test_helpers_1.createUserPlusFriendRequests)();
|
|
626
|
+
});
|
|
627
|
+
function getQuery(viewer) {
|
|
628
|
+
return index_1.UserToIncomingFriendRequestsQuery.query(viewer || user.viewer, [
|
|
629
|
+
user.id,
|
|
630
|
+
user2.id,
|
|
631
|
+
]);
|
|
632
|
+
}
|
|
633
|
+
test("ids", async () => {
|
|
634
|
+
const idsMap = await getQuery().queryAllIDs();
|
|
635
|
+
expect(idsMap.size).toBe(2);
|
|
636
|
+
expect(idsMap.get(user.id)?.length).toBe(friendRequests.length);
|
|
637
|
+
expect(idsMap.get(user2.id)?.length).toBe(0);
|
|
638
|
+
});
|
|
639
|
+
test("count", async () => {
|
|
640
|
+
const countMap = await getQuery().queryAllCount();
|
|
641
|
+
expect(countMap.size).toBe(2);
|
|
642
|
+
expect(countMap.get(user.id)).toBe(friendRequests.length);
|
|
643
|
+
expect(countMap.get(user2.id)).toBe(0);
|
|
644
|
+
});
|
|
645
|
+
test("count", async () => {
|
|
646
|
+
const countMap = await getQuery().queryAllRawCount();
|
|
647
|
+
expect(countMap.size).toBe(2);
|
|
648
|
+
expect(countMap.get(user.id)).toBe(friendRequests.length);
|
|
649
|
+
expect(countMap.get(user2.id)).toBe(0);
|
|
650
|
+
});
|
|
651
|
+
test("edges", async () => {
|
|
652
|
+
const edgesMap = await getQuery().queryAllEdges();
|
|
653
|
+
expect(edgesMap.size).toBe(2);
|
|
654
|
+
expect(edgesMap.get(user.id)?.length).toBe(friendRequests.length);
|
|
655
|
+
expect(edgesMap.get(user2.id)?.length).toBe(0);
|
|
656
|
+
});
|
|
657
|
+
test("ents", async () => {
|
|
658
|
+
const entsMap = await getQuery().queryAllEnts();
|
|
659
|
+
expect(entsMap.size).toBe(2);
|
|
660
|
+
expect(entsMap.get(user.id)?.length).toBe(0);
|
|
661
|
+
expect(entsMap.get(user2.id)?.length).toBe(0);
|
|
662
|
+
const entsMapFromUserVCToken = await getQuery(new index_1.ViewerWithAccessToken(user.id, {
|
|
663
|
+
tokens: {
|
|
664
|
+
allow_incoming_friend_request: true,
|
|
665
|
+
},
|
|
666
|
+
})).queryAllEnts();
|
|
667
|
+
expect(entsMapFromUserVCToken.size).toBe(2);
|
|
668
|
+
expect(entsMapFromUserVCToken.get(user.id)?.length).toBe(friendRequests.length);
|
|
669
|
+
expect(entsMapFromUserVCToken.get(user2.id)?.length).toBe(0);
|
|
670
|
+
});
|
|
671
|
+
});
|
|
428
672
|
}
|
|
429
673
|
exports.assocTests = assocTests;
|
|
@@ -2,7 +2,7 @@ import { Data, Viewer } from "../base";
|
|
|
2
2
|
import { FakeUser, FakeContact } from "../../testutils/fake_data/index";
|
|
3
3
|
import { EdgeQuery } from "./query";
|
|
4
4
|
interface options<TData extends Data> {
|
|
5
|
-
newQuery: (v: Viewer, user: FakeUser) => EdgeQuery<FakeContact, TData>;
|
|
5
|
+
newQuery: (v: Viewer, user: FakeUser) => EdgeQuery<FakeUser, FakeContact, TData>;
|
|
6
6
|
tableName: string;
|
|
7
7
|
entsLength?: number;
|
|
8
8
|
where: string;
|
|
@@ -20,7 +20,7 @@ class TestQueryFilter {
|
|
|
20
20
|
}
|
|
21
21
|
async beforeEach() {
|
|
22
22
|
// console.log("sss");
|
|
23
|
-
[this.user, this.allContacts] = await test_helpers_1.createAllContacts();
|
|
23
|
+
[this.user, this.allContacts] = await (0, test_helpers_1.createAllContacts)();
|
|
24
24
|
// console.log(this.user, this.contacts);
|
|
25
25
|
// this.allContacts = this.allContacts.reverse();
|
|
26
26
|
this.filteredContacts = this.ents(this.allContacts);
|
|
@@ -59,10 +59,10 @@ class TestQueryFilter {
|
|
|
59
59
|
const q = this.getQuery();
|
|
60
60
|
// TODO sad not generic enough
|
|
61
61
|
if (q instanceof index_1.UserToContactsFkeyQuery) {
|
|
62
|
-
test_helpers_1.verifyUserToContactRawData(this.user, edges, this.filteredContacts);
|
|
62
|
+
(0, test_helpers_1.verifyUserToContactRawData)(this.user, edges, this.filteredContacts);
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
test_helpers_1.verifyUserToContactEdges(this.user, edges, this.filteredContacts);
|
|
65
|
+
(0, test_helpers_1.verifyUserToContactEdges)(this.user, edges, this.filteredContacts);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
async testEnts() {
|
|
@@ -70,7 +70,7 @@ class TestQueryFilter {
|
|
|
70
70
|
this.verifyEnts(entsMap);
|
|
71
71
|
}
|
|
72
72
|
verifyEnts(ents) {
|
|
73
|
-
test_helpers_1.verifyUserToContacts(this.user, ents, this.filteredContacts);
|
|
73
|
+
(0, test_helpers_1.verifyUserToContacts)(this.user, ents, this.filteredContacts);
|
|
74
74
|
}
|
|
75
75
|
async testAll() {
|
|
76
76
|
const query = this.getQuery(new viewer_1.IDViewer(this.user.id));
|
|
@@ -156,7 +156,7 @@ const commonTests = (opts) => {
|
|
|
156
156
|
// based on getContactBuilder
|
|
157
157
|
// so regardless of if we're doing assoc or custom queries, we can get the time
|
|
158
158
|
// from the created_at field
|
|
159
|
-
return ent_1.getCursor({
|
|
159
|
+
return (0, ent_1.getCursor)({
|
|
160
160
|
row: contacts[idx],
|
|
161
161
|
col: "createdAt",
|
|
162
162
|
conv: (t) => {
|
|
@@ -174,20 +174,20 @@ const commonTests = (opts) => {
|
|
|
174
174
|
let tdb;
|
|
175
175
|
if (opts.sqlite) {
|
|
176
176
|
// tableName just to make it unique
|
|
177
|
-
test_db_1.setupSqlite(`sqlite:///shared_test+${opts.tableName}.db`, test_helpers_1.tempDBTables);
|
|
177
|
+
(0, test_db_1.setupSqlite)(`sqlite:///shared_test+${opts.tableName}.db`, test_helpers_1.tempDBTables);
|
|
178
178
|
}
|
|
179
179
|
beforeAll(async () => {
|
|
180
180
|
// want error on by default in tests?
|
|
181
|
-
logger_1.setLogLevels(["error", "warn", "info"]);
|
|
181
|
+
(0, logger_1.setLogLevels)(["error", "warn", "info"]);
|
|
182
182
|
if (opts.livePostgresDB) {
|
|
183
|
-
tdb = await test_helpers_1.setupTempDB();
|
|
183
|
+
tdb = await (0, test_helpers_1.setupTempDB)();
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
186
|
beforeEach(async () => {
|
|
187
187
|
if (opts.livePostgresDB) {
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
await test_helpers_1.createEdges();
|
|
190
|
+
await (0, test_helpers_1.createEdges)();
|
|
191
191
|
});
|
|
192
192
|
afterAll(async () => {
|
|
193
193
|
if (opts.livePostgresDB && tdb) {
|
|
@@ -338,7 +338,7 @@ const commonTests = (opts) => {
|
|
|
338
338
|
});
|
|
339
339
|
});
|
|
340
340
|
test("first. after each cursor", async () => {
|
|
341
|
-
let [user, contacts] = await test_helpers_1.createAllContacts();
|
|
341
|
+
let [user, contacts] = await (0, test_helpers_1.createAllContacts)();
|
|
342
342
|
contacts = contacts.reverse();
|
|
343
343
|
const edges = await opts.newQuery(getViewer(), user).queryEdges();
|
|
344
344
|
let query;
|
|
@@ -406,7 +406,7 @@ const commonTests = (opts) => {
|
|
|
406
406
|
});
|
|
407
407
|
});
|
|
408
408
|
test("last. before each cursor", async () => {
|
|
409
|
-
let [user, contacts] = await test_helpers_1.createAllContacts();
|
|
409
|
+
let [user, contacts] = await (0, test_helpers_1.createAllContacts)();
|
|
410
410
|
contacts = contacts.reverse();
|
|
411
411
|
const edges = await opts.newQuery(getViewer(), user).queryEdges();
|
|
412
412
|
let query;
|
package/core/viewer.js
CHANGED
|
@@ -5,18 +5,19 @@ const graphql_1 = require("graphql");
|
|
|
5
5
|
const node_1 = require("./node");
|
|
6
6
|
const edge_1 = require("./edge");
|
|
7
7
|
const page_info_1 = require("../query/page_info");
|
|
8
|
+
// NB: if this changes, need to update renderer.go also
|
|
8
9
|
exports.GraphQLConnectionInterface = new graphql_1.GraphQLInterfaceType({
|
|
9
10
|
name: "Connection",
|
|
10
11
|
description: "connection interface",
|
|
11
12
|
fields: () => ({
|
|
12
13
|
edges: {
|
|
13
|
-
type: graphql_1.GraphQLNonNull(graphql_1.GraphQLList(graphql_1.GraphQLNonNull(edge_1.GraphQLEdgeInterface))),
|
|
14
|
+
type: (0, graphql_1.GraphQLNonNull)((0, graphql_1.GraphQLList)((0, graphql_1.GraphQLNonNull)(edge_1.GraphQLEdgeInterface))),
|
|
14
15
|
},
|
|
15
16
|
nodes: {
|
|
16
|
-
type: graphql_1.GraphQLNonNull(graphql_1.GraphQLList(graphql_1.GraphQLNonNull(node_1.GraphQLNodeInterface))),
|
|
17
|
+
type: (0, graphql_1.GraphQLNonNull)((0, graphql_1.GraphQLList)((0, graphql_1.GraphQLNonNull)(node_1.GraphQLNodeInterface))),
|
|
17
18
|
},
|
|
18
19
|
pageInfo: {
|
|
19
|
-
type: graphql_1.GraphQLNonNull(page_info_1.GraphQLPageInfo),
|
|
20
|
+
type: (0, graphql_1.GraphQLNonNull)(page_info_1.GraphQLPageInfo),
|
|
20
21
|
},
|
|
21
22
|
}),
|
|
22
23
|
});
|
package/graphql/builtins/edge.js
CHANGED
|
@@ -3,15 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GraphQLEdgeInterface = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const node_1 = require("./node");
|
|
6
|
+
// NB: if this changes, need to update renderer.go also
|
|
6
7
|
exports.GraphQLEdgeInterface = new graphql_1.GraphQLInterfaceType({
|
|
7
8
|
name: "Edge",
|
|
8
9
|
description: "edge interface",
|
|
9
10
|
fields: () => ({
|
|
10
11
|
node: {
|
|
11
|
-
type: graphql_1.GraphQLNonNull(node_1.GraphQLNodeInterface),
|
|
12
|
+
type: (0, graphql_1.GraphQLNonNull)(node_1.GraphQLNodeInterface),
|
|
12
13
|
},
|
|
13
14
|
cursor: {
|
|
14
|
-
type: graphql_1.GraphQLNonNull(graphql_1.GraphQLString),
|
|
15
|
+
type: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
15
16
|
},
|
|
16
17
|
}),
|
|
17
18
|
});
|
package/graphql/builtins/node.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GraphQLNodeInterface = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
|
+
// NB: if this changes, need to update renderer.go also
|
|
5
6
|
exports.GraphQLNodeInterface = new graphql_1.GraphQLInterfaceType({
|
|
6
7
|
name: "Node",
|
|
7
8
|
description: "node interface",
|
|
8
9
|
fields: () => ({
|
|
9
10
|
id: {
|
|
10
|
-
type: graphql_1.GraphQLNonNull(graphql_1.GraphQLID),
|
|
11
|
+
type: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLID),
|
|
11
12
|
},
|
|
12
13
|
}),
|
|
13
14
|
});
|
package/graphql/graphql.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface CustomType {
|
|
|
8
8
|
importPath: string;
|
|
9
9
|
tsType?: string;
|
|
10
10
|
tsImportPath?: string;
|
|
11
|
+
[x: string]: any;
|
|
11
12
|
}
|
|
12
13
|
declare type Type = GraphQLScalarType | ClassType | string | CustomType;
|
|
13
14
|
export declare type GraphQLConnection<T> = {
|
|
@@ -81,6 +82,7 @@ declare enum NullableResult {
|
|
|
81
82
|
CONTENTS_AND_LIST = "contentsAndList",
|
|
82
83
|
ITEM = "true"
|
|
83
84
|
}
|
|
85
|
+
export declare const addCustomType: (type: CustomType) => void;
|
|
84
86
|
export declare class GQLCapture {
|
|
85
87
|
private static enabled;
|
|
86
88
|
static enable(enabled: boolean): void;
|