@snowtop/ent 0.0.27 → 0.0.29
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 +1 -2
- package/action/executor.d.ts +7 -12
- package/action/executor.js +35 -29
- package/action/index.d.ts +1 -1
- package/action/orchestrator.d.ts +5 -4
- package/action/orchestrator.js +14 -8
- package/core/clause.js +1 -1
- package/core/ent.d.ts +16 -10
- package/core/ent.js +8 -1
- package/graphql/builtins/connection.js +1 -0
- package/graphql/builtins/edge.js +1 -0
- package/graphql/builtins/node.js +1 -0
- package/graphql/graphql.d.ts +2 -0
- package/graphql/graphql.js +83 -61
- package/graphql/query/page_info.js +1 -0
- package/imports/index.d.ts +1 -1
- package/imports/index.js +3 -5
- package/package.json +2 -2
- package/scripts/custom_compiler.js +0 -0
- package/scripts/custom_graphql.js +43 -8
- package/testutils/builder.d.ts +1 -1
- package/testutils/builder.js +5 -1
- package/testutils/db_mock.js +2 -2
- package/testutils/ent-graphql-tests/index.js +5 -5
- package/testutils/fake_data/test_helpers.js +1 -2
- package/testutils/parse_sql.js +1 -1
package/action/action.d.ts
CHANGED
|
@@ -27,9 +27,8 @@ export interface Changeset<T extends Ent> {
|
|
|
27
27
|
executor(): Executor;
|
|
28
28
|
viewer: Viewer;
|
|
29
29
|
placeholderID: ID;
|
|
30
|
-
ent: EntConstructor<T>;
|
|
31
30
|
changesets?: Changeset<Ent>[];
|
|
32
|
-
dependencies?: Map<ID, Builder<
|
|
31
|
+
dependencies?: Map<ID, Builder<Ent>>;
|
|
33
32
|
}
|
|
34
33
|
export declare type TriggerReturn = void | Promise<Changeset<Ent> | void | (Changeset<Ent> | void)[]> | Promise<Changeset<Ent>>[];
|
|
35
34
|
export interface Trigger<T extends Ent> {
|
package/action/executor.d.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import { ID, Data, Ent, Viewer,
|
|
1
|
+
import { ID, Data, Ent, Viewer, Context } from "../core/base";
|
|
2
2
|
import { DataOperation } from "../core/ent";
|
|
3
|
-
import { Changeset, Executor } from "../action";
|
|
3
|
+
import { Changeset, Executor } from "../action/action";
|
|
4
4
|
import { Builder } from "../action";
|
|
5
5
|
import { OrchestratorOptions } from "./orchestrator";
|
|
6
6
|
import { Queryer } from "../core/db";
|
|
7
7
|
export declare class ListBasedExecutor<T extends Ent> implements Executor {
|
|
8
8
|
private viewer;
|
|
9
9
|
placeholderID: ID;
|
|
10
|
-
private ent;
|
|
11
10
|
private operations;
|
|
12
11
|
private options?;
|
|
13
12
|
private idx;
|
|
14
|
-
constructor(viewer: Viewer, placeholderID: ID,
|
|
13
|
+
constructor(viewer: Viewer, placeholderID: ID, operations: DataOperation<T>[], options?: OrchestratorOptions<T, Data> | undefined);
|
|
15
14
|
private lastOp;
|
|
16
15
|
private createdEnt;
|
|
17
16
|
resolveValue(val: ID): Ent | null;
|
|
18
17
|
[Symbol.iterator](): this;
|
|
19
|
-
next(): IteratorResult<DataOperation
|
|
18
|
+
next(): IteratorResult<DataOperation<T>>;
|
|
20
19
|
executeObservers(): Promise<void>;
|
|
21
20
|
execute(): Promise<void>;
|
|
22
21
|
preFetch?(queryer: Queryer, context: Context): Promise<void>;
|
|
@@ -25,23 +24,19 @@ export declare class ListBasedExecutor<T extends Ent> implements Executor {
|
|
|
25
24
|
export declare class ComplexExecutor<T extends Ent> implements Executor {
|
|
26
25
|
private viewer;
|
|
27
26
|
placeholderID: ID;
|
|
28
|
-
private ent;
|
|
29
|
-
private options?;
|
|
30
27
|
private idx;
|
|
31
28
|
private mapper;
|
|
32
29
|
private lastOp;
|
|
33
30
|
private allOperations;
|
|
34
|
-
private changesetMap;
|
|
35
|
-
private nodeOpMap;
|
|
36
31
|
private executors;
|
|
37
|
-
constructor(viewer: Viewer, placeholderID: ID,
|
|
32
|
+
constructor(viewer: Viewer, placeholderID: ID, operations: DataOperation[], dependencies: Map<ID, Builder<T>>, changesets: Changeset<T>[], options?: OrchestratorOptions<T, Data>);
|
|
38
33
|
[Symbol.iterator](): this;
|
|
39
34
|
private handleCreatedEnt;
|
|
40
|
-
next(): IteratorResult<DataOperation
|
|
35
|
+
next(): IteratorResult<DataOperation<Ent>>;
|
|
41
36
|
resolveValue(val: ID): Ent | null;
|
|
42
37
|
executeObservers(): Promise<void>;
|
|
43
38
|
execute(): Promise<void>;
|
|
44
39
|
preFetch?(queryer: Queryer, context: Context): Promise<void>;
|
|
45
40
|
postFetch?(queryer: Queryer, context: Context): Promise<void>;
|
|
46
41
|
}
|
|
47
|
-
export declare function executeOperations(executor: Executor, context?: Context, trackOps?: true): Promise<DataOperation[]>;
|
|
42
|
+
export declare function executeOperations(executor: Executor, context?: Context, trackOps?: true): Promise<DataOperation<Ent>[]>;
|
package/action/executor.js
CHANGED
|
@@ -9,10 +9,9 @@ const db_1 = __importDefault(require("../core/db"));
|
|
|
9
9
|
const logger_1 = require("../core/logger");
|
|
10
10
|
// private to ent
|
|
11
11
|
class ListBasedExecutor {
|
|
12
|
-
constructor(viewer, placeholderID,
|
|
12
|
+
constructor(viewer, placeholderID, operations, options) {
|
|
13
13
|
this.viewer = viewer;
|
|
14
14
|
this.placeholderID = placeholderID;
|
|
15
|
-
this.ent = ent;
|
|
16
15
|
this.operations = operations;
|
|
17
16
|
this.options = options;
|
|
18
17
|
this.idx = 0;
|
|
@@ -27,8 +26,9 @@ class ListBasedExecutor {
|
|
|
27
26
|
[Symbol.iterator]() {
|
|
28
27
|
return this;
|
|
29
28
|
}
|
|
29
|
+
// returns true and null|undefined when done
|
|
30
30
|
next() {
|
|
31
|
-
let createdEnt = getCreatedEnt(this.viewer, this.lastOp
|
|
31
|
+
let createdEnt = getCreatedEnt(this.viewer, this.lastOp);
|
|
32
32
|
if (createdEnt) {
|
|
33
33
|
this.createdEnt = createdEnt;
|
|
34
34
|
}
|
|
@@ -36,6 +36,10 @@ class ListBasedExecutor {
|
|
|
36
36
|
const op = this.operations[this.idx];
|
|
37
37
|
this.idx++;
|
|
38
38
|
this.lastOp = op;
|
|
39
|
+
// reset since this could be called multiple times. not needed if we have getSortedOps or something like that
|
|
40
|
+
if (done) {
|
|
41
|
+
this.idx = 0;
|
|
42
|
+
}
|
|
39
43
|
return {
|
|
40
44
|
value: op,
|
|
41
45
|
done: done,
|
|
@@ -74,30 +78,24 @@ class ListBasedExecutor {
|
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
exports.ListBasedExecutor = ListBasedExecutor;
|
|
77
|
-
function getCreatedEnt(viewer, op
|
|
78
|
-
if (op && op.
|
|
79
|
-
|
|
80
|
-
if (row) {
|
|
81
|
-
return new ent(viewer, row);
|
|
82
|
-
}
|
|
81
|
+
function getCreatedEnt(viewer, op) {
|
|
82
|
+
if (op && op.createdEnt) {
|
|
83
|
+
return op.createdEnt(viewer);
|
|
83
84
|
}
|
|
84
85
|
return null;
|
|
85
86
|
}
|
|
86
87
|
class ComplexExecutor {
|
|
87
|
-
constructor(viewer, placeholderID,
|
|
88
|
+
constructor(viewer, placeholderID, operations, dependencies, changesets, options) {
|
|
88
89
|
this.viewer = viewer;
|
|
89
90
|
this.placeholderID = placeholderID;
|
|
90
|
-
this.ent = ent;
|
|
91
|
-
this.options = options;
|
|
92
91
|
this.idx = 0;
|
|
93
92
|
this.mapper = new Map();
|
|
94
93
|
this.allOperations = [];
|
|
95
|
-
this.changesetMap = new Map();
|
|
96
|
-
this.nodeOpMap = new Map();
|
|
97
94
|
this.executors = [];
|
|
98
95
|
let graph = (0, graph_data_structure_1.default)();
|
|
96
|
+
const changesetMap = new Map();
|
|
99
97
|
const impl = (c) => {
|
|
100
|
-
|
|
98
|
+
changesetMap.set(c.placeholderID.toString(), c);
|
|
101
99
|
graph.addNode(c.placeholderID.toString());
|
|
102
100
|
if (c.dependencies) {
|
|
103
101
|
for (let [key, builder] of c.dependencies) {
|
|
@@ -117,20 +115,19 @@ class ComplexExecutor {
|
|
|
117
115
|
impl({
|
|
118
116
|
viewer: this.viewer,
|
|
119
117
|
placeholderID: this.placeholderID,
|
|
120
|
-
ent: this.ent,
|
|
121
118
|
changesets: changesets,
|
|
122
119
|
dependencies: dependencies,
|
|
123
120
|
executor: () => {
|
|
124
|
-
return new ListBasedExecutor(this.viewer, this.placeholderID,
|
|
121
|
+
return new ListBasedExecutor(this.viewer, this.placeholderID, operations, options);
|
|
125
122
|
},
|
|
126
123
|
});
|
|
127
124
|
// use a set to handle repeated ops because of how the executor logic currently works
|
|
128
|
-
// TODO: this logic
|
|
125
|
+
// TODO: can this logic be rewritten to not have a set yet avoid duplicates?
|
|
129
126
|
let nodeOps = new Set();
|
|
130
127
|
let remainOps = new Set();
|
|
131
128
|
let sorted = graph.topologicalSort(graph.nodes());
|
|
132
129
|
sorted.forEach((node) => {
|
|
133
|
-
let c =
|
|
130
|
+
let c = changesetMap.get(node);
|
|
134
131
|
if (!c) {
|
|
135
132
|
// phew. expect it to be handled somewhere else
|
|
136
133
|
// we can just skip it and expect the resolver to handle this correctly
|
|
@@ -143,9 +140,8 @@ class ComplexExecutor {
|
|
|
143
140
|
// get ordered list of ops
|
|
144
141
|
let executor = c.executor();
|
|
145
142
|
for (let op of executor) {
|
|
146
|
-
if (op.
|
|
143
|
+
if (op.createdEnt) {
|
|
147
144
|
nodeOps.add(op);
|
|
148
|
-
this.nodeOpMap.set(op, c);
|
|
149
145
|
}
|
|
150
146
|
else {
|
|
151
147
|
remainOps.add(op);
|
|
@@ -165,26 +161,30 @@ class ComplexExecutor {
|
|
|
165
161
|
return this;
|
|
166
162
|
}
|
|
167
163
|
handleCreatedEnt() {
|
|
168
|
-
|
|
169
|
-
if (!c) {
|
|
170
|
-
// nothing to do here
|
|
164
|
+
if (!this.lastOp) {
|
|
171
165
|
return;
|
|
172
166
|
}
|
|
173
|
-
let createdEnt = getCreatedEnt(this.viewer, this.lastOp
|
|
167
|
+
let createdEnt = getCreatedEnt(this.viewer, this.lastOp);
|
|
174
168
|
if (!createdEnt) {
|
|
175
169
|
return;
|
|
176
170
|
}
|
|
177
|
-
|
|
171
|
+
const placeholderID = this.lastOp.placeholderID;
|
|
172
|
+
if (!placeholderID) {
|
|
173
|
+
console.error(`op ${this.lastOp} which implements getCreatedEnt doesn't have a placeholderID`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
178
176
|
this.mapper.set(placeholderID, createdEnt);
|
|
179
177
|
}
|
|
180
178
|
next() {
|
|
181
|
-
|
|
182
|
-
this.handleCreatedEnt();
|
|
183
|
-
}
|
|
179
|
+
this.handleCreatedEnt();
|
|
184
180
|
const done = this.idx === this.allOperations.length;
|
|
185
181
|
const op = this.allOperations[this.idx];
|
|
186
182
|
this.idx++;
|
|
187
183
|
this.lastOp = op;
|
|
184
|
+
// reset since this could be called multiple times. not needed if we have getSortedOps or something like that
|
|
185
|
+
if (done) {
|
|
186
|
+
this.idx = 0;
|
|
187
|
+
}
|
|
188
188
|
return {
|
|
189
189
|
value: op,
|
|
190
190
|
done: done,
|
|
@@ -195,6 +195,12 @@ class ComplexExecutor {
|
|
|
195
195
|
if (ent) {
|
|
196
196
|
return ent;
|
|
197
197
|
}
|
|
198
|
+
for (const c of this.executors) {
|
|
199
|
+
const ent = c.resolveValue(val);
|
|
200
|
+
if (ent) {
|
|
201
|
+
return ent;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
198
204
|
return null;
|
|
199
205
|
}
|
|
200
206
|
async executeObservers() {
|
package/action/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { WriteOperation, Builder,
|
|
1
|
+
export { WriteOperation, Builder, Changeset, Trigger, Observer, Validator, Action, saveBuilder, saveBuilderX, setEdgeTypeInGroup, TriggerReturn, } from "./action";
|
|
2
2
|
export { OrchestratorOptions, Orchestrator, EntChangeset, EdgeInputData, } from "./orchestrator";
|
|
3
3
|
export { DenyIfBuilder, AllowIfBuilder } from "./privacy";
|
package/action/orchestrator.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ID, Data, Ent, Viewer, EntConstructor, LoadEntOptions } from "../core/base";
|
|
2
2
|
import { AssocEdgeInputOptions, DataOperation } from "../core/ent";
|
|
3
3
|
import { SchemaInputType } from "../schema/schema";
|
|
4
|
-
import { Changeset, Executor } from "../action";
|
|
4
|
+
import { Changeset, Executor } from "../action/action";
|
|
5
5
|
import { WriteOperation, Builder, Action } from "../action";
|
|
6
6
|
export interface OrchestratorOptions<T extends Ent, TData extends Data> {
|
|
7
7
|
viewer: Viewer;
|
|
@@ -64,7 +64,7 @@ export declare class Orchestrator<T extends Ent> {
|
|
|
64
64
|
validX(): Promise<void>;
|
|
65
65
|
build(): Promise<EntChangeset<T>>;
|
|
66
66
|
private viewerForEntLoad;
|
|
67
|
-
returnedRow
|
|
67
|
+
private returnedRow;
|
|
68
68
|
editedEnt(): Promise<T | null>;
|
|
69
69
|
editedEntX(): Promise<T>;
|
|
70
70
|
}
|
|
@@ -73,10 +73,11 @@ export declare class EntChangeset<T extends Ent> implements Changeset<T> {
|
|
|
73
73
|
readonly placeholderID: ID;
|
|
74
74
|
readonly ent: EntConstructor<T>;
|
|
75
75
|
operations: DataOperation[];
|
|
76
|
-
dependencies?: Map<ID, Builder<
|
|
76
|
+
dependencies?: Map<ID, Builder<Ent>> | undefined;
|
|
77
77
|
changesets?: Changeset<Ent>[] | undefined;
|
|
78
78
|
private options?;
|
|
79
|
-
|
|
79
|
+
private _executor;
|
|
80
|
+
constructor(viewer: Viewer, placeholderID: ID, ent: EntConstructor<T>, operations: DataOperation[], dependencies?: Map<ID, Builder<Ent>> | undefined, changesets?: Changeset<Ent>[] | undefined, options?: OrchestratorOptions<T, Data> | undefined);
|
|
80
81
|
executor(): Executor;
|
|
81
82
|
}
|
|
82
83
|
export {};
|
package/action/orchestrator.js
CHANGED
|
@@ -146,6 +146,8 @@ class Orchestrator {
|
|
|
146
146
|
tableName: this.options.tableName,
|
|
147
147
|
fieldsToResolve: this.fieldsToResolve,
|
|
148
148
|
key: this.options.key,
|
|
149
|
+
ent: this.options.loaderOptions.ent,
|
|
150
|
+
placeholderID: this.options.builder.placeholderID,
|
|
149
151
|
};
|
|
150
152
|
if (this.logValues) {
|
|
151
153
|
opts.fieldsToLog = this.logValues;
|
|
@@ -432,8 +434,8 @@ class Orchestrator {
|
|
|
432
434
|
return action.viewerForEntLoad(data);
|
|
433
435
|
}
|
|
434
436
|
async returnedRow() {
|
|
435
|
-
if (this.mainOp && this.mainOp.
|
|
436
|
-
return this.mainOp.
|
|
437
|
+
if (this.mainOp && this.mainOp.returnedRow) {
|
|
438
|
+
return this.mainOp.returnedRow();
|
|
437
439
|
}
|
|
438
440
|
return null;
|
|
439
441
|
}
|
|
@@ -475,13 +477,17 @@ class EntChangeset {
|
|
|
475
477
|
this.options = options;
|
|
476
478
|
}
|
|
477
479
|
executor() {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
// executor and depend on something else in the stack to handle this correctly
|
|
481
|
-
if (this.changesets?.length) {
|
|
482
|
-
return new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.ent, this.operations, this.dependencies, this.changesets, this.options);
|
|
480
|
+
if (this._executor) {
|
|
481
|
+
return this._executor;
|
|
483
482
|
}
|
|
484
|
-
|
|
483
|
+
if (!this.changesets?.length) {
|
|
484
|
+
// if we have dependencies but no changesets, we just need a simple
|
|
485
|
+
// executor and depend on something else in the stack to handle this correctly
|
|
486
|
+
// ComplexExecutor which could be a parent of this should make sure the dependency
|
|
487
|
+
// is resolved beforehand
|
|
488
|
+
return (this._executor = new executor_1.ListBasedExecutor(this.viewer, this.placeholderID, this.operations, this.options));
|
|
489
|
+
}
|
|
490
|
+
return (this._executor = new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.operations, this.dependencies || new Map(), this.changesets || [], this.options));
|
|
485
491
|
}
|
|
486
492
|
}
|
|
487
493
|
exports.EntChangeset = EntChangeset;
|
package/core/clause.js
CHANGED
|
@@ -177,7 +177,7 @@ function Or(...args) {
|
|
|
177
177
|
return new compositeClause(args, " OR ");
|
|
178
178
|
}
|
|
179
179
|
exports.Or = Or;
|
|
180
|
-
// todo
|
|
180
|
+
// TODO this breaks if values.length ===1 and array. todo fix
|
|
181
181
|
function In(col, ...values) {
|
|
182
182
|
return new inClause(col, values);
|
|
183
183
|
}
|
package/core/ent.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Queryer, SyncQueryer } from "./db";
|
|
2
|
-
import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context, SelectBaseDataOptions, CreateRowOptions, QueryDataOptions } from "./base";
|
|
3
|
-
import { Executor } from "../action";
|
|
2
|
+
import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context, SelectBaseDataOptions, CreateRowOptions, QueryDataOptions, EntConstructor } from "./base";
|
|
3
|
+
import { Executor } from "../action/action";
|
|
4
4
|
import * as clause from "./clause";
|
|
5
5
|
import { Builder } from "../action";
|
|
6
6
|
import DataLoader from "dataloader";
|
|
@@ -39,27 +39,33 @@ interface GroupQueryOptions {
|
|
|
39
39
|
limit: number;
|
|
40
40
|
}
|
|
41
41
|
export declare function buildGroupQuery(options: GroupQueryOptions): [string, clause.Clause];
|
|
42
|
-
export interface DataOperation {
|
|
42
|
+
export interface DataOperation<T extends Ent = Ent> {
|
|
43
43
|
preFetch?(queryer: Queryer, context?: Context): Promise<void>;
|
|
44
44
|
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
45
45
|
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
46
|
-
|
|
46
|
+
placeholderID?: ID;
|
|
47
|
+
returnedRow?(): Data | null;
|
|
48
|
+
createdEnt?(viewer: Viewer): T | null;
|
|
47
49
|
resolve?(executor: Executor): void;
|
|
48
50
|
postFetch?(queryer: Queryer, context?: Context): Promise<void>;
|
|
49
51
|
}
|
|
50
|
-
export interface EditNodeOptions extends EditRowOptions {
|
|
52
|
+
export interface EditNodeOptions<T extends Ent> extends EditRowOptions {
|
|
51
53
|
fieldsToResolve: string[];
|
|
54
|
+
ent: EntConstructor<T>;
|
|
55
|
+
placeholderID?: ID;
|
|
52
56
|
}
|
|
53
|
-
export declare class EditNodeOperation implements DataOperation {
|
|
54
|
-
options: EditNodeOptions
|
|
57
|
+
export declare class EditNodeOperation<T extends Ent> implements DataOperation {
|
|
58
|
+
options: EditNodeOptions<T>;
|
|
55
59
|
private existingEnt;
|
|
56
60
|
row: Data | null;
|
|
57
|
-
|
|
61
|
+
placeholderID?: ID | undefined;
|
|
62
|
+
constructor(options: EditNodeOptions<T>, existingEnt?: Ent | null);
|
|
58
63
|
resolve<T extends Ent>(executor: Executor): void;
|
|
59
64
|
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
60
|
-
reloadRow
|
|
65
|
+
private reloadRow;
|
|
61
66
|
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
62
|
-
|
|
67
|
+
returnedRow(): Data | null;
|
|
68
|
+
createdEnt(viewer: Viewer): T | null;
|
|
63
69
|
}
|
|
64
70
|
export declare class EdgeOperation implements DataOperation {
|
|
65
71
|
edgeInput: AssocEdgeInput;
|
package/core/ent.js
CHANGED
|
@@ -401,6 +401,7 @@ class EditNodeOperation {
|
|
|
401
401
|
constructor(options, existingEnt = null) {
|
|
402
402
|
this.options = options;
|
|
403
403
|
this.existingEnt = existingEnt;
|
|
404
|
+
this.placeholderID = options.placeholderID;
|
|
404
405
|
}
|
|
405
406
|
resolve(executor) {
|
|
406
407
|
if (!this.options.fieldsToResolve.length) {
|
|
@@ -463,9 +464,15 @@ class EditNodeOperation {
|
|
|
463
464
|
this.reloadRow(queryer, id, options);
|
|
464
465
|
}
|
|
465
466
|
}
|
|
466
|
-
|
|
467
|
+
returnedRow() {
|
|
467
468
|
return this.row;
|
|
468
469
|
}
|
|
470
|
+
createdEnt(viewer) {
|
|
471
|
+
if (!this.row) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
return new this.options.ent(viewer, this.row);
|
|
475
|
+
}
|
|
469
476
|
}
|
|
470
477
|
exports.EditNodeOperation = EditNodeOperation;
|
|
471
478
|
class EdgeOperation {
|
|
@@ -5,6 +5,7 @@ const graphql_1 = require("graphql");
|
|
|
5
5
|
const node_1 = require("./node");
|
|
6
6
|
const edge_1 = require("./edge");
|
|
7
7
|
const page_info_1 = require("../query/page_info");
|
|
8
|
+
// NB: if this changes, need to update renderer.go also
|
|
8
9
|
exports.GraphQLConnectionInterface = new graphql_1.GraphQLInterfaceType({
|
|
9
10
|
name: "Connection",
|
|
10
11
|
description: "connection interface",
|
package/graphql/builtins/edge.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GraphQLEdgeInterface = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const node_1 = require("./node");
|
|
6
|
+
// NB: if this changes, need to update renderer.go also
|
|
6
7
|
exports.GraphQLEdgeInterface = new graphql_1.GraphQLInterfaceType({
|
|
7
8
|
name: "Edge",
|
|
8
9
|
description: "edge interface",
|
package/graphql/builtins/node.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GraphQLNodeInterface = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
|
+
// NB: if this changes, need to update renderer.go also
|
|
5
6
|
exports.GraphQLNodeInterface = new graphql_1.GraphQLInterfaceType({
|
|
6
7
|
name: "Node",
|
|
7
8
|
description: "node interface",
|
package/graphql/graphql.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface CustomType {
|
|
|
8
8
|
importPath: string;
|
|
9
9
|
tsType?: string;
|
|
10
10
|
tsImportPath?: string;
|
|
11
|
+
[x: string]: any;
|
|
11
12
|
}
|
|
12
13
|
declare type Type = GraphQLScalarType | ClassType | string | CustomType;
|
|
13
14
|
export declare type GraphQLConnection<T> = {
|
|
@@ -81,6 +82,7 @@ declare enum NullableResult {
|
|
|
81
82
|
CONTENTS_AND_LIST = "contentsAndList",
|
|
82
83
|
ITEM = "true"
|
|
83
84
|
}
|
|
85
|
+
export declare const addCustomType: (type: CustomType) => void;
|
|
84
86
|
export declare class GQLCapture {
|
|
85
87
|
private static enabled;
|
|
86
88
|
static enable(enabled: boolean): void;
|
package/graphql/graphql.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.gqlFileUpload = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlArg = exports.gqlField = exports.GQLCapture = exports.CustomFieldType = void 0;
|
|
3
|
+
exports.gqlFileUpload = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlArg = exports.gqlField = exports.GQLCapture = exports.addCustomType = exports.CustomFieldType = void 0;
|
|
4
4
|
require("reflect-metadata");
|
|
5
5
|
// export interface gqlTopLevelOptions
|
|
6
6
|
// name?: string;
|
|
@@ -20,6 +20,88 @@ var NullableResult;
|
|
|
20
20
|
NullableResult["CONTENTS_AND_LIST"] = "contentsAndList";
|
|
21
21
|
NullableResult["ITEM"] = "true";
|
|
22
22
|
})(NullableResult || (NullableResult = {}));
|
|
23
|
+
const isArray = (type) => {
|
|
24
|
+
if (typeof type === "function") {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return type.push !== undefined;
|
|
28
|
+
};
|
|
29
|
+
const isConnection = (type) => {
|
|
30
|
+
if (typeof type !== "object") {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return type.node !== undefined;
|
|
34
|
+
};
|
|
35
|
+
const isString = (type) => {
|
|
36
|
+
if (type.lastIndexOf !== undefined) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
};
|
|
41
|
+
const isCustomType = (type) => {
|
|
42
|
+
return type.importPath !== undefined;
|
|
43
|
+
};
|
|
44
|
+
const isGraphQLScalarType = (type) => {
|
|
45
|
+
return type.serialize !== undefined;
|
|
46
|
+
};
|
|
47
|
+
const addCustomType = (type) => {
|
|
48
|
+
// TODO these should return ReadOnly objects...
|
|
49
|
+
const customType = GQLCapture.getCustomTypes().get(type.type);
|
|
50
|
+
if (customType && customType !== type) {
|
|
51
|
+
throw new Error(`cannot add multiple custom types of name ${type.type}`);
|
|
52
|
+
}
|
|
53
|
+
if (customType) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const r = require(type.importPath);
|
|
58
|
+
const ct = r[type.type];
|
|
59
|
+
// this gets us the information needed for scalars
|
|
60
|
+
if (ct && isGraphQLScalarType(ct)) {
|
|
61
|
+
type.scalarInfo = {
|
|
62
|
+
description: ct.description,
|
|
63
|
+
name: ct.name,
|
|
64
|
+
};
|
|
65
|
+
if (ct.specifiedByUrl) {
|
|
66
|
+
type.scalarInfo.specifiedByUrl = ct.specifiedByUrl;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
GQLCapture.getCustomTypes().set(type.type, type);
|
|
74
|
+
};
|
|
75
|
+
exports.addCustomType = addCustomType;
|
|
76
|
+
const getType = (typ, result) => {
|
|
77
|
+
if (isConnection(typ)) {
|
|
78
|
+
result.connection = true;
|
|
79
|
+
return getType(typ.node, result);
|
|
80
|
+
}
|
|
81
|
+
if (isArray(typ)) {
|
|
82
|
+
result.list = true;
|
|
83
|
+
return getType(typ[0], result);
|
|
84
|
+
}
|
|
85
|
+
if (isString(typ)) {
|
|
86
|
+
if (typ.lastIndexOf("]") !== -1) {
|
|
87
|
+
result.list = true;
|
|
88
|
+
result.type = typ.substr(1, typ.length - 2);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
result.type = typ;
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (isCustomType(typ)) {
|
|
96
|
+
result.type = typ.type;
|
|
97
|
+
(0, exports.addCustomType)(typ);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// GraphQLScalarType or ClassType
|
|
101
|
+
result.scalarType = isGraphQLScalarType(typ);
|
|
102
|
+
result.type = typ.name;
|
|
103
|
+
return;
|
|
104
|
+
};
|
|
23
105
|
class GQLCapture {
|
|
24
106
|
static enable(enabled) {
|
|
25
107
|
this.enabled = enabled;
|
|
@@ -104,66 +186,6 @@ class GQLCapture {
|
|
|
104
186
|
if ((type === "Number" || type === "Object") && !options?.type) {
|
|
105
187
|
throw new Error(`type is required when accessor/function/property returns a ${type}`);
|
|
106
188
|
}
|
|
107
|
-
const isArray = (type) => {
|
|
108
|
-
if (typeof type === "function") {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
return type.push !== undefined;
|
|
112
|
-
};
|
|
113
|
-
const isConnection = (type) => {
|
|
114
|
-
if (typeof type !== "object") {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
return type.node !== undefined;
|
|
118
|
-
};
|
|
119
|
-
const isString = (type) => {
|
|
120
|
-
if (type.lastIndexOf !== undefined) {
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
};
|
|
125
|
-
const isCustomType = (type) => {
|
|
126
|
-
return type.importPath !== undefined;
|
|
127
|
-
};
|
|
128
|
-
const isGraphQLScalarType = (type) => {
|
|
129
|
-
return type.serialize !== undefined;
|
|
130
|
-
};
|
|
131
|
-
const addCustomType = (type) => {
|
|
132
|
-
const customType = this.customTypes.get(type.type);
|
|
133
|
-
if (customType && customType !== type) {
|
|
134
|
-
throw new Error(`cannot add multiple custom types of name ${type.type}`);
|
|
135
|
-
}
|
|
136
|
-
this.customTypes.set(type.type, type);
|
|
137
|
-
};
|
|
138
|
-
const getType = (typ, result) => {
|
|
139
|
-
if (isConnection(typ)) {
|
|
140
|
-
result.connection = true;
|
|
141
|
-
return getType(typ.node, result);
|
|
142
|
-
}
|
|
143
|
-
if (isArray(typ)) {
|
|
144
|
-
result.list = true;
|
|
145
|
-
return getType(typ[0], result);
|
|
146
|
-
}
|
|
147
|
-
if (isString(typ)) {
|
|
148
|
-
if (typ.lastIndexOf("]") !== -1) {
|
|
149
|
-
result.list = true;
|
|
150
|
-
result.type = typ.substr(1, typ.length - 2);
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
result.type = typ;
|
|
154
|
-
}
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (isCustomType(typ)) {
|
|
158
|
-
result.type = typ.type;
|
|
159
|
-
addCustomType(typ);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
// GraphQLScalarType or ClassType
|
|
163
|
-
result.scalarType = isGraphQLScalarType(typ);
|
|
164
|
-
result.type = typ.name;
|
|
165
|
-
return;
|
|
166
|
-
};
|
|
167
189
|
let list;
|
|
168
190
|
let scalarType = false;
|
|
169
191
|
let connection;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GraphQLPageInfo = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
|
+
// NB: if this changes, need to update renderer.go also
|
|
5
6
|
exports.GraphQLPageInfo = new graphql_1.GraphQLObjectType({
|
|
6
7
|
name: "PageInfo",
|
|
7
8
|
fields: () => ({
|
package/imports/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ interface classResult {
|
|
|
10
10
|
class: classInfo;
|
|
11
11
|
file: file;
|
|
12
12
|
}
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function parseCustomImports(filePath: string, opts?: Options): PathResult;
|
|
14
14
|
export declare function findTSConfigFile(filePath: string): string | null;
|
|
15
15
|
export interface importInfo {
|
|
16
16
|
name: string;
|
package/imports/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.findTSConfigFile = exports.
|
|
25
|
+
exports.findTSConfigFile = exports.parseCustomImports = void 0;
|
|
26
26
|
const glob_1 = __importDefault(require("glob"));
|
|
27
27
|
const typescript_1 = __importDefault(require("typescript"));
|
|
28
28
|
const json5_1 = __importDefault(require("json5"));
|
|
@@ -42,10 +42,9 @@ function getFiles(filePath, opts) {
|
|
|
42
42
|
}
|
|
43
43
|
return files;
|
|
44
44
|
}
|
|
45
|
-
function
|
|
45
|
+
function parseCustomImports(filePath, opts) {
|
|
46
46
|
const files = getFiles(filePath, opts);
|
|
47
47
|
const options = readCompilerOptions(filePath);
|
|
48
|
-
// classMap
|
|
49
48
|
let classMap = new Map();
|
|
50
49
|
files.forEach((file) => {
|
|
51
50
|
const sourceFile = typescript_1.default.createSourceFile(file, fs.readFileSync(file).toString(), options.target || typescript_1.default.ScriptTarget.ES2015);
|
|
@@ -77,7 +76,7 @@ function parseCustomInput(filePath, opts) {
|
|
|
77
76
|
},
|
|
78
77
|
};
|
|
79
78
|
}
|
|
80
|
-
exports.
|
|
79
|
+
exports.parseCustomImports = parseCustomImports;
|
|
81
80
|
function findTSConfigFile(filePath) {
|
|
82
81
|
while (filePath != "/") {
|
|
83
82
|
let configPath = `${filePath}/tsconfig.json`;
|
|
@@ -95,7 +94,6 @@ function readCompilerOptions(filePath) {
|
|
|
95
94
|
if (!configPath) {
|
|
96
95
|
return {};
|
|
97
96
|
}
|
|
98
|
-
const root = path.join(filePath, "..");
|
|
99
97
|
let json = {};
|
|
100
98
|
try {
|
|
101
99
|
json = json5_1.default.parse(fs.readFileSync(configPath, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snowtop/ent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"description": "snowtop ent framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"engines": {
|
|
42
|
-
"node": "
|
|
42
|
+
"node": ">=14.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {},
|
|
45
45
|
"scripts": {},
|
|
File without changes
|
|
@@ -25,6 +25,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const glob_1 = __importDefault(require("glob"));
|
|
27
27
|
const minimist_1 = __importDefault(require("minimist"));
|
|
28
|
+
const graphql_1 = require("../graphql/graphql");
|
|
28
29
|
const readline = __importStar(require("readline"));
|
|
29
30
|
const path = __importStar(require("path"));
|
|
30
31
|
const fs = __importStar(require("fs"));
|
|
@@ -52,7 +53,17 @@ async function readInputs() {
|
|
|
52
53
|
});
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
|
-
async function captureCustom(filePath) {
|
|
56
|
+
async function captureCustom(filePath, filesCsv) {
|
|
57
|
+
if (filesCsv !== undefined) {
|
|
58
|
+
let files = filesCsv.split(",");
|
|
59
|
+
for (let i = 0; i < files.length; i++) {
|
|
60
|
+
// TODO fix. we have "src" in the path we get here
|
|
61
|
+
files[i] = path.join(filePath, "..", files[i]);
|
|
62
|
+
}
|
|
63
|
+
await requireFiles(files);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// TODO delete all of this eventually
|
|
56
67
|
// TODO configurable paths eventually
|
|
57
68
|
// for now only files that are in the include path of the roots are allowed
|
|
58
69
|
const rootFiles = [
|
|
@@ -81,18 +92,28 @@ async function captureCustom(filePath) {
|
|
|
81
92
|
ignore: ignore,
|
|
82
93
|
});
|
|
83
94
|
const files = rootFiles.concat(customGQLResolvers, customGQLMutations);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
await requireFiles(files);
|
|
96
|
+
}
|
|
97
|
+
async function requireFiles(files) {
|
|
98
|
+
await Promise.all(files.map(async (file) => {
|
|
87
99
|
if (fs.existsSync(file)) {
|
|
88
|
-
|
|
100
|
+
try {
|
|
101
|
+
await require(file);
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
throw new Error(`${e.message} loading ${file}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw new Error(`file ${file} doesn't exist`);
|
|
89
109
|
}
|
|
110
|
+
})).catch((err) => {
|
|
111
|
+
throw new Error(err);
|
|
90
112
|
});
|
|
91
|
-
await Promise.all(promises);
|
|
92
113
|
}
|
|
93
114
|
async function parseImports(filePath) {
|
|
94
115
|
// only do graphql files...
|
|
95
|
-
return (0, imports_1.
|
|
116
|
+
return (0, imports_1.parseCustomImports)(path.join(filePath, "graphql"), {
|
|
96
117
|
ignore: ["**/generated/**", "**/tests/**"],
|
|
97
118
|
});
|
|
98
119
|
}
|
|
@@ -110,6 +131,20 @@ function findGraphQLPath(filePath) {
|
|
|
110
131
|
return undefined;
|
|
111
132
|
}
|
|
112
133
|
async function main() {
|
|
134
|
+
// known custom types that are not required
|
|
135
|
+
// if not in the schema, will be ignored
|
|
136
|
+
// something like GraphQLUpload gotten via gqlArg({type: gqlFileUpload})
|
|
137
|
+
// these 2 need this because they're added by the schema
|
|
138
|
+
// if this list grows too long, need to build this into golang types and passed here
|
|
139
|
+
// TODO foreign non-scalars eventually
|
|
140
|
+
(0, graphql_1.addCustomType)({
|
|
141
|
+
importPath: "../graphql/scalars/time",
|
|
142
|
+
type: "GraphQLTime",
|
|
143
|
+
});
|
|
144
|
+
(0, graphql_1.addCustomType)({
|
|
145
|
+
importPath: "graphql-type-json",
|
|
146
|
+
type: "GraphQLJSON",
|
|
147
|
+
});
|
|
113
148
|
const options = (0, minimist_1.default)(process.argv.slice(2));
|
|
114
149
|
if (!options.path) {
|
|
115
150
|
throw new Error("path required");
|
|
@@ -126,7 +161,7 @@ async function main() {
|
|
|
126
161
|
GQLCapture.enable(true);
|
|
127
162
|
const [inputsRead, _, imports] = await Promise.all([
|
|
128
163
|
readInputs(),
|
|
129
|
-
captureCustom(options.path),
|
|
164
|
+
captureCustom(options.path, options.files),
|
|
130
165
|
parseImports(options.path),
|
|
131
166
|
]);
|
|
132
167
|
const { nodes, nodesMap } = inputsRead;
|
package/testutils/builder.d.ts
CHANGED
|
@@ -93,7 +93,7 @@ export declare class SimpleAction<T extends Ent> implements Action<T> {
|
|
|
93
93
|
viewerForEntLoad: viewerEntLoadFunc | undefined;
|
|
94
94
|
constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation?: WriteOperation, existingEnt?: T | undefined);
|
|
95
95
|
getPrivacyPolicy(): import("../core/base").PrivacyPolicy;
|
|
96
|
-
getInput():
|
|
96
|
+
getInput(): Data;
|
|
97
97
|
changeset(): Promise<Changeset<T>>;
|
|
98
98
|
valid(): Promise<boolean>;
|
|
99
99
|
validX(): Promise<void>;
|
package/testutils/builder.js
CHANGED
|
@@ -185,7 +185,11 @@ class SimpleAction {
|
|
|
185
185
|
return privacy_1.AlwaysAllowPrivacyPolicy;
|
|
186
186
|
}
|
|
187
187
|
getInput() {
|
|
188
|
-
|
|
188
|
+
const ret = {};
|
|
189
|
+
for (const [k, v] of this.fields) {
|
|
190
|
+
ret[k] = v;
|
|
191
|
+
}
|
|
192
|
+
return ret;
|
|
189
193
|
}
|
|
190
194
|
changeset() {
|
|
191
195
|
return this.builder.build();
|
package/testutils/db_mock.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QueryRecorder = exports.queryType = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
|
-
const
|
|
5
|
+
const jest_mock_1 = require("jest-mock");
|
|
6
6
|
const parse_sql_1 = require("./parse_sql");
|
|
7
7
|
const eventEmitter = {
|
|
8
8
|
on: jest.fn(),
|
|
@@ -185,7 +185,7 @@ class QueryRecorder {
|
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
static mockPool(pool) {
|
|
188
|
-
const mockedPool = (0,
|
|
188
|
+
const mockedPool = (0, jest_mock_1.mocked)(pool, true);
|
|
189
189
|
mockedPool.mockImplementation(() => {
|
|
190
190
|
return {
|
|
191
191
|
totalCount: 1,
|
|
@@ -286,11 +286,11 @@ async function expectFromRoot(config, ...options) {
|
|
|
286
286
|
let fields = query?.getFields();
|
|
287
287
|
if (!fields) {
|
|
288
288
|
// TODO custom error?
|
|
289
|
-
|
|
289
|
+
throw new Error("schema doesn't have query or fields");
|
|
290
290
|
}
|
|
291
291
|
let field = fields[config.root];
|
|
292
292
|
if (!field) {
|
|
293
|
-
|
|
293
|
+
throw new Error(`could not find field ${config.root} in GraphQL query schema`);
|
|
294
294
|
}
|
|
295
295
|
let fieldArgs = field.args;
|
|
296
296
|
let queryParams = [];
|
|
@@ -361,7 +361,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
361
361
|
expect(errors[0].message).toMatch(config.expectedError);
|
|
362
362
|
}
|
|
363
363
|
else {
|
|
364
|
-
|
|
364
|
+
throw new Error(`unhandled error ${JSON.stringify(errors)}`);
|
|
365
365
|
}
|
|
366
366
|
return st;
|
|
367
367
|
}
|
|
@@ -416,7 +416,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
416
416
|
if (idx !== -1) {
|
|
417
417
|
let endIdx = part.indexOf("]");
|
|
418
418
|
if (endIdx === -1) {
|
|
419
|
-
|
|
419
|
+
throw new Error("can't have a beginning index without an end index");
|
|
420
420
|
}
|
|
421
421
|
// get the idx we care about
|
|
422
422
|
listIdx = parseInt(part.substr(idx + 1, endIdx - idx), 10);
|
|
@@ -428,7 +428,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
428
428
|
if (idx !== -1) {
|
|
429
429
|
let endIdx = part.indexOf(")");
|
|
430
430
|
if (endIdx === -1) {
|
|
431
|
-
|
|
431
|
+
throw new Error("can't have a beginning index without an end index");
|
|
432
432
|
}
|
|
433
433
|
// update part
|
|
434
434
|
part = part.substr(0, idx);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAllEvents = exports.tempDBTables = exports.setupTempDB = exports.createTestEvent = exports.edgeTableNames = exports.createEdges = exports.verifyUserToContacts = exports.verifyUserToContactRawData = exports.verifyUserToContactEdges = exports.addEdge = exports.createUserPlusFriendRequests = exports.createAllContacts = exports.inputs = exports.createTestUser = exports.getEventInput = exports.getUserInput = exports.getContactInput = void 0;
|
|
4
|
-
const assert_1 = require("assert");
|
|
5
4
|
const jest_date_mock_1 = require("jest-date-mock");
|
|
6
5
|
const viewer_1 = require("../../core/viewer");
|
|
7
6
|
const ent_1 = require("../../core/ent");
|
|
@@ -56,7 +55,7 @@ async function createTestUser(input) {
|
|
|
56
55
|
...input,
|
|
57
56
|
});
|
|
58
57
|
if (!user) {
|
|
59
|
-
|
|
58
|
+
throw new Error("error creating user");
|
|
60
59
|
}
|
|
61
60
|
return user;
|
|
62
61
|
}
|