@snowtop/ent 0.1.0-alpha7 → 0.1.0-alpha75
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 +28 -24
- package/action/executor.d.ts +4 -4
- package/action/executor.js +2 -2
- package/action/experimental_action.d.ts +29 -22
- package/action/experimental_action.js +29 -6
- package/action/orchestrator.d.ts +44 -16
- package/action/orchestrator.js +287 -73
- package/action/privacy.d.ts +2 -2
- package/core/base.d.ts +43 -23
- package/core/base.js +16 -0
- package/core/clause.d.ts +82 -3
- package/core/clause.js +463 -27
- package/core/config.d.ts +26 -0
- package/core/config.js +17 -0
- package/core/context.d.ts +5 -3
- package/core/context.js +7 -2
- package/core/convert.d.ts +1 -1
- package/core/db.d.ts +3 -4
- package/core/db.js +2 -0
- package/core/ent.d.ts +71 -27
- package/core/ent.js +458 -97
- package/core/loaders/assoc_count_loader.d.ts +2 -2
- package/core/loaders/assoc_count_loader.js +6 -1
- package/core/loaders/assoc_edge_loader.d.ts +3 -3
- package/core/loaders/assoc_edge_loader.js +5 -4
- package/core/loaders/index_loader.js +1 -0
- package/core/loaders/loader.js +5 -5
- package/core/loaders/object_loader.d.ts +11 -5
- package/core/loaders/object_loader.js +70 -4
- package/core/loaders/query_loader.d.ts +2 -2
- package/core/loaders/raw_count_loader.d.ts +2 -2
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +26 -25
- package/core/privacy.js +23 -24
- package/core/query/assoc_query.d.ts +6 -6
- package/core/query/custom_query.d.ts +5 -5
- package/core/query/query.d.ts +1 -1
- package/core/query/shared_assoc_test.d.ts +1 -1
- package/core/query/shared_assoc_test.js +17 -5
- package/core/query/shared_test.d.ts +3 -0
- package/core/query/shared_test.js +95 -17
- package/core/viewer.d.ts +4 -3
- package/core/viewer.js +5 -1
- package/graphql/builtins/connection.js +3 -3
- package/graphql/builtins/edge.js +2 -2
- package/graphql/builtins/node.js +1 -1
- package/graphql/graphql.d.ts +3 -2
- package/graphql/graphql.js +30 -23
- package/graphql/node_resolver.d.ts +0 -1
- package/graphql/query/connection_type.js +6 -6
- package/graphql/query/edge_connection.d.ts +9 -9
- package/graphql/query/page_info.d.ts +1 -1
- package/graphql/query/page_info.js +4 -4
- package/graphql/query/shared_assoc_test.js +2 -2
- package/graphql/scalars/time.d.ts +1 -1
- package/index.d.ts +21 -1
- package/index.js +24 -5
- package/package.json +3 -3
- package/parse_schema/parse.d.ts +24 -5
- package/parse_schema/parse.js +90 -8
- package/schema/base_schema.d.ts +36 -1
- package/schema/base_schema.js +51 -2
- package/schema/field.d.ts +34 -6
- package/schema/field.js +67 -2
- package/schema/index.d.ts +2 -2
- package/schema/index.js +8 -1
- package/schema/json_field.d.ts +13 -1
- package/schema/json_field.js +28 -1
- package/schema/schema.d.ts +101 -2
- package/schema/schema.js +127 -5
- package/schema/struct_field.d.ts +11 -1
- package/schema/struct_field.js +43 -4
- package/scripts/custom_graphql.js +127 -16
- package/scripts/{transform_schema.d.ts → migrate_v0.1.d.ts} +0 -0
- package/scripts/migrate_v0.1.js +36 -0
- package/scripts/read_schema.js +25 -2
- package/testutils/builder.d.ts +36 -22
- package/testutils/builder.js +110 -13
- package/testutils/context/test_context.d.ts +2 -2
- package/testutils/context/test_context.js +7 -1
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +17 -4
- package/testutils/db/{test_db.js → temp_db.js} +76 -19
- package/testutils/ent-graphql-tests/index.d.ts +2 -0
- package/testutils/ent-graphql-tests/index.js +26 -17
- package/testutils/fake_data/fake_contact.d.ts +5 -9
- package/testutils/fake_data/fake_contact.js +17 -21
- package/testutils/fake_data/fake_event.d.ts +5 -9
- package/testutils/fake_data/fake_event.js +24 -28
- package/testutils/fake_data/fake_user.d.ts +6 -10
- package/testutils/fake_data/fake_user.js +25 -29
- package/testutils/fake_data/test_helpers.d.ts +2 -2
- package/testutils/fake_data/test_helpers.js +6 -6
- package/testutils/fake_data/user_query.d.ts +2 -2
- package/testutils/fake_log.d.ts +3 -3
- package/testutils/parse_sql.d.ts +6 -0
- package/testutils/parse_sql.js +16 -2
- package/testutils/test_edge_global_schema.d.ts +15 -0
- package/testutils/test_edge_global_schema.js +58 -0
- package/testutils/write.d.ts +2 -2
- package/testutils/write.js +3 -3
- package/tsc/ast.d.ts +44 -0
- package/tsc/ast.js +267 -0
- package/tsc/compilerOptions.d.ts +6 -0
- package/tsc/compilerOptions.js +40 -1
- package/tsc/move_generated.d.ts +1 -0
- package/tsc/move_generated.js +160 -0
- package/tsc/transform.d.ts +21 -0
- package/tsc/transform.js +167 -0
- package/tsc/transform_action.d.ts +22 -0
- package/tsc/transform_action.js +179 -0
- package/tsc/transform_ent.d.ts +17 -0
- package/tsc/transform_ent.js +59 -0
- package/tsc/transform_schema.d.ts +27 -0
- package/tsc/transform_schema.js +379 -0
- package/scripts/transform_schema.js +0 -288
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ID, Context, Loader, LoaderFactory } from "../base";
|
|
2
2
|
export declare class AssocEdgeCountLoader implements Loader<ID, number> {
|
|
3
3
|
private edgeType;
|
|
4
|
-
context?: Context | undefined;
|
|
4
|
+
context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
|
|
5
5
|
private loaderFn;
|
|
6
6
|
private loader;
|
|
7
|
-
constructor(edgeType: string, context?: Context | undefined);
|
|
7
|
+
constructor(edgeType: string, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
|
|
8
8
|
private getLoader;
|
|
9
9
|
load(id: ID): Promise<number>;
|
|
10
10
|
clearAll(): void;
|
|
@@ -41,10 +41,15 @@ class AssocEdgeCountLoader {
|
|
|
41
41
|
if (!edgeData) {
|
|
42
42
|
throw new Error(`error loading edge data for ${this.edgeType}`);
|
|
43
43
|
}
|
|
44
|
+
const { cls } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", this.edgeType), {
|
|
45
|
+
// don't need this..
|
|
46
|
+
id1: "1",
|
|
47
|
+
edgeType: this.edgeType,
|
|
48
|
+
});
|
|
44
49
|
this.loader = (0, raw_count_loader_1.createCountDataLoader)({
|
|
45
50
|
tableName: edgeData.edgeTable,
|
|
46
51
|
groupCol: "id1",
|
|
47
|
-
clause:
|
|
52
|
+
clause: cls,
|
|
48
53
|
});
|
|
49
54
|
return this.loader;
|
|
50
55
|
}
|
|
@@ -20,8 +20,8 @@ export declare class AssocDirectEdgeLoader<T extends AssocEdge> implements Loade
|
|
|
20
20
|
private edgeType;
|
|
21
21
|
private edgeCtr;
|
|
22
22
|
private options?;
|
|
23
|
-
context?: Context | undefined;
|
|
24
|
-
constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined, context?: Context | undefined);
|
|
23
|
+
context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
|
|
24
|
+
constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
|
|
25
25
|
load(id: ID): Promise<T[]>;
|
|
26
26
|
loadEdgeForID2(id: ID, id2: ID): Promise<T | undefined>;
|
|
27
27
|
clearAll(): void;
|
|
@@ -32,7 +32,7 @@ export declare class AssocEdgeLoaderFactory<T extends AssocEdge> implements Load
|
|
|
32
32
|
name: string;
|
|
33
33
|
constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T> | (() => AssocEdgeConstructor<T>));
|
|
34
34
|
createLoader(context?: Context): AssocLoader<T>;
|
|
35
|
-
private
|
|
35
|
+
private isConstructor;
|
|
36
36
|
createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): AssocLoader<T>;
|
|
37
37
|
}
|
|
38
38
|
export {};
|
|
@@ -161,16 +161,17 @@ class AssocEdgeLoaderFactory {
|
|
|
161
161
|
createLoader(context) {
|
|
162
162
|
return this.createConfigurableLoader({}, context);
|
|
163
163
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
isConstructor(edgeCtr) {
|
|
165
|
+
return (edgeCtr.prototype &&
|
|
166
|
+
edgeCtr.prototype.constructor &&
|
|
167
|
+
edgeCtr.prototype.constructor.name.length > 0);
|
|
167
168
|
}
|
|
168
169
|
createConfigurableLoader(options, context) {
|
|
169
170
|
let edgeCtr = this.edgeCtr;
|
|
170
171
|
// in generated code, the edge is not necessarily defined at the time of loading
|
|
171
172
|
// so we call this as follows:
|
|
172
173
|
// const loader = new AssocEdgeLoaderFactory(EdgeType.Foo, ()=>DerivedEdgeClass);
|
|
173
|
-
if (this.
|
|
174
|
+
if (!this.isConstructor(edgeCtr)) {
|
|
174
175
|
edgeCtr = edgeCtr();
|
|
175
176
|
}
|
|
176
177
|
// rename to make TS happy
|
|
@@ -4,6 +4,7 @@ exports.IndexLoaderFactory = void 0;
|
|
|
4
4
|
const query_loader_1 = require("./query_loader");
|
|
5
5
|
// we're keeping this for legacy reasons so as to not break existing callers
|
|
6
6
|
// and to decouple the change here but all callers can safely be changed here to use QueryLoaderFactory
|
|
7
|
+
// @deprecated use QueryLoaderFactory
|
|
7
8
|
class IndexLoaderFactory {
|
|
8
9
|
constructor(options, col, opts) {
|
|
9
10
|
this.factory = new query_loader_1.QueryLoaderFactory({
|
package/core/loaders/loader.js
CHANGED
|
@@ -37,12 +37,12 @@ class cacheMap {
|
|
|
37
37
|
// might be a lot?
|
|
38
38
|
// TODO this is not the best log format
|
|
39
39
|
// was designed for ObjectLoader time. Now we have different needs e.g. count, assoc etc
|
|
40
|
-
(0, logger_1.log)("
|
|
40
|
+
(0, logger_1.log)("cache", {
|
|
41
41
|
"dataloader-cache-hit": key,
|
|
42
42
|
"tableName": this.options.tableName,
|
|
43
43
|
});
|
|
44
44
|
// } else {
|
|
45
|
-
// log("
|
|
45
|
+
// log("cache", {
|
|
46
46
|
// "dataloader-cache-miss": key,
|
|
47
47
|
// "tableName": options.tableName,
|
|
48
48
|
// });
|
|
@@ -50,21 +50,21 @@ class cacheMap {
|
|
|
50
50
|
return ret;
|
|
51
51
|
}
|
|
52
52
|
set(key, value) {
|
|
53
|
-
// log("
|
|
53
|
+
// log("cache", {
|
|
54
54
|
// "dataloader-cache-set": key,
|
|
55
55
|
// "tableName": options.tableName,
|
|
56
56
|
// });
|
|
57
57
|
return this.m.set(key, value);
|
|
58
58
|
}
|
|
59
59
|
delete(key) {
|
|
60
|
-
// log("
|
|
60
|
+
// log("cache", {
|
|
61
61
|
// "dataloader-cache-delete": key,
|
|
62
62
|
// "tableName": options.tableName,
|
|
63
63
|
// });
|
|
64
64
|
return this.m.delete(key);
|
|
65
65
|
}
|
|
66
66
|
clear() {
|
|
67
|
-
// log("
|
|
67
|
+
// log("cache", {
|
|
68
68
|
// "dataloader-cache-clear": true,
|
|
69
69
|
// "tableName": options.tableName,
|
|
70
70
|
// });
|
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import { Data, SelectDataOptions, Context, Loader, LoaderFactory } from "../base";
|
|
1
|
+
import { ID, Data, SelectDataOptions, Context, Loader, LoaderFactory } from "../base";
|
|
2
2
|
export declare class ObjectLoader<T> implements Loader<T, Data | null> {
|
|
3
3
|
private options;
|
|
4
|
-
context?: Context | undefined;
|
|
4
|
+
context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
|
|
5
5
|
private toPrime?;
|
|
6
6
|
private loader;
|
|
7
7
|
private primedLoaders;
|
|
8
8
|
private memoizedInitPrime;
|
|
9
|
-
constructor(options: SelectDataOptions, context?: Context | undefined, toPrime?: ObjectLoaderFactory<T>[] | undefined);
|
|
9
|
+
constructor(options: SelectDataOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, toPrime?: ObjectLoaderFactory<T>[] | undefined);
|
|
10
|
+
getOptions(): SelectDataOptions;
|
|
10
11
|
private initPrime;
|
|
11
12
|
load(key: T): Promise<Data | null>;
|
|
12
13
|
clearAll(): void;
|
|
13
14
|
loadMany(keys: T[]): Promise<Data[]>;
|
|
14
15
|
prime(data: Data): void;
|
|
16
|
+
primeAll(data: Data): void;
|
|
17
|
+
}
|
|
18
|
+
interface ObjectLoaderOptions extends SelectDataOptions {
|
|
19
|
+
instanceKey?: string;
|
|
15
20
|
}
|
|
16
21
|
export declare class ObjectLoaderFactory<T> implements LoaderFactory<T, Data | null> {
|
|
17
|
-
options:
|
|
22
|
+
options: ObjectLoaderOptions;
|
|
18
23
|
name: string;
|
|
19
24
|
private toPrime;
|
|
20
|
-
constructor(options:
|
|
25
|
+
constructor(options: ObjectLoaderOptions);
|
|
21
26
|
createLoader(context?: Context): ObjectLoader<T>;
|
|
22
27
|
addToPrime(factory: ObjectLoaderFactory<T>): void;
|
|
23
28
|
}
|
|
29
|
+
export {};
|
|
@@ -29,6 +29,9 @@ const clause = __importStar(require("../clause"));
|
|
|
29
29
|
const logger_1 = require("../logger");
|
|
30
30
|
const loader_1 = require("./loader");
|
|
31
31
|
const memoizee_1 = __importDefault(require("memoizee"));
|
|
32
|
+
// optional clause...
|
|
33
|
+
// so ObjectLoaderFactory and createDataLoader need to take a new optional field which is a clause that's always added here
|
|
34
|
+
// and we need a disableTransform which skips loader completely and uses loadRow...
|
|
32
35
|
function createDataLoader(options) {
|
|
33
36
|
const loaderOptions = {};
|
|
34
37
|
// if query logging is enabled, we should log what's happening with loader
|
|
@@ -40,9 +43,22 @@ function createDataLoader(options) {
|
|
|
40
43
|
return [];
|
|
41
44
|
}
|
|
42
45
|
let col = options.key;
|
|
46
|
+
let cls = clause.In(col, ...ids);
|
|
47
|
+
if (options.clause) {
|
|
48
|
+
let optionClause;
|
|
49
|
+
if (typeof options.clause === "function") {
|
|
50
|
+
optionClause = options.clause();
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
optionClause = options.clause;
|
|
54
|
+
}
|
|
55
|
+
if (optionClause) {
|
|
56
|
+
cls = clause.And(cls, optionClause);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
43
59
|
const rowOptions = {
|
|
44
60
|
...options,
|
|
45
|
-
clause:
|
|
61
|
+
clause: cls,
|
|
46
62
|
};
|
|
47
63
|
let m = new Map();
|
|
48
64
|
let result = [];
|
|
@@ -77,6 +93,9 @@ class ObjectLoader {
|
|
|
77
93
|
}
|
|
78
94
|
this.memoizedInitPrime = (0, memoizee_1.default)(this.initPrime.bind(this));
|
|
79
95
|
}
|
|
96
|
+
getOptions() {
|
|
97
|
+
return this.options;
|
|
98
|
+
}
|
|
80
99
|
initPrime() {
|
|
81
100
|
if (!this.context || !this.toPrime) {
|
|
82
101
|
return;
|
|
@@ -107,9 +126,22 @@ class ObjectLoader {
|
|
|
107
126
|
}
|
|
108
127
|
return result;
|
|
109
128
|
}
|
|
129
|
+
let cls = clause.Eq(this.options.key, key);
|
|
130
|
+
if (this.options.clause) {
|
|
131
|
+
let optionClause;
|
|
132
|
+
if (typeof this.options.clause === "function") {
|
|
133
|
+
optionClause = this.options.clause();
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
optionClause = this.options.clause;
|
|
137
|
+
}
|
|
138
|
+
if (optionClause) {
|
|
139
|
+
cls = clause.And(cls, optionClause);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
110
142
|
const rowOptions = {
|
|
111
143
|
...this.options,
|
|
112
|
-
clause:
|
|
144
|
+
clause: cls,
|
|
113
145
|
context: this.context,
|
|
114
146
|
};
|
|
115
147
|
return await (0, ent_1.loadRow)(rowOptions);
|
|
@@ -121,9 +153,22 @@ class ObjectLoader {
|
|
|
121
153
|
if (this.loader) {
|
|
122
154
|
return await this.loader.loadMany(keys);
|
|
123
155
|
}
|
|
156
|
+
let cls = clause.In(this.options.key, ...keys);
|
|
157
|
+
if (this.options.clause) {
|
|
158
|
+
let optionClause;
|
|
159
|
+
if (typeof this.options.clause === "function") {
|
|
160
|
+
optionClause = this.options.clause();
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
optionClause = this.options.clause;
|
|
164
|
+
}
|
|
165
|
+
if (optionClause) {
|
|
166
|
+
cls = clause.And(cls, optionClause);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
124
169
|
const rowOptions = {
|
|
125
170
|
...this.options,
|
|
126
|
-
clause:
|
|
171
|
+
clause: cls,
|
|
127
172
|
context: this.context,
|
|
128
173
|
};
|
|
129
174
|
return await (0, ent_1.loadRows)(rowOptions);
|
|
@@ -136,13 +181,34 @@ class ObjectLoader {
|
|
|
136
181
|
this.loader.prime(key, data);
|
|
137
182
|
}
|
|
138
183
|
}
|
|
184
|
+
// prime this loader and any other loaders it's aware of
|
|
185
|
+
primeAll(data) {
|
|
186
|
+
this.prime(data);
|
|
187
|
+
if (this.primedLoaders) {
|
|
188
|
+
for (const [key, loader] of this.primedLoaders) {
|
|
189
|
+
const value = data[key];
|
|
190
|
+
if (value !== undefined) {
|
|
191
|
+
loader.prime(data);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
139
196
|
}
|
|
140
197
|
exports.ObjectLoader = ObjectLoader;
|
|
141
198
|
class ObjectLoaderFactory {
|
|
142
199
|
constructor(options) {
|
|
143
200
|
this.options = options;
|
|
144
201
|
this.toPrime = [];
|
|
145
|
-
|
|
202
|
+
let instanceKey = options.instanceKey || "";
|
|
203
|
+
if (typeof this.options.clause === "function") {
|
|
204
|
+
if (!options.instanceKey) {
|
|
205
|
+
throw new Error(`need to pass an instanceKey to ObjectLoader if clause is a function`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else if (this.options.clause) {
|
|
209
|
+
instanceKey = this.options.clause.instanceKey();
|
|
210
|
+
}
|
|
211
|
+
this.name = `${options.tableName}:${options.key}:${instanceKey}`;
|
|
146
212
|
}
|
|
147
213
|
createLoader(context) {
|
|
148
214
|
return (0, loader_1.getLoader)(this, () => {
|
|
@@ -10,12 +10,12 @@ export declare class QueryDirectLoader<K extends any> implements Loader<K, Data[
|
|
|
10
10
|
}
|
|
11
11
|
export declare class QueryLoader<K extends any> implements Loader<K, Data[]> {
|
|
12
12
|
private options;
|
|
13
|
-
context?: Context | undefined;
|
|
13
|
+
context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
|
|
14
14
|
private queryOptions?;
|
|
15
15
|
private loader;
|
|
16
16
|
private primedLoaders;
|
|
17
17
|
private memoizedInitPrime;
|
|
18
|
-
constructor(options: QueryOptions, context?: Context | undefined, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined);
|
|
18
|
+
constructor(options: QueryOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined);
|
|
19
19
|
private initPrime;
|
|
20
20
|
load(id: K): Promise<Data[]>;
|
|
21
21
|
clearAll(): void;
|
|
@@ -9,9 +9,9 @@ interface QueryCountOptions {
|
|
|
9
9
|
export declare function createCountDataLoader<K extends any>(options: QueryCountOptions): DataLoader<K, number, K>;
|
|
10
10
|
export declare class RawCountLoader<K extends any> implements Loader<K, number> {
|
|
11
11
|
private options;
|
|
12
|
-
context?: Context | undefined;
|
|
12
|
+
context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
|
|
13
13
|
private loader;
|
|
14
|
-
constructor(options: QueryCountOptions, context?: Context | undefined);
|
|
14
|
+
constructor(options: QueryCountOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
|
|
15
15
|
load(id: K): Promise<number>;
|
|
16
16
|
clearAll(): void;
|
|
17
17
|
}
|
package/core/logger.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare type logType = "query" | "warn" | "info" | "error" | "debug";
|
|
1
|
+
declare type logType = "query" | "warn" | "info" | "error" | "debug" | "cache";
|
|
2
2
|
export declare function setLogLevels(levels: logType | logType[]): void;
|
|
3
3
|
export declare function clearLogLevels(): void;
|
|
4
4
|
export declare function log(level: logType, msg: any): void;
|
package/core/logger.js
CHANGED
package/core/privacy.d.ts
CHANGED
|
@@ -6,22 +6,22 @@ export declare class EntPrivacyError extends Error implements PrivacyError {
|
|
|
6
6
|
constructor(privacyPolicy: PrivacyPolicy, rule: PrivacyPolicyRule, ent?: Ent);
|
|
7
7
|
}
|
|
8
8
|
export declare const AlwaysAllowRule: {
|
|
9
|
-
apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
9
|
+
apply(_v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
10
10
|
};
|
|
11
11
|
export declare const AlwaysDenyRule: {
|
|
12
|
-
apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
12
|
+
apply(_v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
13
13
|
};
|
|
14
14
|
export declare const DenyIfLoggedOutRule: {
|
|
15
|
-
apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
15
|
+
apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
16
16
|
};
|
|
17
17
|
export declare const DenyIfLoggedInRule: {
|
|
18
|
-
apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
18
|
+
apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
19
19
|
};
|
|
20
20
|
export declare const AllowIfHasIdentity: {
|
|
21
|
-
apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
21
|
+
apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
22
22
|
};
|
|
23
23
|
export declare const AllowIfViewerRule: {
|
|
24
|
-
apply(v: Viewer, ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
24
|
+
apply(v: Viewer, ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
25
25
|
};
|
|
26
26
|
export declare class AllowIfViewerEqualsRule {
|
|
27
27
|
private id;
|
|
@@ -71,45 +71,45 @@ export declare class DenyIfEntPropertyIsRule<T extends Ent> implements PrivacyPo
|
|
|
71
71
|
constructor(property: keyof T, val: any);
|
|
72
72
|
apply(v: Viewer, ent?: T): Promise<PrivacyResult>;
|
|
73
73
|
}
|
|
74
|
-
export declare class AllowIfEntIsVisibleRule<
|
|
74
|
+
export declare class AllowIfEntIsVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
|
|
75
75
|
private id;
|
|
76
76
|
private options;
|
|
77
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
78
|
-
apply(v:
|
|
77
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
78
|
+
apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
|
|
79
79
|
}
|
|
80
|
-
export declare class AllowIfEntIsNotVisibleRule<
|
|
80
|
+
export declare class AllowIfEntIsNotVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
|
|
81
81
|
private id;
|
|
82
82
|
private options;
|
|
83
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
84
|
-
apply(v:
|
|
83
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
84
|
+
apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
|
|
85
85
|
}
|
|
86
|
-
export declare class AllowIfEntIsVisiblePolicy<
|
|
86
|
+
export declare class AllowIfEntIsVisiblePolicy<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicy<TEnt, TViewer> {
|
|
87
87
|
private id;
|
|
88
88
|
private options;
|
|
89
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
89
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
90
90
|
rules: {
|
|
91
|
-
apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
91
|
+
apply(_v: Viewer<Ent<any> | null, ID | null>, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
92
92
|
}[];
|
|
93
93
|
}
|
|
94
|
-
export declare class DenyIfEntIsVisiblePolicy<
|
|
94
|
+
export declare class DenyIfEntIsVisiblePolicy<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicy<TEnt, TViewer> {
|
|
95
95
|
private id;
|
|
96
96
|
private options;
|
|
97
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
97
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
98
98
|
rules: {
|
|
99
|
-
apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
|
|
99
|
+
apply(_v: Viewer<Ent<any> | null, ID | null>, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
|
|
100
100
|
}[];
|
|
101
101
|
}
|
|
102
|
-
export declare class DenyIfEntIsVisibleRule<
|
|
102
|
+
export declare class DenyIfEntIsVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule<TEnt, TViewer> {
|
|
103
103
|
private id;
|
|
104
104
|
private options;
|
|
105
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
106
|
-
apply(v:
|
|
105
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
106
|
+
apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
|
|
107
107
|
}
|
|
108
|
-
export declare class DenyIfEntIsNotVisibleRule<
|
|
108
|
+
export declare class DenyIfEntIsNotVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
|
|
109
109
|
private id;
|
|
110
110
|
private options;
|
|
111
|
-
constructor(id: ID, options: LoadEntOptions<
|
|
112
|
-
apply(v:
|
|
111
|
+
constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
|
|
112
|
+
apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
|
|
113
113
|
}
|
|
114
114
|
export declare class AllowIfEdgeExistsRule implements PrivacyPolicyRule {
|
|
115
115
|
private id1;
|
|
@@ -121,7 +121,7 @@ export declare class AllowIfEdgeExistsRule implements PrivacyPolicyRule {
|
|
|
121
121
|
export declare class AllowIfViewerInboundEdgeExistsRule implements PrivacyPolicyRule {
|
|
122
122
|
private edgeType;
|
|
123
123
|
constructor(edgeType: string);
|
|
124
|
-
apply(v: Viewer, ent
|
|
124
|
+
apply(v: Viewer, ent?: Ent): Promise<PrivacyResult>;
|
|
125
125
|
}
|
|
126
126
|
export declare class AllowIfViewerOutboundEdgeExistsRule implements PrivacyPolicyRule {
|
|
127
127
|
private edgeType;
|
|
@@ -183,6 +183,7 @@ export declare class AllowIfSubPolicyAllowsRule implements PrivacyPolicyRule {
|
|
|
183
183
|
}
|
|
184
184
|
export declare function applyPrivacyPolicy(v: Viewer, policy: PrivacyPolicy, ent: Ent | undefined): Promise<boolean>;
|
|
185
185
|
export declare function applyPrivacyPolicyX(v: Viewer, policy: PrivacyPolicy, ent: Ent | undefined, throwErr?: () => Error): Promise<boolean>;
|
|
186
|
+
export declare function applyPrivacyPolicyImpl(v: Viewer, policy: PrivacyPolicy, ent: Ent | undefined, throwErr?: () => Error): Promise<Error | null>;
|
|
186
187
|
export declare const AlwaysAllowPrivacyPolicy: PrivacyPolicy;
|
|
187
188
|
export declare const AlwaysDenyPrivacyPolicy: PrivacyPolicy;
|
|
188
189
|
export declare const AllowIfViewerPrivacyPolicy: PrivacyPolicy;
|
package/core/privacy.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
|
|
3
|
+
exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyImpl = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
|
|
4
4
|
const base_1 = require("./base");
|
|
5
5
|
const ent_1 = require("./ent");
|
|
6
|
-
const logger_1 = require("./logger");
|
|
7
6
|
// copied from ./base
|
|
8
7
|
var privacyResult;
|
|
9
8
|
(function (privacyResult) {
|
|
@@ -437,42 +436,42 @@ class AllowIfSubPolicyAllowsRule {
|
|
|
437
436
|
}
|
|
438
437
|
exports.AllowIfSubPolicyAllowsRule = AllowIfSubPolicyAllowsRule;
|
|
439
438
|
async function applyPrivacyPolicy(v, policy, ent) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
catch (e) {
|
|
444
|
-
// TODO privacy errors should not throw
|
|
445
|
-
// but other expected errors should throw...
|
|
446
|
-
// we shouldn't just hide them
|
|
447
|
-
(0, logger_1.log)("debug", e);
|
|
448
|
-
return false;
|
|
449
|
-
}
|
|
439
|
+
const err = await applyPrivacyPolicyImpl(v, policy, ent);
|
|
440
|
+
return err === null;
|
|
450
441
|
}
|
|
451
442
|
exports.applyPrivacyPolicy = applyPrivacyPolicy;
|
|
452
|
-
// this will throw an exception if fails or return error | null?
|
|
453
443
|
async function applyPrivacyPolicyX(v, policy, ent, throwErr) {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
444
|
+
const err = await applyPrivacyPolicyImpl(v, policy, ent, throwErr);
|
|
445
|
+
if (err !== null) {
|
|
446
|
+
throw err;
|
|
447
|
+
}
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
exports.applyPrivacyPolicyX = applyPrivacyPolicyX;
|
|
451
|
+
// this will throw an exception if fails or return error | null?
|
|
452
|
+
async function applyPrivacyPolicyImpl(v, policy, ent, throwErr) {
|
|
453
|
+
for (const rule of policy.rules) {
|
|
454
|
+
const res = await rule.apply(v, ent);
|
|
459
455
|
if (res.result == privacyResult.Allow) {
|
|
460
|
-
return
|
|
456
|
+
return null;
|
|
461
457
|
}
|
|
462
458
|
else if (res.result == privacyResult.Deny) {
|
|
463
459
|
// specific error throw that
|
|
464
460
|
if (res.error) {
|
|
465
|
-
|
|
461
|
+
return res.error;
|
|
462
|
+
}
|
|
463
|
+
if (res.getError) {
|
|
464
|
+
return res.getError(policy, rule, ent);
|
|
466
465
|
}
|
|
467
466
|
if (throwErr) {
|
|
468
|
-
|
|
467
|
+
return throwErr();
|
|
469
468
|
}
|
|
470
|
-
|
|
469
|
+
return new EntPrivacyError(policy, rule, ent);
|
|
471
470
|
}
|
|
472
471
|
}
|
|
473
|
-
|
|
472
|
+
return new EntInvalidPrivacyPolicyError(policy, ent);
|
|
474
473
|
}
|
|
475
|
-
exports.
|
|
474
|
+
exports.applyPrivacyPolicyImpl = applyPrivacyPolicyImpl;
|
|
476
475
|
exports.AlwaysAllowPrivacyPolicy = {
|
|
477
476
|
rules: [exports.AlwaysAllowRule],
|
|
478
477
|
};
|
|
@@ -3,15 +3,15 @@ import { AssocEdge } from "../ent";
|
|
|
3
3
|
import { AssocEdgeCountLoaderFactory } from "../loaders/assoc_count_loader";
|
|
4
4
|
import { AssocEdgeLoaderFactory } from "../loaders/assoc_edge_loader";
|
|
5
5
|
import { EdgeQuery, BaseEdgeQuery, IDInfo } from "./query";
|
|
6
|
-
export declare type EdgeQuerySource<TSource extends Ent
|
|
7
|
-
declare type loaderOptionsFunc = (type: string) => LoadEntOptions<Ent>;
|
|
8
|
-
export declare abstract class AssocEdgeQueryBase<TSource extends Ent
|
|
9
|
-
viewer:
|
|
10
|
-
src: EdgeQuerySource<TSource, TDest>;
|
|
6
|
+
export declare type EdgeQuerySource<TSource extends Ent<TViewer>, TDest extends Ent<TViewer> = Ent<any>, TViewer extends Viewer = Viewer> = TSource | TSource[] | ID | ID[] | EdgeQuery<TDest, Ent, AssocEdge>;
|
|
7
|
+
declare type loaderOptionsFunc<TViewer extends Viewer> = (type: string) => LoadEntOptions<Ent, TViewer>;
|
|
8
|
+
export declare abstract class AssocEdgeQueryBase<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TEdge extends AssocEdge, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<TSource, TDest, TEdge> implements EdgeQuery<TSource, TDest, TEdge> {
|
|
9
|
+
viewer: TViewer;
|
|
10
|
+
src: EdgeQuerySource<TSource, TDest, TViewer>;
|
|
11
11
|
private countLoaderFactory;
|
|
12
12
|
private dataLoaderFactory;
|
|
13
13
|
private options;
|
|
14
|
-
constructor(viewer:
|
|
14
|
+
constructor(viewer: TViewer, src: EdgeQuerySource<TSource, TDest, TViewer>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest, TViewer> | loaderOptionsFunc<TViewer>);
|
|
15
15
|
private isEdgeQuery;
|
|
16
16
|
abstract sourceEnt(id: ID): Promise<Ent | null>;
|
|
17
17
|
private getSingleID;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Data, Ent, ID, EdgeQueryableDataOptions, LoadEntOptions, Viewer, LoaderFactory, ConfigurableLoaderFactory } from "../base";
|
|
2
2
|
import { BaseEdgeQuery, IDInfo, EdgeQuery } from "./query";
|
|
3
|
-
export interface CustomEdgeQueryOptions<TSource extends Ent
|
|
3
|
+
export interface CustomEdgeQueryOptions<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
|
|
4
4
|
src: TSource | ID;
|
|
5
5
|
countLoaderFactory: LoaderFactory<ID, number>;
|
|
6
6
|
dataLoaderFactory: ConfigurableLoaderFactory<ID, Data[]>;
|
|
7
|
-
options: LoadEntOptions<TDest>;
|
|
7
|
+
options: LoadEntOptions<TDest, TViewer>;
|
|
8
8
|
sortColumn?: string;
|
|
9
9
|
}
|
|
10
|
-
export declare abstract class CustomEdgeQueryBase<TSource extends Ent
|
|
11
|
-
viewer:
|
|
10
|
+
export declare abstract class CustomEdgeQueryBase<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<TSource, TDest, Data> implements EdgeQuery<TSource, TDest, Data> {
|
|
11
|
+
viewer: TViewer;
|
|
12
12
|
private options;
|
|
13
13
|
private id;
|
|
14
|
-
constructor(viewer:
|
|
14
|
+
constructor(viewer: TViewer, options: CustomEdgeQueryOptions<TSource, TDest, TViewer>);
|
|
15
15
|
abstract sourceEnt(id: ID): Promise<Ent | null>;
|
|
16
16
|
private idVisible;
|
|
17
17
|
queryRawCount(): Promise<number>;
|
package/core/query/query.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
|
|
|
41
41
|
private idMap;
|
|
42
42
|
private idsToFetch;
|
|
43
43
|
constructor(viewer: Viewer, sortCol: string);
|
|
44
|
-
getPrivacyPolicy(): PrivacyPolicy<Ent
|
|
44
|
+
getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
|
|
45
45
|
abstract sourceEnt(id: ID): Promise<Ent | null>;
|
|
46
46
|
first(n: number, after?: string): this;
|
|
47
47
|
last(n: number, before?: string): this;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function assocTests(): void;
|
|
1
|
+
export declare function assocTests(global?: boolean): void;
|
|
@@ -27,7 +27,7 @@ const jest_date_mock_1 = require("jest-date-mock");
|
|
|
27
27
|
const index_1 = require("../../testutils/fake_data/index");
|
|
28
28
|
const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
|
|
29
29
|
const db_1 = __importStar(require("../db"));
|
|
30
|
-
function assocTests() {
|
|
30
|
+
function assocTests(global = false) {
|
|
31
31
|
describe("custom edge", () => {
|
|
32
32
|
let user1, user2;
|
|
33
33
|
beforeEach(async () => {
|
|
@@ -76,9 +76,16 @@ function assocTests() {
|
|
|
76
76
|
for (let i = 0; i < numQueries; i++) {
|
|
77
77
|
const query = queries[i];
|
|
78
78
|
let expLimit = disablePaginationBump ? limit : limit + 1;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
if (global) {
|
|
80
|
+
expect(query.qs?.whereClause, `${i}`).toBe(
|
|
81
|
+
// default limit
|
|
82
|
+
`id1 = $1 AND edge_type = $2 AND deleted_at IS NULL ORDER BY time DESC LIMIT ${expLimit}`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
expect(query.qs?.whereClause, `${i}`).toBe(
|
|
86
|
+
// default limit
|
|
87
|
+
`id1 = $1 AND edge_type = $2 ORDER BY time DESC LIMIT ${expLimit}`);
|
|
88
|
+
}
|
|
82
89
|
}
|
|
83
90
|
}
|
|
84
91
|
function verifyCountQuery({ length = 1, numQueries = 1 }) {
|
|
@@ -89,7 +96,12 @@ function assocTests() {
|
|
|
89
96
|
expect(queries.length).toBe(length);
|
|
90
97
|
for (let i = 0; i < numQueries; i++) {
|
|
91
98
|
const query = queries[i];
|
|
92
|
-
|
|
99
|
+
if (global) {
|
|
100
|
+
expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2 AND deleted_at IS NULL`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2`);
|
|
104
|
+
}
|
|
93
105
|
}
|
|
94
106
|
}
|
|
95
107
|
// TODO need to test multi-ids with id1s that aren't visible...
|