@snowtop/ent 0.1.0-alpha6 → 0.1.0-alpha9
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 +2 -0
- package/action/executor.d.ts +1 -1
- package/action/orchestrator.d.ts +10 -2
- package/action/orchestrator.js +128 -34
- package/core/base.d.ts +5 -1
- package/core/base.js +16 -0
- package/core/clause.d.ts +24 -3
- package/core/clause.js +246 -5
- package/core/config.d.ts +18 -0
- package/core/config.js +17 -0
- package/core/db.d.ts +3 -3
- package/core/db.js +2 -0
- package/core/ent.d.ts +2 -4
- package/core/ent.js +70 -23
- package/core/loaders/assoc_edge_loader.d.ts +1 -1
- package/core/loaders/assoc_edge_loader.js +5 -4
- package/core/loaders/index_loader.js +1 -0
- package/core/loaders/object_loader.d.ts +7 -2
- package/core/loaders/object_loader.js +59 -4
- package/core/privacy.js +3 -0
- package/core/viewer.d.ts +1 -0
- package/core/viewer.js +4 -0
- 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 +24 -23
- package/graphql/node_resolver.d.ts +0 -1
- package/graphql/query/connection_type.js +6 -6
- 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 +16 -1
- package/index.js +18 -5
- package/package.json +3 -3
- package/parse_schema/parse.d.ts +16 -5
- package/parse_schema/parse.js +51 -6
- package/schema/base_schema.d.ts +36 -1
- package/schema/base_schema.js +48 -2
- package/schema/field.js +1 -1
- package/schema/index.d.ts +2 -2
- package/schema/index.js +8 -1
- package/schema/schema.d.ts +50 -1
- package/schema/schema.js +113 -5
- package/scripts/custom_graphql.js +122 -15
- package/scripts/read_schema.js +15 -1
- package/scripts/transform_schema.js +212 -55
- package/testutils/builder.d.ts +5 -1
- package/testutils/builder.js +46 -2
- package/testutils/context/test_context.d.ts +2 -2
- package/testutils/context/test_context.js +7 -1
- package/testutils/db/test_db.d.ts +2 -1
- package/testutils/db/test_db.js +13 -4
- 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 +2 -6
- package/testutils/fake_data/fake_contact.js +9 -16
- package/testutils/fake_data/fake_event.d.ts +2 -6
- package/testutils/fake_data/fake_event.js +17 -24
- package/testutils/fake_data/fake_user.d.ts +2 -6
- package/testutils/fake_data/fake_user.js +10 -17
- package/testutils/fake_data/test_helpers.js +1 -1
|
@@ -24,6 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const glob_1 = __importDefault(require("glob"));
|
|
27
|
+
const json5_1 = __importDefault(require("json5"));
|
|
27
28
|
const minimist_1 = __importDefault(require("minimist"));
|
|
28
29
|
const graphql_1 = require("../graphql/graphql");
|
|
29
30
|
const readline = __importStar(require("readline"));
|
|
@@ -53,7 +54,103 @@ async function readInputs() {
|
|
|
53
54
|
});
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
function processCustomObjects(l, gqlCapture, input) {
|
|
58
|
+
let m;
|
|
59
|
+
if (input) {
|
|
60
|
+
m = gqlCapture.getCustomInputObjects();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
m = gqlCapture.getCustomObjects();
|
|
64
|
+
}
|
|
65
|
+
for (const input of l) {
|
|
66
|
+
m.set(input.name, {
|
|
67
|
+
nodeName: input.graphQLName || input.name,
|
|
68
|
+
className: input.name,
|
|
69
|
+
});
|
|
70
|
+
if (input.fields) {
|
|
71
|
+
processCustomFields(input.fields, gqlCapture, input.name);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function transformArgs(f) {
|
|
76
|
+
return (f.args || []).map((v) => {
|
|
77
|
+
const ret = {
|
|
78
|
+
...v,
|
|
79
|
+
};
|
|
80
|
+
// duplicated from getType in graphql.ts
|
|
81
|
+
if ((0, graphql_1.isCustomType)(ret.type)) {
|
|
82
|
+
ret.type = v.type.type;
|
|
83
|
+
(0, graphql_1.addCustomType)(v.type);
|
|
84
|
+
}
|
|
85
|
+
// scalar types not supported for now
|
|
86
|
+
ret.tsType = graphql_1.knownAllowedNames.get(v.type);
|
|
87
|
+
return ret;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function transformResultType(f) {
|
|
91
|
+
return f.resultType
|
|
92
|
+
? [
|
|
93
|
+
{
|
|
94
|
+
name: "",
|
|
95
|
+
type: f.resultType,
|
|
96
|
+
tsType: graphql_1.knownAllowedNames.get(f.resultType),
|
|
97
|
+
list: f.list,
|
|
98
|
+
nullable: f.nullable,
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
: [];
|
|
102
|
+
}
|
|
103
|
+
function processTopLevel(l, l2) {
|
|
104
|
+
for (const custom of l) {
|
|
105
|
+
l2.push({
|
|
106
|
+
nodeName: custom.class,
|
|
107
|
+
functionName: custom.functionName || custom.name,
|
|
108
|
+
gqlName: custom.graphQLName || custom.name,
|
|
109
|
+
fieldType: custom.fieldType,
|
|
110
|
+
args: transformArgs(custom),
|
|
111
|
+
results: transformResultType(custom),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function processCustomFields(fields, gqlCapture, nodeName) {
|
|
116
|
+
const m = gqlCapture.getCustomFields();
|
|
117
|
+
let results = [];
|
|
118
|
+
for (const f of fields) {
|
|
119
|
+
results.push({
|
|
120
|
+
nodeName: nodeName,
|
|
121
|
+
gqlName: f.graphQLName || f.name,
|
|
122
|
+
functionName: f.functionName || f.name,
|
|
123
|
+
fieldType: f.fieldType,
|
|
124
|
+
args: transformArgs(f),
|
|
125
|
+
results: transformResultType(f),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
m.set(nodeName, results);
|
|
129
|
+
}
|
|
130
|
+
async function captureCustom(filePath, filesCsv, jsonPath, gqlCapture) {
|
|
131
|
+
if (jsonPath !== undefined) {
|
|
132
|
+
let json = json5_1.default.parse(fs.readFileSync(jsonPath, {
|
|
133
|
+
encoding: "utf8",
|
|
134
|
+
}));
|
|
135
|
+
if (json.fields) {
|
|
136
|
+
for (const k in json.fields) {
|
|
137
|
+
processCustomFields(json.fields[k], gqlCapture, k);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (json.inputs) {
|
|
141
|
+
processCustomObjects(json.inputs, gqlCapture, true);
|
|
142
|
+
}
|
|
143
|
+
if (json.objects) {
|
|
144
|
+
processCustomObjects(json.objects, gqlCapture);
|
|
145
|
+
}
|
|
146
|
+
if (json.queries) {
|
|
147
|
+
processTopLevel(json.queries, gqlCapture.getCustomQueries());
|
|
148
|
+
}
|
|
149
|
+
if (json.mutations) {
|
|
150
|
+
processTopLevel(json.mutations, gqlCapture.getCustomMutations());
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
57
154
|
if (filesCsv !== undefined) {
|
|
58
155
|
let files = filesCsv.split(",");
|
|
59
156
|
for (let i = 0; i < files.length; i++) {
|
|
@@ -153,15 +250,25 @@ async function main() {
|
|
|
153
250
|
if (!gqlPath) {
|
|
154
251
|
throw new Error("could not find graphql path");
|
|
155
252
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
253
|
+
// use different variable so that we use the correct GQLCapture as needed
|
|
254
|
+
// for local dev, get the one from the file system. otherwise, get the one
|
|
255
|
+
// from node_modules
|
|
256
|
+
let gqlCapture;
|
|
257
|
+
if (process.env.LOCAL_SCRIPT_PATH) {
|
|
258
|
+
const r = require("../graphql/graphql");
|
|
259
|
+
gqlCapture = r.GQLCapture;
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
const r = require(gqlPath);
|
|
263
|
+
if (!r.GQLCapture) {
|
|
264
|
+
throw new Error("could not find GQLCapture in module");
|
|
265
|
+
}
|
|
266
|
+
gqlCapture = r.GQLCapture;
|
|
267
|
+
gqlCapture.enable(true);
|
|
159
268
|
}
|
|
160
|
-
const GQLCapture = r.GQLCapture;
|
|
161
|
-
GQLCapture.enable(true);
|
|
162
269
|
const [inputsRead, _, imports] = await Promise.all([
|
|
163
270
|
readInputs(),
|
|
164
|
-
captureCustom(options.path, options.files),
|
|
271
|
+
captureCustom(options.path, options.files, options.json_path, gqlCapture),
|
|
165
272
|
parseImports(options.path),
|
|
166
273
|
]);
|
|
167
274
|
const { nodes, nodesMap } = inputsRead;
|
|
@@ -172,14 +279,14 @@ async function main() {
|
|
|
172
279
|
}
|
|
173
280
|
return result;
|
|
174
281
|
}
|
|
175
|
-
|
|
176
|
-
let args = fromMap(
|
|
177
|
-
let inputs = fromMap(
|
|
178
|
-
let fields =
|
|
179
|
-
let queries =
|
|
180
|
-
let mutations =
|
|
181
|
-
let objects = fromMap(
|
|
182
|
-
let customTypes = fromMap(
|
|
282
|
+
gqlCapture.resolve(nodes);
|
|
283
|
+
let args = fromMap(gqlCapture.getCustomArgs());
|
|
284
|
+
let inputs = fromMap(gqlCapture.getCustomInputObjects());
|
|
285
|
+
let fields = gqlCapture.getProcessedCustomFields();
|
|
286
|
+
let queries = gqlCapture.getProcessedCustomQueries();
|
|
287
|
+
let mutations = gqlCapture.getProcessedCustomMutations();
|
|
288
|
+
let objects = fromMap(gqlCapture.getCustomObjects());
|
|
289
|
+
let customTypes = fromMap(gqlCapture.getCustomTypes());
|
|
183
290
|
let classes = {};
|
|
184
291
|
let allFiles = {};
|
|
185
292
|
const buildClasses2 = (args) => {
|
package/scripts/read_schema.js
CHANGED
|
@@ -44,7 +44,21 @@ function main() {
|
|
|
44
44
|
if (!match) {
|
|
45
45
|
throw new Error(`non-typescript file ${p} returned by glob`);
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
let schema = match[1];
|
|
48
|
+
// convert foo_schema.ts -> foo
|
|
49
|
+
if (schema.endsWith("_schema")) {
|
|
50
|
+
schema = schema.slice(0, -7);
|
|
51
|
+
}
|
|
52
|
+
let relativePath;
|
|
53
|
+
const index = p.indexOf("src/schema");
|
|
54
|
+
if (index !== -1) {
|
|
55
|
+
relativePath = p.substring(index);
|
|
56
|
+
}
|
|
57
|
+
const s = require(p).default;
|
|
58
|
+
if (relativePath !== undefined) {
|
|
59
|
+
s.schemaPath = relativePath;
|
|
60
|
+
}
|
|
61
|
+
potentialSchemas[(0, pascal_case_1.pascalCase)(schema)] = s;
|
|
48
62
|
}
|
|
49
63
|
// console.log(potentialSchemas);
|
|
50
64
|
const result = (0, parse_1.parseSchema)(potentialSchemas);
|
|
@@ -27,6 +27,7 @@ const typescript_1 = __importDefault(require("typescript"));
|
|
|
27
27
|
const fs = __importStar(require("fs"));
|
|
28
28
|
const compilerOptions_1 = require("../tsc/compilerOptions");
|
|
29
29
|
const child_process_1 = require("child_process");
|
|
30
|
+
const path_1 = __importDefault(require("path"));
|
|
30
31
|
function getTarget(target) {
|
|
31
32
|
switch (target.toLowerCase()) {
|
|
32
33
|
case "es2015":
|
|
@@ -65,13 +66,18 @@ async function main() {
|
|
|
65
66
|
// files = files.filter((f) => f.endsWith("event.ts"));
|
|
66
67
|
files.forEach((file) => {
|
|
67
68
|
// assume valid file since we do glob above
|
|
68
|
-
const idx = file.lastIndexOf(".ts");
|
|
69
|
-
const writeFile = file.substring(0, idx) + "2" + ".ts";
|
|
69
|
+
// const idx = file.lastIndexOf(".ts");
|
|
70
|
+
// const writeFile = file.substring(0, idx) + "2" + ".ts";
|
|
71
|
+
// console.debug(file);
|
|
72
|
+
const writeFile = "src/schema/" + path_1.default.basename(file).slice(0, -3) + "_schema.ts";
|
|
73
|
+
// const writeFile = file;
|
|
74
|
+
// console.debug(file, writeFile);
|
|
70
75
|
let contents = fs.readFileSync(file).toString();
|
|
71
76
|
// go through the file and print everything back if not starting immediately after other position
|
|
72
77
|
const sourceFile = typescript_1.default.createSourceFile(file, contents, target, false, typescript_1.default.ScriptKind.TS);
|
|
73
78
|
const nodes = [];
|
|
74
79
|
let updateImport = false;
|
|
80
|
+
let removeImports = [];
|
|
75
81
|
const f = {
|
|
76
82
|
trackNode: function (tni) {
|
|
77
83
|
nodes.push({
|
|
@@ -79,6 +85,9 @@ async function main() {
|
|
|
79
85
|
importNode: tni.node && typescript_1.default.isImportDeclaration(tni.node),
|
|
80
86
|
rawString: tni.rawString,
|
|
81
87
|
});
|
|
88
|
+
if (tni.removeImports) {
|
|
89
|
+
removeImports.push(...tni.removeImports);
|
|
90
|
+
}
|
|
82
91
|
},
|
|
83
92
|
flagUpdateImport() {
|
|
84
93
|
updateImport = true;
|
|
@@ -91,7 +100,7 @@ async function main() {
|
|
|
91
100
|
for (const node of nodes) {
|
|
92
101
|
if (updateImport && node.importNode) {
|
|
93
102
|
const importNode = node.node;
|
|
94
|
-
const transformedImport = transformImport(importNode, sourceFile);
|
|
103
|
+
const transformedImport = transformImport(importNode, sourceFile, removeImports);
|
|
95
104
|
if (transformedImport) {
|
|
96
105
|
newContents += transformedImport;
|
|
97
106
|
continue;
|
|
@@ -110,6 +119,7 @@ async function main() {
|
|
|
110
119
|
// console.debug(newContents);
|
|
111
120
|
// ideally there's a flag that indicates if we write
|
|
112
121
|
fs.writeFileSync(writeFile, newContents);
|
|
122
|
+
fs.rmSync(file);
|
|
113
123
|
});
|
|
114
124
|
(0, child_process_1.execSync)("prettier src/schema/*.ts --write");
|
|
115
125
|
}
|
|
@@ -129,62 +139,206 @@ function traverse(fileContents, sourceFile, f) {
|
|
|
129
139
|
});
|
|
130
140
|
return traversed;
|
|
131
141
|
}
|
|
132
|
-
// TODO need to replace class field member, print that and see what happens
|
|
133
142
|
function traverseClass(fileContents, sourceFile, node, f) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
const ci = getClassInfo(fileContents, sourceFile, node);
|
|
144
|
+
if (!ci) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
let klassContents = `${ci.comment}const ${ci.name} = new ${ci.class}({\n`;
|
|
148
|
+
let removeImports = [];
|
|
149
|
+
if (ci.implementsSchema) {
|
|
150
|
+
removeImports.push("Schema");
|
|
151
|
+
}
|
|
138
152
|
for (let member of node.members) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
153
|
+
const fInfo = getClassElementInfo(fileContents, member, sourceFile);
|
|
154
|
+
if (!fInfo) {
|
|
155
|
+
return false;
|
|
142
156
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const comment = getPreText(fileContents, member, sourceFile);
|
|
147
|
-
if (comment) {
|
|
148
|
-
fieldMap += comment;
|
|
157
|
+
klassContents += `${fInfo.comment}${fInfo.key}:${fInfo.value},\n`;
|
|
158
|
+
if (fInfo.type) {
|
|
159
|
+
removeImports.push(fInfo.type);
|
|
149
160
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
}
|
|
162
|
+
klassContents += "\n})";
|
|
163
|
+
if (ci.export && ci.default) {
|
|
164
|
+
klassContents += `\n export default ${ci.name};`;
|
|
165
|
+
}
|
|
166
|
+
else if (ci.export) {
|
|
167
|
+
klassContents = "export " + klassContents;
|
|
168
|
+
}
|
|
169
|
+
// console.debug(klassContents);
|
|
170
|
+
f.trackNode({ rawString: klassContents, removeImports: removeImports });
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
function transformSchema(str) {
|
|
174
|
+
// only do known class names
|
|
175
|
+
if (str === "BaseEntSchema" || str === "BaseEntSchemaWithTZ") {
|
|
176
|
+
return str.substring(4);
|
|
177
|
+
}
|
|
178
|
+
return str;
|
|
179
|
+
}
|
|
180
|
+
function getClassInfo(fileContents, sourceFile, node) {
|
|
181
|
+
let className = node.name?.text;
|
|
182
|
+
if (!className?.endsWith("Schema")) {
|
|
183
|
+
className += "Schema";
|
|
184
|
+
}
|
|
185
|
+
let classExtends;
|
|
186
|
+
let implementsSchema = false;
|
|
187
|
+
if (node.heritageClauses) {
|
|
188
|
+
for (const hc of node.heritageClauses) {
|
|
189
|
+
if (hc.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
|
|
190
|
+
for (const type of hc.types) {
|
|
191
|
+
if (type.expression.getText(sourceFile) === "Schema") {
|
|
192
|
+
implementsSchema = true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
159
196
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
197
|
+
// ts.SyntaxKind.ExtendsKeyword
|
|
198
|
+
// can only extend one class
|
|
199
|
+
for (const type of hc.types) {
|
|
200
|
+
const text = type.expression.getText(sourceFile);
|
|
201
|
+
const transformed = transformSchema(text);
|
|
202
|
+
if (transformed === text) {
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
classExtends = transformed;
|
|
165
206
|
}
|
|
166
|
-
|
|
167
|
-
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!className || !node.heritageClauses || !classExtends) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
let ci = {
|
|
213
|
+
name: className,
|
|
214
|
+
class: classExtends,
|
|
215
|
+
comment: getPreText(fileContents, node, sourceFile),
|
|
216
|
+
implementsSchema,
|
|
217
|
+
};
|
|
218
|
+
if (node.modifiers) {
|
|
219
|
+
for (const mod of node.modifiers) {
|
|
220
|
+
const text = mod.getText(sourceFile);
|
|
221
|
+
if (text === "export") {
|
|
222
|
+
ci.export = true;
|
|
168
223
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let fnCall = "";
|
|
172
|
-
if (properties.length) {
|
|
173
|
-
fnCall = `{${properties.join(",")}}`;
|
|
224
|
+
else if (text === "default") {
|
|
225
|
+
ci.default = true;
|
|
174
226
|
}
|
|
175
|
-
property += `${name}:${call}(${fnCall}),`;
|
|
176
|
-
fieldMap += property;
|
|
177
227
|
}
|
|
178
|
-
fieldMap += "}";
|
|
179
|
-
klassContents += fieldMap;
|
|
180
228
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
229
|
+
return ci;
|
|
230
|
+
}
|
|
231
|
+
// intentionally doesn't parse decorators since we don't need it
|
|
232
|
+
function getClassElementInfo(fileContents, member, sourceFile) {
|
|
233
|
+
if (isFieldElement(member, sourceFile)) {
|
|
234
|
+
return getFieldElementInfo(fileContents, member, sourceFile);
|
|
235
|
+
}
|
|
236
|
+
if (member.kind === typescript_1.default.SyntaxKind.Constructor) {
|
|
237
|
+
return getConstructorElementInfo(fileContents, member, sourceFile);
|
|
238
|
+
}
|
|
239
|
+
if (member.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
// other properties
|
|
243
|
+
const property = member;
|
|
244
|
+
if (!property.initializer) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const token = property.name;
|
|
248
|
+
return {
|
|
249
|
+
key: token.escapedText.toString(),
|
|
250
|
+
value: property.initializer?.getFullText(sourceFile),
|
|
251
|
+
comment: getPreText(fileContents, member, sourceFile),
|
|
252
|
+
type: getType(property, sourceFile),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function getType(property, sourceFile) {
|
|
256
|
+
let propertytype = property.type?.getText(sourceFile) || "";
|
|
257
|
+
let ends = ["| null", "[]"];
|
|
258
|
+
for (const end of ends) {
|
|
259
|
+
if (propertytype.endsWith(end)) {
|
|
260
|
+
propertytype = propertytype.slice(0, -1 * end.length);
|
|
261
|
+
}
|
|
185
262
|
}
|
|
186
|
-
|
|
187
|
-
|
|
263
|
+
return propertytype;
|
|
264
|
+
}
|
|
265
|
+
function getFieldElementInfo(fileContents, member, sourceFile) {
|
|
266
|
+
let fieldMap = "";
|
|
267
|
+
// need to change to fields: {code: StringType()};
|
|
268
|
+
const property = member;
|
|
269
|
+
const initializer = property.initializer;
|
|
270
|
+
fieldMap += "{";
|
|
271
|
+
for (const element of initializer.elements) {
|
|
272
|
+
const parsed = parseFieldElement(element, sourceFile, fileContents);
|
|
273
|
+
if (parsed === null) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const { callEx, name, nameComment, properties } = parsed;
|
|
277
|
+
let property = "";
|
|
278
|
+
const fieldComment = getPreText(fileContents, element, sourceFile).trim();
|
|
279
|
+
if (fieldComment) {
|
|
280
|
+
property += "\n" + fieldComment + "\n";
|
|
281
|
+
}
|
|
282
|
+
if (nameComment) {
|
|
283
|
+
property += nameComment + "\n";
|
|
284
|
+
}
|
|
285
|
+
// e.g. UUIDType, StringType etc
|
|
286
|
+
let call = callEx.expression.getText(sourceFile);
|
|
287
|
+
let fnCall = "";
|
|
288
|
+
if (properties.length) {
|
|
289
|
+
fnCall = `{${properties.join(",")}}`;
|
|
290
|
+
}
|
|
291
|
+
property += `${name}:${call}(${fnCall}),`;
|
|
292
|
+
fieldMap += property;
|
|
293
|
+
}
|
|
294
|
+
fieldMap += "}";
|
|
295
|
+
return {
|
|
296
|
+
key: "fields",
|
|
297
|
+
value: fieldMap,
|
|
298
|
+
comment: getPreText(fileContents, member, sourceFile),
|
|
299
|
+
type: getType(property, sourceFile),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function getConstructorElementInfo(fileContents, member, sourceFile) {
|
|
303
|
+
const c = member;
|
|
304
|
+
//remove {}
|
|
305
|
+
let fullText = c.body?.getFullText(sourceFile) || "";
|
|
306
|
+
fullText = fullText.trim().slice(1, -1).trim();
|
|
307
|
+
// convert something like
|
|
308
|
+
/*
|
|
309
|
+
constructor() {
|
|
310
|
+
super();
|
|
311
|
+
this.addPatterns(
|
|
312
|
+
new Feedback(),
|
|
313
|
+
new DayOfWeek(),
|
|
314
|
+
new Feedback(),
|
|
315
|
+
new DayOfWeek(),
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
*/
|
|
319
|
+
// into this.addPatterns(new Feedback(),new DayOfWeek(),new Feedback(),new DayOfWeek(),)
|
|
320
|
+
const lines = fullText
|
|
321
|
+
.split("\n")
|
|
322
|
+
.map((line) => line.trim())
|
|
323
|
+
.join("")
|
|
324
|
+
.split(";")
|
|
325
|
+
.filter((f) => f != "super()" && f != "");
|
|
326
|
+
// at this point there should be only line for what we handle
|
|
327
|
+
if (lines.length != 1) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const line = lines[0];
|
|
331
|
+
const addPatterns = "this.addPatterns(";
|
|
332
|
+
if (!line.startsWith(addPatterns)) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
key: "patterns",
|
|
337
|
+
// remove this.addPatterns at the front, remove trailing ) at the end
|
|
338
|
+
// if there's a trailing comma, it'll be handled by prettier
|
|
339
|
+
value: `[${line.slice(addPatterns.length, -1)}]`,
|
|
340
|
+
comment: "",
|
|
341
|
+
};
|
|
188
342
|
}
|
|
189
343
|
function isFieldElement(member, sourceFile) {
|
|
190
344
|
if (member.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
|
|
@@ -249,7 +403,7 @@ function parseFieldElement(element, sourceFile, fileContents) {
|
|
|
249
403
|
nameComment: propertyComment,
|
|
250
404
|
};
|
|
251
405
|
}
|
|
252
|
-
function transformImport(importNode, sourceFile) {
|
|
406
|
+
function transformImport(importNode, sourceFile, removeImports) {
|
|
253
407
|
// remove quotes too
|
|
254
408
|
const text = importNode.moduleSpecifier.getText(sourceFile).slice(1, -1);
|
|
255
409
|
if (text !== "@snowtop/ent" &&
|
|
@@ -267,20 +421,23 @@ function transformImport(importNode, sourceFile) {
|
|
|
267
421
|
.substring(start + 1, end)
|
|
268
422
|
// .trim()
|
|
269
423
|
.split(",");
|
|
424
|
+
let removeImportsMap = {};
|
|
425
|
+
removeImports.forEach((imp) => (removeImportsMap[imp] = true));
|
|
426
|
+
let newImports = [];
|
|
270
427
|
for (let i = 0; i < imports.length; i++) {
|
|
271
|
-
|
|
272
|
-
if (imp
|
|
273
|
-
|
|
428
|
+
let imp = transformSchema(imports[i].trim());
|
|
429
|
+
if (removeImportsMap[imp]) {
|
|
430
|
+
continue;
|
|
274
431
|
}
|
|
432
|
+
newImports.push(imp);
|
|
275
433
|
}
|
|
276
|
-
// TODO better to update node instead of doing this but this works for now
|
|
277
434
|
return ("import " +
|
|
278
435
|
importText.substring(0, start + 1) +
|
|
279
|
-
|
|
436
|
+
newImports.join(", ") +
|
|
280
437
|
importText.substring(end) +
|
|
281
438
|
' from "' +
|
|
282
439
|
text +
|
|
283
|
-
'"');
|
|
440
|
+
'";');
|
|
284
441
|
}
|
|
285
442
|
function getPreText(fileContents, node, sourceFile) {
|
|
286
443
|
return fileContents.substring(node.getFullStart(), node.getStart(sourceFile));
|
package/testutils/builder.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Ent, ID, Viewer, Data, EntConstructor } from "../core/base";
|
|
2
2
|
import { Orchestrator } from "../action/orchestrator";
|
|
3
3
|
import { Action, Builder, Changeset, WriteOperation, Validator, Trigger, Observer } from "../action";
|
|
4
|
-
import { Schema } from "../schema";
|
|
4
|
+
import { FieldMap, Schema } from "../schema";
|
|
5
|
+
import { SchemaConfig } from "../schema/base_schema";
|
|
5
6
|
export declare class User implements Ent {
|
|
6
7
|
viewer: Viewer;
|
|
7
8
|
data: Data;
|
|
@@ -60,6 +61,9 @@ export declare class Address implements Ent {
|
|
|
60
61
|
export interface BuilderSchema<T extends Ent> extends Schema {
|
|
61
62
|
ent: EntConstructor<T>;
|
|
62
63
|
}
|
|
64
|
+
export declare function getBuilderSchema<T extends Ent>(cfg: SchemaConfig, ent: EntConstructor<T>): BuilderSchema<T>;
|
|
65
|
+
export declare function getBuilderSchemaFromFields<T extends Ent>(fields: FieldMap, ent: EntConstructor<T>): BuilderSchema<T>;
|
|
66
|
+
export declare function getBuilderSchemaTZFromFields<T extends Ent>(fields: FieldMap, ent: EntConstructor<T>): BuilderSchema<T>;
|
|
63
67
|
export declare function getSchemaName(value: BuilderSchema<Ent>): string;
|
|
64
68
|
export declare function getTableName(value: BuilderSchema<Ent>): string;
|
|
65
69
|
export declare class SimpleBuilder<T extends Ent> implements Builder<T> {
|
package/testutils/builder.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SimpleAction = exports.SimpleBuilder = exports.getTableName = exports.getSchemaName = exports.Address = exports.Message = exports.Group = exports.Contact = exports.Event = exports.User = void 0;
|
|
6
|
+
exports.SimpleAction = exports.SimpleBuilder = exports.getTableName = exports.getSchemaName = exports.getBuilderSchemaTZFromFields = exports.getBuilderSchemaFromFields = exports.getBuilderSchema = exports.Address = exports.Message = exports.Group = exports.Contact = exports.Event = exports.User = void 0;
|
|
7
7
|
const privacy_1 = require("../core/privacy");
|
|
8
8
|
const orchestrator_1 = require("../action/orchestrator");
|
|
9
9
|
const action_1 = require("../action");
|
|
@@ -14,6 +14,7 @@ const snake_case_1 = require("snake-case");
|
|
|
14
14
|
const loaders_1 = require("../core/loaders");
|
|
15
15
|
const convert_1 = require("../core/convert");
|
|
16
16
|
const camel_case_1 = require("camel-case");
|
|
17
|
+
const base_schema_1 = require("../schema/base_schema");
|
|
17
18
|
class User {
|
|
18
19
|
constructor(viewer, data) {
|
|
19
20
|
this.viewer = viewer;
|
|
@@ -85,6 +86,27 @@ class Address {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
exports.Address = Address;
|
|
89
|
+
function getBuilderSchema(cfg, ent) {
|
|
90
|
+
return {
|
|
91
|
+
...new base_schema_1.EntSchema(cfg),
|
|
92
|
+
ent,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
exports.getBuilderSchema = getBuilderSchema;
|
|
96
|
+
function getBuilderSchemaFromFields(fields, ent) {
|
|
97
|
+
return {
|
|
98
|
+
...new base_schema_1.EntSchema({ fields }),
|
|
99
|
+
ent,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
exports.getBuilderSchemaFromFields = getBuilderSchemaFromFields;
|
|
103
|
+
function getBuilderSchemaTZFromFields(fields, ent) {
|
|
104
|
+
return {
|
|
105
|
+
...new base_schema_1.EntSchemaWithTZ({ fields }),
|
|
106
|
+
ent,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
exports.getBuilderSchemaTZFromFields = getBuilderSchemaTZFromFields;
|
|
88
110
|
function getSchemaName(value) {
|
|
89
111
|
return value.ent.name;
|
|
90
112
|
}
|
|
@@ -142,12 +164,34 @@ class SimpleBuilder {
|
|
|
142
164
|
ent: schema.ent,
|
|
143
165
|
tableName: tableName,
|
|
144
166
|
fields: [],
|
|
167
|
+
fieldPrivacy: (0, schema_1.getFieldsWithPrivacy)(schema),
|
|
145
168
|
},
|
|
146
169
|
builder: this,
|
|
147
170
|
action: action,
|
|
148
171
|
schema: this.schema,
|
|
149
172
|
editedFields: () => {
|
|
150
|
-
return
|
|
173
|
+
// to simulate what we do in generated builders where we return a new Map
|
|
174
|
+
const m = new Map();
|
|
175
|
+
for (const [k, v] of this.fields) {
|
|
176
|
+
m.set(k, v);
|
|
177
|
+
}
|
|
178
|
+
return m;
|
|
179
|
+
},
|
|
180
|
+
updateInput: (input) => {
|
|
181
|
+
const knownFields = (0, schema_1.getFields)(this.schema);
|
|
182
|
+
for (const k in input) {
|
|
183
|
+
if (knownFields.has(k)) {
|
|
184
|
+
this.fields.set(k, input[k]);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// related to #510. we do camelCase to pass fields in here but fields may be snakeCase and we want that to pass in tests
|
|
188
|
+
// we do camelCase in
|
|
189
|
+
const sc = (0, snake_case_1.snakeCase)(k);
|
|
190
|
+
if (knownFields.has(sc)) {
|
|
191
|
+
this.fields.set(sc, input[k]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
151
195
|
},
|
|
152
196
|
});
|
|
153
197
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Context, Viewer } from "../../core/base";
|
|
2
2
|
import { ContextCache } from "../../core/context";
|
|
3
|
-
import { LoggedOutViewer } from "../../core/viewer";
|
|
4
3
|
export declare class TestContext implements Context {
|
|
4
|
+
constructor(viewer?: Viewer);
|
|
5
5
|
cache: ContextCache;
|
|
6
|
-
viewer:
|
|
6
|
+
viewer: Viewer;
|
|
7
7
|
getViewer(): Viewer;
|
|
8
8
|
}
|
|
@@ -4,9 +4,15 @@ exports.TestContext = void 0;
|
|
|
4
4
|
const context_1 = require("../../core/context");
|
|
5
5
|
const viewer_1 = require("../../core/viewer");
|
|
6
6
|
class TestContext {
|
|
7
|
-
constructor() {
|
|
7
|
+
constructor(viewer) {
|
|
8
8
|
this.cache = new context_1.ContextCache();
|
|
9
9
|
this.viewer = new viewer_1.LoggedOutViewer(this);
|
|
10
|
+
if (viewer) {
|
|
11
|
+
this.viewer = viewer;
|
|
12
|
+
if (viewer.setContext !== undefined) {
|
|
13
|
+
viewer.setContext(this);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
getViewer() {
|
|
12
18
|
return this.viewer;
|
|
@@ -71,10 +71,11 @@ export declare class TempDB {
|
|
|
71
71
|
constructor(tables: CoreConcept[]);
|
|
72
72
|
getDialect(): Dialect;
|
|
73
73
|
getTables(): Map<string, CoreConcept>;
|
|
74
|
-
beforeAll(): Promise<void>;
|
|
74
|
+
beforeAll(setupConnString?: boolean): Promise<void>;
|
|
75
75
|
getSqliteClient(): SqliteDatabase;
|
|
76
76
|
getPostgresClient(): PGClient;
|
|
77
77
|
afterAll(): Promise<void>;
|
|
78
|
+
getDB(): string;
|
|
78
79
|
dropAll(): Promise<void>;
|
|
79
80
|
drop(...tables: string[]): Promise<void>;
|
|
80
81
|
create(...tables: CoreConcept[]): Promise<void>;
|