@snowtop/ent 0.1.0-alpha7 → 0.1.0-alpha8
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/graphql.d.ts +3 -2
- package/graphql/graphql.js +22 -21
- package/graphql/node_resolver.d.ts +0 -1
- package/index.d.ts +16 -1
- package/index.js +18 -5
- package/package.json +2 -2
- package/parse_schema/parse.d.ts +11 -4
- package/parse_schema/parse.js +50 -6
- package/schema/base_schema.d.ts +36 -1
- package/schema/base_schema.js +48 -2
- 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/transform_schema.js +204 -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 +7 -5
- 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
|
@@ -62,16 +62,18 @@ async function main() {
|
|
|
62
62
|
getTarget(options.target)
|
|
63
63
|
: typescript_1.default.ScriptTarget.ESNext;
|
|
64
64
|
// filter to only event.ts e.g. for comments and whitespace...
|
|
65
|
-
//
|
|
65
|
+
// files = files.filter((f) => f.endsWith("user.ts"));
|
|
66
66
|
files.forEach((file) => {
|
|
67
67
|
// assume valid file since we do glob above
|
|
68
|
-
const idx = file.lastIndexOf(".ts");
|
|
69
|
-
const writeFile = file.substring(0, idx) + "2" + ".ts";
|
|
68
|
+
// const idx = file.lastIndexOf(".ts");
|
|
69
|
+
// const writeFile = file.substring(0, idx) + "2" + ".ts";
|
|
70
|
+
const writeFile = file;
|
|
70
71
|
let contents = fs.readFileSync(file).toString();
|
|
71
72
|
// go through the file and print everything back if not starting immediately after other position
|
|
72
73
|
const sourceFile = typescript_1.default.createSourceFile(file, contents, target, false, typescript_1.default.ScriptKind.TS);
|
|
73
74
|
const nodes = [];
|
|
74
75
|
let updateImport = false;
|
|
76
|
+
let removeImports = [];
|
|
75
77
|
const f = {
|
|
76
78
|
trackNode: function (tni) {
|
|
77
79
|
nodes.push({
|
|
@@ -79,6 +81,9 @@ async function main() {
|
|
|
79
81
|
importNode: tni.node && typescript_1.default.isImportDeclaration(tni.node),
|
|
80
82
|
rawString: tni.rawString,
|
|
81
83
|
});
|
|
84
|
+
if (tni.removeImports) {
|
|
85
|
+
removeImports.push(...tni.removeImports);
|
|
86
|
+
}
|
|
82
87
|
},
|
|
83
88
|
flagUpdateImport() {
|
|
84
89
|
updateImport = true;
|
|
@@ -91,7 +96,7 @@ async function main() {
|
|
|
91
96
|
for (const node of nodes) {
|
|
92
97
|
if (updateImport && node.importNode) {
|
|
93
98
|
const importNode = node.node;
|
|
94
|
-
const transformedImport = transformImport(importNode, sourceFile);
|
|
99
|
+
const transformedImport = transformImport(importNode, sourceFile, removeImports);
|
|
95
100
|
if (transformedImport) {
|
|
96
101
|
newContents += transformedImport;
|
|
97
102
|
continue;
|
|
@@ -129,62 +134,203 @@ function traverse(fileContents, sourceFile, f) {
|
|
|
129
134
|
});
|
|
130
135
|
return traversed;
|
|
131
136
|
}
|
|
132
|
-
// TODO need to replace class field member, print that and see what happens
|
|
133
137
|
function traverseClass(fileContents, sourceFile, node, f) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
const ci = getClassInfo(fileContents, sourceFile, node);
|
|
139
|
+
if (!ci) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
let klassContents = `${ci.comment}const ${ci.name} = new ${ci.class}({\n`;
|
|
143
|
+
let removeImports = [];
|
|
144
|
+
if (ci.implementsSchema) {
|
|
145
|
+
removeImports.push("Schema");
|
|
146
|
+
}
|
|
138
147
|
for (let member of node.members) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
const fInfo = getClassElementInfo(fileContents, member, sourceFile);
|
|
149
|
+
if (!fInfo) {
|
|
150
|
+
return false;
|
|
142
151
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const comment = getPreText(fileContents, member, sourceFile);
|
|
147
|
-
if (comment) {
|
|
148
|
-
fieldMap += comment;
|
|
152
|
+
klassContents += `${fInfo.comment}${fInfo.key}:${fInfo.value},\n`;
|
|
153
|
+
if (fInfo.type) {
|
|
154
|
+
removeImports.push(fInfo.type);
|
|
149
155
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
}
|
|
157
|
+
klassContents += "\n})";
|
|
158
|
+
if (ci.export && ci.default) {
|
|
159
|
+
klassContents += `\n export default ${ci.name};`;
|
|
160
|
+
}
|
|
161
|
+
else if (ci.export) {
|
|
162
|
+
klassContents = "export " + klassContents;
|
|
163
|
+
}
|
|
164
|
+
// console.debug(klassContents);
|
|
165
|
+
f.trackNode({ rawString: klassContents, removeImports: removeImports });
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
function transformSchema(str) {
|
|
169
|
+
// only do known class names
|
|
170
|
+
if (str === "BaseEntSchema" || str === "BaseEntSchemaWithTZ") {
|
|
171
|
+
return str.substring(4);
|
|
172
|
+
}
|
|
173
|
+
return str;
|
|
174
|
+
}
|
|
175
|
+
function getClassInfo(fileContents, sourceFile, node) {
|
|
176
|
+
const className = node.name?.text;
|
|
177
|
+
let classExtends;
|
|
178
|
+
let implementsSchema = false;
|
|
179
|
+
if (node.heritageClauses) {
|
|
180
|
+
for (const hc of node.heritageClauses) {
|
|
181
|
+
if (hc.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
|
|
182
|
+
for (const type of hc.types) {
|
|
183
|
+
if (type.expression.getText(sourceFile) === "Schema") {
|
|
184
|
+
implementsSchema = true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
continue;
|
|
159
188
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
189
|
+
// ts.SyntaxKind.ExtendsKeyword
|
|
190
|
+
// can only extend one class
|
|
191
|
+
for (const type of hc.types) {
|
|
192
|
+
const text = type.expression.getText(sourceFile);
|
|
193
|
+
const transformed = transformSchema(text);
|
|
194
|
+
if (transformed === text) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
classExtends = transformed;
|
|
165
198
|
}
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!className || !node.heritageClauses || !classExtends) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
let ci = {
|
|
205
|
+
name: className,
|
|
206
|
+
class: classExtends,
|
|
207
|
+
comment: getPreText(fileContents, node, sourceFile),
|
|
208
|
+
implementsSchema,
|
|
209
|
+
};
|
|
210
|
+
if (node.modifiers) {
|
|
211
|
+
for (const mod of node.modifiers) {
|
|
212
|
+
const text = mod.getText(sourceFile);
|
|
213
|
+
if (text === "export") {
|
|
214
|
+
ci.export = true;
|
|
168
215
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let fnCall = "";
|
|
172
|
-
if (properties.length) {
|
|
173
|
-
fnCall = `{${properties.join(",")}}`;
|
|
216
|
+
else if (text === "default") {
|
|
217
|
+
ci.default = true;
|
|
174
218
|
}
|
|
175
|
-
property += `${name}:${call}(${fnCall}),`;
|
|
176
|
-
fieldMap += property;
|
|
177
219
|
}
|
|
178
|
-
fieldMap += "}";
|
|
179
|
-
klassContents += fieldMap;
|
|
180
220
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
221
|
+
return ci;
|
|
222
|
+
}
|
|
223
|
+
// intentionally doesn't parse decorators since we don't need it
|
|
224
|
+
function getClassElementInfo(fileContents, member, sourceFile) {
|
|
225
|
+
if (isFieldElement(member, sourceFile)) {
|
|
226
|
+
return getFieldElementInfo(fileContents, member, sourceFile);
|
|
185
227
|
}
|
|
186
|
-
|
|
187
|
-
|
|
228
|
+
if (member.kind === typescript_1.default.SyntaxKind.Constructor) {
|
|
229
|
+
return getConstructorElementInfo(fileContents, member, sourceFile);
|
|
230
|
+
}
|
|
231
|
+
if (member.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
// other properties
|
|
235
|
+
const property = member;
|
|
236
|
+
if (!property.initializer) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const token = property.name;
|
|
240
|
+
return {
|
|
241
|
+
key: token.escapedText.toString(),
|
|
242
|
+
value: property.initializer?.getFullText(sourceFile),
|
|
243
|
+
comment: getPreText(fileContents, member, sourceFile),
|
|
244
|
+
type: getType(property, sourceFile),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function getType(property, sourceFile) {
|
|
248
|
+
let propertytype = property.type?.getText(sourceFile) || "";
|
|
249
|
+
let ends = ["| null", "[]"];
|
|
250
|
+
for (const end of ends) {
|
|
251
|
+
if (propertytype.endsWith(end)) {
|
|
252
|
+
propertytype = propertytype.slice(0, -1 * end.length);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return propertytype;
|
|
256
|
+
}
|
|
257
|
+
function getFieldElementInfo(fileContents, member, sourceFile) {
|
|
258
|
+
let fieldMap = "";
|
|
259
|
+
// need to change to fields: {code: StringType()};
|
|
260
|
+
const property = member;
|
|
261
|
+
const initializer = property.initializer;
|
|
262
|
+
fieldMap += "{";
|
|
263
|
+
for (const element of initializer.elements) {
|
|
264
|
+
const parsed = parseFieldElement(element, sourceFile, fileContents);
|
|
265
|
+
if (parsed === null) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const { callEx, name, nameComment, properties } = parsed;
|
|
269
|
+
let property = "";
|
|
270
|
+
const fieldComment = getPreText(fileContents, element, sourceFile).trim();
|
|
271
|
+
if (fieldComment) {
|
|
272
|
+
property += "\n" + fieldComment + "\n";
|
|
273
|
+
}
|
|
274
|
+
if (nameComment) {
|
|
275
|
+
property += nameComment + "\n";
|
|
276
|
+
}
|
|
277
|
+
// e.g. UUIDType, StringType etc
|
|
278
|
+
let call = callEx.expression.getText(sourceFile);
|
|
279
|
+
let fnCall = "";
|
|
280
|
+
if (properties.length) {
|
|
281
|
+
fnCall = `{${properties.join(",")}}`;
|
|
282
|
+
}
|
|
283
|
+
property += `${name}:${call}(${fnCall}),`;
|
|
284
|
+
fieldMap += property;
|
|
285
|
+
}
|
|
286
|
+
fieldMap += "}";
|
|
287
|
+
return {
|
|
288
|
+
key: "fields",
|
|
289
|
+
value: fieldMap,
|
|
290
|
+
comment: getPreText(fileContents, member, sourceFile),
|
|
291
|
+
type: getType(property, sourceFile),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function getConstructorElementInfo(fileContents, member, sourceFile) {
|
|
295
|
+
const c = member;
|
|
296
|
+
//remove {}
|
|
297
|
+
let fullText = c.body?.getFullText(sourceFile) || "";
|
|
298
|
+
fullText = fullText.trim().slice(1, -1).trim();
|
|
299
|
+
// convert something like
|
|
300
|
+
/*
|
|
301
|
+
constructor() {
|
|
302
|
+
super();
|
|
303
|
+
this.addPatterns(
|
|
304
|
+
new Feedback(),
|
|
305
|
+
new DayOfWeek(),
|
|
306
|
+
new Feedback(),
|
|
307
|
+
new DayOfWeek(),
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
*/
|
|
311
|
+
// into this.addPatterns(new Feedback(),new DayOfWeek(),new Feedback(),new DayOfWeek(),)
|
|
312
|
+
const lines = fullText
|
|
313
|
+
.split("\n")
|
|
314
|
+
.map((line) => line.trim())
|
|
315
|
+
.join("")
|
|
316
|
+
.split(";")
|
|
317
|
+
.filter((f) => f != "super()" && f != "");
|
|
318
|
+
// at this point there should be only line for what we handle
|
|
319
|
+
if (lines.length != 1) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const line = lines[0];
|
|
323
|
+
const addPatterns = "this.addPatterns(";
|
|
324
|
+
if (!line.startsWith(addPatterns)) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
key: "patterns",
|
|
329
|
+
// remove this.addPatterns at the front, remove trailing ) at the end
|
|
330
|
+
// if there's a trailing comma, it'll be handled by prettier
|
|
331
|
+
value: `[${line.slice(addPatterns.length, -1)}]`,
|
|
332
|
+
comment: "",
|
|
333
|
+
};
|
|
188
334
|
}
|
|
189
335
|
function isFieldElement(member, sourceFile) {
|
|
190
336
|
if (member.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
|
|
@@ -249,7 +395,7 @@ function parseFieldElement(element, sourceFile, fileContents) {
|
|
|
249
395
|
nameComment: propertyComment,
|
|
250
396
|
};
|
|
251
397
|
}
|
|
252
|
-
function transformImport(importNode, sourceFile) {
|
|
398
|
+
function transformImport(importNode, sourceFile, removeImports) {
|
|
253
399
|
// remove quotes too
|
|
254
400
|
const text = importNode.moduleSpecifier.getText(sourceFile).slice(1, -1);
|
|
255
401
|
if (text !== "@snowtop/ent" &&
|
|
@@ -267,16 +413,19 @@ function transformImport(importNode, sourceFile) {
|
|
|
267
413
|
.substring(start + 1, end)
|
|
268
414
|
// .trim()
|
|
269
415
|
.split(",");
|
|
416
|
+
let removeImportsMap = {};
|
|
417
|
+
removeImports.forEach((imp) => (removeImportsMap[imp] = true));
|
|
418
|
+
let newImports = [];
|
|
270
419
|
for (let i = 0; i < imports.length; i++) {
|
|
271
|
-
|
|
272
|
-
if (imp
|
|
273
|
-
|
|
420
|
+
let imp = transformSchema(imports[i].trim());
|
|
421
|
+
if (removeImportsMap[imp]) {
|
|
422
|
+
continue;
|
|
274
423
|
}
|
|
424
|
+
newImports.push(imp);
|
|
275
425
|
}
|
|
276
|
-
// TODO better to update node instead of doing this but this works for now
|
|
277
426
|
return ("import " +
|
|
278
427
|
importText.substring(0, start + 1) +
|
|
279
|
-
|
|
428
|
+
newImports.join(", ") +
|
|
280
429
|
importText.substring(end) +
|
|
281
430
|
' from "' +
|
|
282
431
|
text +
|
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>;
|
package/testutils/db/test_db.js
CHANGED
|
@@ -336,7 +336,7 @@ class TempDB {
|
|
|
336
336
|
getTables() {
|
|
337
337
|
return this.tables;
|
|
338
338
|
}
|
|
339
|
-
async beforeAll() {
|
|
339
|
+
async beforeAll(setupConnString = true) {
|
|
340
340
|
if (this.dialect === db_1.Dialect.Postgres) {
|
|
341
341
|
const user = process.env.POSTGRES_USER || "";
|
|
342
342
|
const password = process.env.POSTGRES_PASSWORD || "";
|
|
@@ -348,11 +348,17 @@ class TempDB {
|
|
|
348
348
|
await this.client.connect();
|
|
349
349
|
this.db = randomDB();
|
|
350
350
|
await this.client.query(`CREATE DATABASE ${this.db}`);
|
|
351
|
-
if (
|
|
352
|
-
|
|
351
|
+
if (setupConnString) {
|
|
352
|
+
if (user && password) {
|
|
353
|
+
process.env.DB_CONNECTION_STRING = `postgres://${user}:${password}@localhost:5432/${this.db}`;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
process.env.DB_CONNECTION_STRING = `postgres://localhost/${this.db}?`;
|
|
357
|
+
}
|
|
353
358
|
}
|
|
354
359
|
else {
|
|
355
|
-
|
|
360
|
+
// will probably be setup via loadConfig
|
|
361
|
+
delete process.env.DB_CONNECTION_STRING;
|
|
356
362
|
}
|
|
357
363
|
this.dbClient = new pg_1.Client({
|
|
358
364
|
host: "localhost",
|
|
@@ -397,6 +403,9 @@ class TempDB {
|
|
|
397
403
|
await this.client.query(`DROP DATABASE ${this.db}`);
|
|
398
404
|
await this.client.end();
|
|
399
405
|
}
|
|
406
|
+
getDB() {
|
|
407
|
+
return this.db;
|
|
408
|
+
}
|
|
400
409
|
async dropAll() {
|
|
401
410
|
for (const [t, _] of this.tables) {
|
|
402
411
|
await this.drop(t);
|
|
@@ -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,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ID, Ent, Viewer, Data, LoadEntOptions, PrivacyPolicy } from "../../core/base";
|
|
2
|
-
import {
|
|
3
|
-
import { BaseEntSchema, FieldMap } from "../../schema";
|
|
2
|
+
import { SimpleBuilder } from "../builder";
|
|
4
3
|
import { NodeType } from "./const";
|
|
5
4
|
import { ObjectLoaderFactory } from "../../core/loaders";
|
|
6
5
|
export declare class FakeContact implements Ent {
|
|
@@ -22,10 +21,7 @@ export declare class FakeContact implements Ent {
|
|
|
22
21
|
static load(v: Viewer, id: ID): Promise<FakeContact | null>;
|
|
23
22
|
static loadX(v: Viewer, id: ID): Promise<FakeContact>;
|
|
24
23
|
}
|
|
25
|
-
export declare
|
|
26
|
-
ent: typeof FakeContact;
|
|
27
|
-
fields: FieldMap;
|
|
28
|
-
}
|
|
24
|
+
export declare const FakeContactSchema: import("../builder").BuilderSchema<FakeContact>;
|
|
29
25
|
export interface ContactCreateInput {
|
|
30
26
|
firstName: string;
|
|
31
27
|
lastName: string;
|
|
@@ -59,21 +59,14 @@ class FakeContact {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
exports.FakeContact = FakeContact;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
userID: (0, schema_1.UUIDType)({
|
|
71
|
-
foreignKey: { schema: "User", column: "ID" },
|
|
72
|
-
}),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
exports.FakeContactSchema = FakeContactSchema;
|
|
62
|
+
exports.FakeContactSchema = (0, builder_1.getBuilderSchemaFromFields)({
|
|
63
|
+
firstName: (0, schema_1.StringType)(),
|
|
64
|
+
lastName: (0, schema_1.StringType)(),
|
|
65
|
+
emailAddress: (0, schema_1.StringType)(),
|
|
66
|
+
userID: (0, schema_1.UUIDType)({
|
|
67
|
+
foreignKey: { schema: "User", column: "ID" },
|
|
68
|
+
}),
|
|
69
|
+
}, FakeContact);
|
|
77
70
|
function getContactBuilder(viewer, input) {
|
|
78
71
|
const m = new Map();
|
|
79
72
|
for (const key in input) {
|
|
@@ -82,7 +75,7 @@ function getContactBuilder(viewer, input) {
|
|
|
82
75
|
//To lock in the value of Date now incase of advanceTo/advanceBy
|
|
83
76
|
m.set("createdAt", new Date());
|
|
84
77
|
m.set("updatedAt", new Date());
|
|
85
|
-
return new builder_1.SimpleBuilder(viewer,
|
|
78
|
+
return new builder_1.SimpleBuilder(viewer, exports.FakeContactSchema, m);
|
|
86
79
|
}
|
|
87
80
|
exports.getContactBuilder = getContactBuilder;
|
|
88
81
|
async function createContact(viewer, input) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ID, Ent, Viewer, Data, LoadEntOptions, PrivacyPolicy } from "../../core/base";
|
|
2
|
-
import {
|
|
3
|
-
import { BaseEntSchema, FieldMap } from "../../schema";
|
|
2
|
+
import { SimpleBuilder } from "../builder";
|
|
4
3
|
import { NodeType } from "./const";
|
|
5
4
|
export declare class FakeEvent implements Ent {
|
|
6
5
|
viewer: Viewer;
|
|
@@ -23,10 +22,7 @@ export declare class FakeEvent implements Ent {
|
|
|
23
22
|
static load(v: Viewer, id: ID): Promise<FakeEvent | null>;
|
|
24
23
|
static loadX(v: Viewer, id: ID): Promise<FakeEvent>;
|
|
25
24
|
}
|
|
26
|
-
export declare
|
|
27
|
-
ent: typeof FakeEvent;
|
|
28
|
-
fields: FieldMap;
|
|
29
|
-
}
|
|
25
|
+
export declare const FakeEventSchema: import("../builder").BuilderSchema<FakeEvent>;
|
|
30
26
|
export interface EventCreateInput {
|
|
31
27
|
startTime: Date;
|
|
32
28
|
endTime?: Date | null;
|