@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.
Files changed (62) hide show
  1. package/action/action.d.ts +2 -0
  2. package/action/executor.d.ts +1 -1
  3. package/action/orchestrator.d.ts +10 -2
  4. package/action/orchestrator.js +128 -34
  5. package/core/base.d.ts +5 -1
  6. package/core/base.js +16 -0
  7. package/core/clause.d.ts +24 -3
  8. package/core/clause.js +246 -5
  9. package/core/config.d.ts +18 -0
  10. package/core/config.js +17 -0
  11. package/core/db.d.ts +3 -3
  12. package/core/db.js +2 -0
  13. package/core/ent.d.ts +2 -4
  14. package/core/ent.js +70 -23
  15. package/core/loaders/assoc_edge_loader.d.ts +1 -1
  16. package/core/loaders/assoc_edge_loader.js +5 -4
  17. package/core/loaders/index_loader.js +1 -0
  18. package/core/loaders/object_loader.d.ts +7 -2
  19. package/core/loaders/object_loader.js +59 -4
  20. package/core/privacy.js +3 -0
  21. package/core/viewer.d.ts +1 -0
  22. package/core/viewer.js +4 -0
  23. package/graphql/builtins/connection.js +3 -3
  24. package/graphql/builtins/edge.js +2 -2
  25. package/graphql/builtins/node.js +1 -1
  26. package/graphql/graphql.d.ts +3 -2
  27. package/graphql/graphql.js +24 -23
  28. package/graphql/node_resolver.d.ts +0 -1
  29. package/graphql/query/connection_type.js +6 -6
  30. package/graphql/query/page_info.js +4 -4
  31. package/graphql/query/shared_assoc_test.js +2 -2
  32. package/graphql/scalars/time.d.ts +1 -1
  33. package/index.d.ts +16 -1
  34. package/index.js +18 -5
  35. package/package.json +3 -3
  36. package/parse_schema/parse.d.ts +16 -5
  37. package/parse_schema/parse.js +51 -6
  38. package/schema/base_schema.d.ts +36 -1
  39. package/schema/base_schema.js +48 -2
  40. package/schema/field.js +1 -1
  41. package/schema/index.d.ts +2 -2
  42. package/schema/index.js +8 -1
  43. package/schema/schema.d.ts +50 -1
  44. package/schema/schema.js +113 -5
  45. package/scripts/custom_graphql.js +122 -15
  46. package/scripts/read_schema.js +15 -1
  47. package/scripts/transform_schema.js +212 -55
  48. package/testutils/builder.d.ts +5 -1
  49. package/testutils/builder.js +46 -2
  50. package/testutils/context/test_context.d.ts +2 -2
  51. package/testutils/context/test_context.js +7 -1
  52. package/testutils/db/test_db.d.ts +2 -1
  53. package/testutils/db/test_db.js +13 -4
  54. package/testutils/ent-graphql-tests/index.d.ts +2 -0
  55. package/testutils/ent-graphql-tests/index.js +26 -17
  56. package/testutils/fake_data/fake_contact.d.ts +2 -6
  57. package/testutils/fake_data/fake_contact.js +9 -16
  58. package/testutils/fake_data/fake_event.d.ts +2 -6
  59. package/testutils/fake_data/fake_event.js +17 -24
  60. package/testutils/fake_data/fake_user.d.ts +2 -6
  61. package/testutils/fake_data/fake_user.js +10 -17
  62. 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
- async function captureCustom(filePath, filesCsv) {
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
- const r = require(gqlPath);
157
- if (!r.GQLCapture) {
158
- throw new Error("could not find GQLCapture in module");
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
- GQLCapture.resolve(nodes);
176
- let args = fromMap(GQLCapture.getCustomArgs());
177
- let inputs = fromMap(GQLCapture.getCustomInputObjects());
178
- let fields = GQLCapture.getProcessedCustomFields();
179
- let queries = GQLCapture.getProcessedCustomQueries();
180
- let mutations = GQLCapture.getProcessedCustomMutations();
181
- let objects = fromMap(GQLCapture.getCustomObjects());
182
- let customTypes = fromMap(GQLCapture.getCustomTypes());
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) => {
@@ -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
- potentialSchemas[(0, pascal_case_1.pascalCase)(match[1])] = require(p).default;
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
- let updated = false;
135
- // beginning of class...
136
- // including comment
137
- let klassContents = fileContents.substring(node.getFullStart(), node.members[0].getFullStart());
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
- if (!isFieldElement(member, sourceFile)) {
140
- klassContents += member.getFullText(sourceFile);
141
- continue;
153
+ const fInfo = getClassElementInfo(fileContents, member, sourceFile);
154
+ if (!fInfo) {
155
+ return false;
142
156
  }
143
- // intentionally doesn't parse decorators since we don't need it
144
- let fieldMap = "";
145
- // fieldMapComment...
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
- updated = true;
151
- // need to change to fields: FieldMap = {code: StringType()};
152
- const property = member;
153
- const initializer = property.initializer;
154
- fieldMap += "fields: FieldMap = {";
155
- for (const element of initializer.elements) {
156
- const parsed = parseFieldElement(element, sourceFile, fileContents);
157
- if (parsed === null) {
158
- return false;
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
- const { callEx, name, nameComment, properties } = parsed;
161
- let property = "";
162
- const fieldComment = getPreText(fileContents, element, sourceFile).trim();
163
- if (fieldComment) {
164
- property += "\n" + fieldComment + "\n";
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
- if (nameComment) {
167
- property += nameComment + "\n";
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
- // e.g. UUIDType, StringType etc
170
- let call = callEx.expression.getText(sourceFile);
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
- klassContents += "\n}";
182
- // console.debug(klassContents);
183
- if (!updated) {
184
- return updated;
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
- f.trackNode({ rawString: klassContents });
187
- return updated;
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
- const imp = imports[i].trim();
272
- if (imp === "Field") {
273
- imports[i] = "FieldMap";
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
- imports.join(", ") +
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));
@@ -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> {
@@ -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 this.fields;
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: LoggedOutViewer;
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>;