@snowtop/ent 0.0.34 → 0.0.37
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/core/base.d.ts +2 -1
- package/core/base.js +16 -0
- package/core/loaders/assoc_edge_loader.d.ts +1 -1
- package/core/loaders/assoc_edge_loader.js +5 -4
- package/core/privacy.js +3 -0
- package/package.json +1 -1
- package/parse_schema/parse.d.ts +9 -2
- package/parse_schema/parse.js +52 -20
- package/schema/schema.d.ts +2 -0
- package/testutils/ent-graphql-tests/index.d.ts +2 -0
- package/testutils/ent-graphql-tests/index.js +7 -5
package/core/base.d.ts
CHANGED
|
@@ -108,6 +108,7 @@ declare enum privacyResult {
|
|
|
108
108
|
export interface PrivacyResult {
|
|
109
109
|
result: privacyResult;
|
|
110
110
|
error?: PrivacyError;
|
|
111
|
+
getError?(policy: PrivacyPolicy, rule: PrivacyPolicyRule, ent?: Ent): PrivacyError;
|
|
111
112
|
}
|
|
112
113
|
export interface PrivacyError extends Error {
|
|
113
114
|
privacyPolicy: PrivacyPolicy;
|
|
@@ -116,7 +117,7 @@ export interface PrivacyError extends Error {
|
|
|
116
117
|
export declare function Allow(): PrivacyResult;
|
|
117
118
|
export declare function Skip(): PrivacyResult;
|
|
118
119
|
export declare function Deny(): PrivacyResult;
|
|
119
|
-
export declare function DenyWithReason(e: PrivacyError): PrivacyResult;
|
|
120
|
+
export declare function DenyWithReason(e: PrivacyError | string): PrivacyResult;
|
|
120
121
|
export interface PrivacyPolicyRule {
|
|
121
122
|
apply(v: Viewer, ent?: Ent): Promise<PrivacyResult>;
|
|
122
123
|
}
|
package/core/base.js
CHANGED
|
@@ -30,7 +30,23 @@ function Deny() {
|
|
|
30
30
|
return deny;
|
|
31
31
|
}
|
|
32
32
|
exports.Deny = Deny;
|
|
33
|
+
class DenyWithReasonError extends Error {
|
|
34
|
+
constructor(privacyPolicy, rule, msg, ent) {
|
|
35
|
+
super(msg);
|
|
36
|
+
this.privacyPolicy = privacyPolicy;
|
|
37
|
+
this.privacyRule = rule;
|
|
38
|
+
this.ent = ent;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
33
41
|
function DenyWithReason(e) {
|
|
42
|
+
if (typeof e === "string") {
|
|
43
|
+
return {
|
|
44
|
+
result: privacyResult.Deny,
|
|
45
|
+
getError(policy, rule, ent) {
|
|
46
|
+
return new DenyWithReasonError(policy, rule, e, ent);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
34
50
|
return {
|
|
35
51
|
result: privacyResult.Deny,
|
|
36
52
|
error: e,
|
|
@@ -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
|
package/core/privacy.js
CHANGED
package/package.json
CHANGED
package/parse_schema/parse.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema, AssocEdge, AssocEdgeGroup, Action } from "../schema";
|
|
1
|
+
import { Schema, Field, AssocEdge, AssocEdgeGroup, Action } from "../schema";
|
|
2
2
|
import { ActionField } from "../schema/schema";
|
|
3
3
|
declare enum NullableResult {
|
|
4
4
|
CONTENTS = "contents",
|
|
@@ -12,10 +12,11 @@ declare type ProcessedAssocEdge = Omit<AssocEdge, "actionOnlyFields" | "edgeActi
|
|
|
12
12
|
patternName?: string;
|
|
13
13
|
edgeActions?: OutputAction[];
|
|
14
14
|
};
|
|
15
|
-
declare type ProcessedSchema = Omit<Schema, "edges" | "actions" | "edgeGroups"> & {
|
|
15
|
+
declare type ProcessedSchema = Omit<Schema, "edges" | "actions" | "edgeGroups" | "fields"> & {
|
|
16
16
|
actions: OutputAction[];
|
|
17
17
|
assocEdges: ProcessedAssocEdge[];
|
|
18
18
|
assocEdgeGroups: ProcessedAssocEdgeGroup[];
|
|
19
|
+
fields: ProcessedField[];
|
|
19
20
|
};
|
|
20
21
|
declare type ProcessedAssocEdgeGroup = Omit<AssocEdgeGroup, "edgeAction"> & {
|
|
21
22
|
edgeAction?: OutputAction;
|
|
@@ -29,7 +30,13 @@ interface schemasDict {
|
|
|
29
30
|
interface ProcessedPattern {
|
|
30
31
|
name: string;
|
|
31
32
|
assocEdges: ProcessedAssocEdge[];
|
|
33
|
+
fields: ProcessedField[];
|
|
32
34
|
}
|
|
35
|
+
declare type ProcessedField = Omit<Field, "defaultValueOnEdit" | "defaultValueOnCreate"> & {
|
|
36
|
+
hasDefaultValueOnCreate?: boolean;
|
|
37
|
+
hasDefaultValueOnEdit?: boolean;
|
|
38
|
+
patternName?: string;
|
|
39
|
+
};
|
|
33
40
|
interface patternsDict {
|
|
34
41
|
[key: string]: ProcessedPattern;
|
|
35
42
|
}
|
package/parse_schema/parse.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSchema = void 0;
|
|
4
|
-
function processFields(
|
|
4
|
+
function processFields(src, patternName) {
|
|
5
|
+
const ret = [];
|
|
5
6
|
for (const field of src) {
|
|
6
7
|
let f = { ...field };
|
|
7
|
-
f
|
|
8
|
-
f
|
|
8
|
+
f.hasDefaultValueOnCreate = field.defaultValueOnCreate != undefined;
|
|
9
|
+
f.hasDefaultValueOnEdit = field.defaultValueOnEdit != undefined;
|
|
9
10
|
if (field.polymorphic) {
|
|
10
11
|
// convert boolean into object
|
|
11
12
|
// we keep boolean as an option to keep API simple
|
|
12
13
|
if (typeof field.polymorphic === "boolean") {
|
|
13
|
-
f
|
|
14
|
+
f.polymorphic = {};
|
|
14
15
|
}
|
|
15
16
|
else {
|
|
16
|
-
f
|
|
17
|
+
f.polymorphic = field.polymorphic;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
else {
|
|
21
|
+
delete f.polymorphic;
|
|
22
|
+
}
|
|
19
23
|
// convert string to object to make API consumed by go simple
|
|
20
24
|
if (f.fieldEdge && f.fieldEdge.inverseEdge) {
|
|
21
25
|
if (typeof f.fieldEdge.inverseEdge === "string") {
|
|
@@ -24,16 +28,41 @@ function processFields(processedSchema, src) {
|
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
if (patternName) {
|
|
32
|
+
f.patternName = patternName;
|
|
33
|
+
}
|
|
34
|
+
transformType(field.type);
|
|
35
|
+
ret.push(f);
|
|
36
|
+
}
|
|
37
|
+
return ret;
|
|
38
|
+
}
|
|
39
|
+
function transformImportType(typ) {
|
|
40
|
+
if (!typ.importType) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
typ.importType = {
|
|
44
|
+
...typ.importType,
|
|
45
|
+
// these 2 needed for forwards compatibility with new go schema
|
|
46
|
+
importPath: typ.importType.path,
|
|
47
|
+
import: typ.importType.type,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function transformType(typ) {
|
|
51
|
+
if (!typ) {
|
|
52
|
+
return;
|
|
28
53
|
}
|
|
54
|
+
transformImportType(typ);
|
|
55
|
+
transformType(typ.listElemType);
|
|
29
56
|
}
|
|
30
|
-
function processEdges(
|
|
57
|
+
function processEdges(src, patternName) {
|
|
58
|
+
const ret = [];
|
|
31
59
|
for (const edge of src) {
|
|
32
60
|
let edge2 = { ...edge };
|
|
33
61
|
edge2.edgeActions = edge.edgeActions?.map((action) => processAction(action));
|
|
34
62
|
edge2.patternName = patternName;
|
|
35
|
-
|
|
63
|
+
ret.push(edge2);
|
|
36
64
|
}
|
|
65
|
+
return ret;
|
|
37
66
|
}
|
|
38
67
|
function processEdgeGroups(processedSchema, edgeGroups) {
|
|
39
68
|
// array-ify this
|
|
@@ -49,26 +78,26 @@ function processEdgeGroups(processedSchema, edgeGroups) {
|
|
|
49
78
|
}
|
|
50
79
|
}
|
|
51
80
|
function processPattern(patterns, pattern, processedSchema) {
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
const name = pattern.name;
|
|
82
|
+
const fields = processFields(pattern.fields, pattern.name);
|
|
83
|
+
processedSchema.fields.push(...fields);
|
|
84
|
+
if (pattern.edges) {
|
|
85
|
+
const edges = processEdges(pattern.edges, pattern.name);
|
|
86
|
+
processedSchema.assocEdges.push(...edges);
|
|
87
|
+
}
|
|
54
88
|
if (patterns[name] === undefined) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
processEdges(edges, pattern.edges);
|
|
58
|
-
}
|
|
89
|
+
// intentionally processing separately and not passing pattern.name
|
|
90
|
+
const edges = processEdges(pattern.edges || []);
|
|
59
91
|
patterns[name] = {
|
|
60
92
|
name: pattern.name,
|
|
61
93
|
assocEdges: edges,
|
|
94
|
+
fields: fields,
|
|
62
95
|
};
|
|
63
96
|
}
|
|
64
97
|
else {
|
|
65
98
|
// TODO ideally we want to make sure that different patterns don't have the same name
|
|
66
99
|
// can't do a deepEqual check because function calls and therefore different instances in fields
|
|
67
100
|
}
|
|
68
|
-
processFields(processedSchema, pattern.fields);
|
|
69
|
-
if (pattern.edges) {
|
|
70
|
-
processEdges(processedSchema.assocEdges, pattern.edges, pattern.name);
|
|
71
|
-
}
|
|
72
101
|
}
|
|
73
102
|
var NullableResult;
|
|
74
103
|
(function (NullableResult) {
|
|
@@ -84,6 +113,7 @@ function processAction(action) {
|
|
|
84
113
|
let actionOnlyFields = action.actionOnlyFields.map((f) => {
|
|
85
114
|
let f2 = f;
|
|
86
115
|
if (!f.nullable) {
|
|
116
|
+
delete f2.nullable;
|
|
87
117
|
return f2;
|
|
88
118
|
}
|
|
89
119
|
if (typeof f.nullable === "boolean") {
|
|
@@ -133,9 +163,11 @@ function parseSchema(potentialSchemas) {
|
|
|
133
163
|
processPattern(patterns, pattern, processedSchema);
|
|
134
164
|
}
|
|
135
165
|
}
|
|
136
|
-
processFields(
|
|
166
|
+
const fields = processFields(schema.fields);
|
|
167
|
+
processedSchema.fields.push(...fields);
|
|
137
168
|
if (schema.edges) {
|
|
138
|
-
processEdges(
|
|
169
|
+
const edges = processEdges(schema.edges);
|
|
170
|
+
processedSchema.assocEdges.push(...edges);
|
|
139
171
|
}
|
|
140
172
|
if (schema.edgeGroups) {
|
|
141
173
|
processEdgeGroups(processedSchema, schema.edgeGroups);
|
package/schema/schema.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ export declare enum DBType {
|
|
|
82
82
|
export interface ImportType {
|
|
83
83
|
path: string;
|
|
84
84
|
type: string;
|
|
85
|
+
[x: string]: any;
|
|
85
86
|
}
|
|
86
87
|
declare type EnumMap = {
|
|
87
88
|
[key: string]: string;
|
|
@@ -131,6 +132,7 @@ export interface FieldOptions {
|
|
|
131
132
|
fieldEdge?: FieldEdge;
|
|
132
133
|
primaryKey?: boolean;
|
|
133
134
|
disableUserEditable?: boolean;
|
|
135
|
+
disableUserGraphQLEditable?: boolean;
|
|
134
136
|
defaultValueOnCreate?(builder: Builder<Ent>, input: Data): any;
|
|
135
137
|
defaultToViewerOnCreate?: boolean;
|
|
136
138
|
defaultValueOnEdit?(builder: Builder<Ent>, input: Data): any;
|
|
@@ -16,6 +16,8 @@ interface queryConfig {
|
|
|
16
16
|
callback?: (res: supertest.Response) => void;
|
|
17
17
|
inlineFragmentRoot?: string;
|
|
18
18
|
customHandlers?: RequestHandler[];
|
|
19
|
+
server?: any;
|
|
20
|
+
graphQLPath?: string;
|
|
19
21
|
}
|
|
20
22
|
export interface queryRootConfig extends queryConfig {
|
|
21
23
|
root: string;
|
|
@@ -56,7 +56,7 @@ function server(config) {
|
|
|
56
56
|
};
|
|
57
57
|
return doWork();
|
|
58
58
|
}));
|
|
59
|
-
app.use("/graphql", ...handlers);
|
|
59
|
+
app.use(config.graphQLPath || "/graphql", ...handlers);
|
|
60
60
|
return app;
|
|
61
61
|
}
|
|
62
62
|
function getInnerType(typ, list) {
|
|
@@ -72,14 +72,14 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
72
72
|
let test;
|
|
73
73
|
if (config.test) {
|
|
74
74
|
if (typeof config.test === "function") {
|
|
75
|
-
test = config.test(server(config));
|
|
75
|
+
test = config.test(config.server ? config.server : server(config));
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
78
|
test = config.test;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
else {
|
|
82
|
-
test = (0, supertest_1.default)(server(config));
|
|
82
|
+
test = (0, supertest_1.default)(config.server ? config.server : server(config));
|
|
83
83
|
}
|
|
84
84
|
let files = new Map();
|
|
85
85
|
// handle files
|
|
@@ -104,7 +104,9 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
if (files.size) {
|
|
107
|
-
let ret = test
|
|
107
|
+
let ret = test
|
|
108
|
+
.post(config.graphQLPath || "/graphql")
|
|
109
|
+
.set(config.headers || {});
|
|
108
110
|
ret.field("operations", JSON.stringify({
|
|
109
111
|
query: query,
|
|
110
112
|
variables: config.args,
|
|
@@ -130,7 +132,7 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
130
132
|
return [
|
|
131
133
|
test,
|
|
132
134
|
test
|
|
133
|
-
.post("/graphql")
|
|
135
|
+
.post(config.graphQLPath || "/graphql")
|
|
134
136
|
.set(config.headers || {})
|
|
135
137
|
.send({
|
|
136
138
|
query: query,
|