@snowtop/ent 0.1.0-alpha8 → 0.1.0-alpha80
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 +27 -25
- package/action/executor.d.ts +3 -3
- 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 +37 -16
- package/action/orchestrator.js +184 -54
- package/action/privacy.d.ts +2 -2
- package/core/base.d.ts +38 -22
- package/core/clause.d.ts +65 -7
- package/core/clause.js +261 -54
- package/core/config.d.ts +8 -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 +1 -2
- package/core/db.js +1 -1
- package/core/ent.d.ts +76 -24
- package/core/ent.js +459 -143
- 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 +2 -2
- package/core/loaders/loader.js +5 -5
- package/core/loaders/object_loader.d.ts +4 -3
- package/core/loaders/object_loader.js +22 -5
- 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 +21 -25
- 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 +3 -3
- package/core/viewer.js +1 -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.js +8 -2
- 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 +10 -5
- package/index.js +13 -6
- package/package.json +2 -2
- package/parse_schema/parse.d.ts +14 -2
- package/parse_schema/parse.js +40 -2
- package/schema/base_schema.d.ts +1 -1
- package/schema/base_schema.js +3 -0
- package/schema/field.d.ts +36 -7
- package/schema/field.js +70 -2
- package/schema/index.d.ts +2 -2
- package/schema/json_field.d.ts +13 -1
- package/schema/json_field.js +28 -1
- package/schema/schema.d.ts +61 -10
- package/schema/schema.js +18 -4
- package/schema/struct_field.d.ts +11 -1
- package/schema/struct_field.js +43 -4
- package/scripts/custom_graphql.js +5 -1
- 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 +31 -21
- package/testutils/builder.js +82 -29
- package/testutils/db/fixture.d.ts +10 -0
- package/testutils/db/fixture.js +26 -0
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +15 -3
- package/testutils/db/{test_db.js → temp_db.js} +63 -15
- package/testutils/db/value.d.ts +6 -0
- package/testutils/db/value.js +251 -0
- package/testutils/db_time_zone.d.ts +4 -0
- package/testutils/db_time_zone.js +41 -0
- package/testutils/ent-graphql-tests/index.js +19 -12
- package/testutils/fake_data/fake_contact.d.ts +3 -3
- package/testutils/fake_data/fake_contact.js +9 -6
- package/testutils/fake_data/fake_event.d.ts +3 -3
- package/testutils/fake_data/fake_event.js +8 -5
- package/testutils/fake_data/fake_user.d.ts +4 -4
- package/testutils/fake_data/fake_user.js +16 -13
- package/testutils/fake_data/test_helpers.d.ts +2 -2
- package/testutils/fake_data/test_helpers.js +5 -5
- 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 +29 -7
- 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 -437
|
@@ -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;
|
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,18 +1,19 @@
|
|
|
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
10
|
getOptions(): SelectDataOptions;
|
|
11
11
|
private initPrime;
|
|
12
12
|
load(key: T): Promise<Data | null>;
|
|
13
13
|
clearAll(): void;
|
|
14
14
|
loadMany(keys: T[]): Promise<Data[]>;
|
|
15
15
|
prime(data: Data): void;
|
|
16
|
+
primeAll(data: Data): void;
|
|
16
17
|
}
|
|
17
18
|
interface ObjectLoaderOptions extends SelectDataOptions {
|
|
18
19
|
instanceKey?: string;
|
|
@@ -53,7 +53,7 @@ function createDataLoader(options) {
|
|
|
53
53
|
optionClause = options.clause;
|
|
54
54
|
}
|
|
55
55
|
if (optionClause) {
|
|
56
|
-
cls = clause.And(
|
|
56
|
+
cls = clause.And(cls, optionClause);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
const rowOptions = {
|
|
@@ -71,6 +71,9 @@ function createDataLoader(options) {
|
|
|
71
71
|
const rows = await (0, ent_1.loadRows)(rowOptions);
|
|
72
72
|
for (const row of rows) {
|
|
73
73
|
const id = row[col];
|
|
74
|
+
if (id === undefined) {
|
|
75
|
+
throw new Error(`need to query for column ${col} when using an object loader because the query may not be sorted and we need the id to maintain sort order`);
|
|
76
|
+
}
|
|
74
77
|
const idx = m.get(id);
|
|
75
78
|
if (idx === undefined) {
|
|
76
79
|
throw new Error(`malformed query. got ${id} back but didn't query for it`);
|
|
@@ -136,7 +139,7 @@ class ObjectLoader {
|
|
|
136
139
|
optionClause = this.options.clause;
|
|
137
140
|
}
|
|
138
141
|
if (optionClause) {
|
|
139
|
-
cls = clause.And(
|
|
142
|
+
cls = clause.And(cls, optionClause);
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
const rowOptions = {
|
|
@@ -163,7 +166,7 @@ class ObjectLoader {
|
|
|
163
166
|
optionClause = this.options.clause;
|
|
164
167
|
}
|
|
165
168
|
if (optionClause) {
|
|
166
|
-
cls = clause.And(
|
|
169
|
+
cls = clause.And(cls, optionClause);
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
const rowOptions = {
|
|
@@ -181,14 +184,28 @@ class ObjectLoader {
|
|
|
181
184
|
this.loader.prime(key, data);
|
|
182
185
|
}
|
|
183
186
|
}
|
|
187
|
+
// prime this loader and any other loaders it's aware of
|
|
188
|
+
primeAll(data) {
|
|
189
|
+
this.prime(data);
|
|
190
|
+
if (this.primedLoaders) {
|
|
191
|
+
for (const [key, loader] of this.primedLoaders) {
|
|
192
|
+
const value = data[key];
|
|
193
|
+
if (value !== undefined) {
|
|
194
|
+
loader.prime(data);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
184
199
|
}
|
|
185
200
|
exports.ObjectLoader = ObjectLoader;
|
|
201
|
+
// NOTE: if not querying for all columns
|
|
202
|
+
// have to query for the id field as one of the fields
|
|
203
|
+
// because it's used to maintain sort order of the queried ids
|
|
186
204
|
class ObjectLoaderFactory {
|
|
187
205
|
constructor(options) {
|
|
188
206
|
this.options = options;
|
|
189
207
|
this.toPrime = [];
|
|
190
|
-
|
|
191
|
-
let instanceKey = "";
|
|
208
|
+
let instanceKey = options.instanceKey || "";
|
|
192
209
|
if (typeof this.options.clause === "function") {
|
|
193
210
|
if (!options.instanceKey) {
|
|
194
211
|
throw new Error(`need to pass an instanceKey to ObjectLoader if clause is a function`);
|
|
@@ -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,45 +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;
|
|
466
462
|
}
|
|
467
463
|
if (res.getError) {
|
|
468
|
-
|
|
464
|
+
return res.getError(policy, rule, ent);
|
|
469
465
|
}
|
|
470
466
|
if (throwErr) {
|
|
471
|
-
|
|
467
|
+
return throwErr();
|
|
472
468
|
}
|
|
473
|
-
|
|
469
|
+
return new EntPrivacyError(policy, rule, ent);
|
|
474
470
|
}
|
|
475
471
|
}
|
|
476
|
-
|
|
472
|
+
return new EntInvalidPrivacyPolicyError(policy, ent);
|
|
477
473
|
}
|
|
478
|
-
exports.
|
|
474
|
+
exports.applyPrivacyPolicyImpl = applyPrivacyPolicyImpl;
|
|
479
475
|
exports.AlwaysAllowPrivacyPolicy = {
|
|
480
476
|
rules: [exports.AlwaysAllowRule],
|
|
481
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...
|
|
@@ -4,11 +4,14 @@ import { EdgeQuery } from "./query";
|
|
|
4
4
|
interface options<TData extends Data> {
|
|
5
5
|
newQuery: (v: Viewer, user: FakeUser) => EdgeQuery<FakeUser, FakeContact, TData>;
|
|
6
6
|
tableName: string;
|
|
7
|
+
uniqKey: string;
|
|
7
8
|
entsLength?: number;
|
|
8
9
|
where: string;
|
|
9
10
|
sortCol: string;
|
|
10
11
|
livePostgresDB?: boolean;
|
|
11
12
|
sqlite?: boolean;
|
|
13
|
+
globalSchema?: boolean;
|
|
14
|
+
rawDataVerify?(user: FakeUser): Promise<void>;
|
|
12
15
|
}
|
|
13
16
|
export declare const commonTests: <TData extends Data>(opts: options<TData>) => void;
|
|
14
17
|
export {};
|