@snowtop/ent 0.1.0-alpha138 → 0.1.0-alpha139
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 +8 -1
- package/action/executor.d.ts +16 -3
- package/action/executor.js +67 -12
- package/action/index.d.ts +1 -1
- package/action/operations.d.ts +125 -0
- package/action/operations.js +684 -0
- package/action/orchestrator.d.ts +13 -7
- package/action/orchestrator.js +109 -42
- package/core/base.d.ts +7 -1
- package/core/db.js +2 -0
- package/core/ent.d.ts +1 -84
- package/core/ent.js +20 -509
- package/index.d.ts +2 -1
- package/index.js +7 -5
- package/package.json +2 -2
- package/parse_schema/parse.js +1 -0
- package/schema/base_schema.d.ts +2 -0
- package/schema/base_schema.js +2 -0
- package/schema/schema.d.ts +2 -1
- package/testutils/action/complex_schemas.d.ts +1 -1
- package/testutils/builder.d.ts +3 -0
- package/testutils/builder.js +6 -0
- package/testutils/db/temp_db.d.ts +2 -1
- package/testutils/db/temp_db.js +41 -5
package/action/orchestrator.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ID, Data, Ent, Viewer,
|
|
2
|
-
import { AssocEdgeInputOptions, DataOperation } from "../core/ent";
|
|
1
|
+
import { ID, Data, Ent, Viewer, LoadEntOptions, CreateRowOptions } from "../core/base";
|
|
3
2
|
import { SchemaInputType, FieldInfoMap } from "../schema/schema";
|
|
4
|
-
import { Changeset, Executor } from "../action/action";
|
|
3
|
+
import { Changeset, ChangesetOptions, Executor } from "../action/action";
|
|
4
|
+
import { AssocEdgeInputOptions, DataOperation, AssocEdgeOptions } from "./operations";
|
|
5
5
|
import { WriteOperation, Builder, Action } from "../action";
|
|
6
6
|
import * as clause from "../core/clause";
|
|
7
7
|
type MaybeNull<T extends Ent> = T | null;
|
|
@@ -37,6 +37,7 @@ export declare class Orchestrator<TEnt extends Ent<TViewer>, TInput extends Data
|
|
|
37
37
|
private options;
|
|
38
38
|
private edgeSet;
|
|
39
39
|
private edges;
|
|
40
|
+
private conditionalEdges;
|
|
40
41
|
private validatedFields;
|
|
41
42
|
private logValues;
|
|
42
43
|
private changesets;
|
|
@@ -49,15 +50,17 @@ export declare class Orchestrator<TEnt extends Ent<TViewer>, TInput extends Data
|
|
|
49
50
|
private actualOperation;
|
|
50
51
|
private existingEnt;
|
|
51
52
|
private disableTransformations;
|
|
53
|
+
private onConflict;
|
|
52
54
|
private memoizedGetFields;
|
|
53
55
|
constructor(options: OrchestratorOptions<TEnt, TInput, TViewer, TExistingEnt>);
|
|
54
56
|
__getOptions(): OrchestratorOptions<any, any, any, any>;
|
|
55
57
|
private addEdge;
|
|
56
58
|
setDisableTransformations(val: boolean): void;
|
|
59
|
+
setOnConflictOptions(onConflict: CreateRowOptions["onConflict"]): void;
|
|
57
60
|
addInboundEdge<T2 extends Ent>(id1: ID | Builder<T2, any>, edgeType: string, nodeType: string, options?: AssocEdgeInputOptions): void;
|
|
58
61
|
addOutboundEdge<T2 extends Ent>(id2: ID | Builder<T2, any>, edgeType: string, nodeType: string, options?: AssocEdgeInputOptions): void;
|
|
59
|
-
removeInboundEdge(id1: ID, edgeType: string): void;
|
|
60
|
-
removeOutboundEdge(id2: ID, edgeType: string): void;
|
|
62
|
+
removeInboundEdge(id1: ID, edgeType: string, options?: AssocEdgeOptions): void;
|
|
63
|
+
removeOutboundEdge(id2: ID, edgeType: string, options?: AssocEdgeOptions): void;
|
|
61
64
|
getInputEdges(edgeType: string, op: WriteOperation): EdgeInputData[];
|
|
62
65
|
clearInputEdges(edgeType: string, op: WriteOperation, id?: ID): void;
|
|
63
66
|
private buildMainOp;
|
|
@@ -95,7 +98,9 @@ export declare class Orchestrator<TEnt extends Ent<TViewer>, TInput extends Data
|
|
|
95
98
|
* If those throws, this still throws and doesn't return them
|
|
96
99
|
*/
|
|
97
100
|
validWithErrors(): Promise<Error[]>;
|
|
101
|
+
private buildPlusChangeset;
|
|
98
102
|
build(): Promise<EntChangeset<TEnt>>;
|
|
103
|
+
buildWithOptions_BETA(options: ChangesetOptions): Promise<EntChangeset<TEnt>>;
|
|
99
104
|
private viewerForEntLoad;
|
|
100
105
|
returnedRow(): Promise<Data | null>;
|
|
101
106
|
editedEnt(): Promise<TEnt | null>;
|
|
@@ -103,14 +108,15 @@ export declare class Orchestrator<TEnt extends Ent<TViewer>, TInput extends Data
|
|
|
103
108
|
}
|
|
104
109
|
export declare class EntChangeset<T extends Ent> implements Changeset {
|
|
105
110
|
viewer: Viewer;
|
|
111
|
+
private builder;
|
|
106
112
|
readonly placeholderID: ID;
|
|
107
|
-
|
|
113
|
+
private conditionalOverride;
|
|
108
114
|
operations: DataOperation[];
|
|
109
115
|
dependencies?: Map<ID, Builder<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>, Ent<Viewer<Ent<any> | null, ID | null>> | null>> | undefined;
|
|
110
116
|
changesets?: Changeset[] | undefined;
|
|
111
117
|
private options?;
|
|
112
118
|
private _executor;
|
|
113
|
-
constructor(viewer: Viewer, placeholderID: ID,
|
|
119
|
+
constructor(viewer: Viewer, builder: Builder<T>, placeholderID: ID, conditionalOverride: boolean, operations: DataOperation[], dependencies?: Map<ID, Builder<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>, Ent<Viewer<Ent<any> | null, ID | null>> | null>> | undefined, changesets?: Changeset[] | undefined, options?: OrchestratorOptions<T, Data, Viewer<Ent<any> | null, ID | null>, MaybeNull<T>> | undefined);
|
|
114
120
|
static changesetFrom(builder: Builder<any, any, any>, ops: DataOperation[]): EntChangeset<any>;
|
|
115
121
|
executor(): Executor;
|
|
116
122
|
}
|
package/action/orchestrator.js
CHANGED
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.EntChangeset = exports.Orchestrator = exports.edgeDirection = void 0;
|
|
30
30
|
const ent_1 = require("../core/ent");
|
|
31
31
|
const schema_1 = require("../schema/schema");
|
|
32
|
+
const operations_1 = require("./operations");
|
|
32
33
|
const action_1 = require("../action");
|
|
33
34
|
const privacy_1 = require("../core/privacy");
|
|
34
35
|
const executor_1 = require("./executor");
|
|
@@ -83,6 +84,7 @@ class Orchestrator {
|
|
|
83
84
|
this.options = options;
|
|
84
85
|
this.edgeSet = new Set();
|
|
85
86
|
this.edges = new Map();
|
|
87
|
+
this.conditionalEdges = new Map();
|
|
86
88
|
this.changesets = [];
|
|
87
89
|
this.dependencies = new Map();
|
|
88
90
|
this.fieldsToResolve = [];
|
|
@@ -97,7 +99,7 @@ class Orchestrator {
|
|
|
97
99
|
__getOptions() {
|
|
98
100
|
return this.options;
|
|
99
101
|
}
|
|
100
|
-
addEdge(edge, op) {
|
|
102
|
+
addEdge(edge, op, conditional) {
|
|
101
103
|
this.edgeSet.add(edge.edgeType);
|
|
102
104
|
let m1 = this.edges.get(edge.edgeType) || new Map();
|
|
103
105
|
let m2 = m1.get(op) || new Map();
|
|
@@ -112,11 +114,22 @@ class Orchestrator {
|
|
|
112
114
|
// set or overwrite the new edge data for said id
|
|
113
115
|
m2.set(id, edge);
|
|
114
116
|
m1.set(op, m2);
|
|
115
|
-
this.
|
|
117
|
+
if (conditional && this.onConflict) {
|
|
118
|
+
this.conditionalEdges.set(edge.edgeType, m1);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
this.edges.set(edge.edgeType, m1);
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
setDisableTransformations(val) {
|
|
118
125
|
this.disableTransformations = val;
|
|
119
126
|
}
|
|
127
|
+
setOnConflictOptions(onConflict) {
|
|
128
|
+
if (onConflict?.onConflictConstraint && !onConflict.updateCols) {
|
|
129
|
+
throw new Error(`cannot set onConflictConstraint without updateCols`);
|
|
130
|
+
}
|
|
131
|
+
this.onConflict = onConflict;
|
|
132
|
+
}
|
|
120
133
|
addInboundEdge(id1, edgeType, nodeType, options) {
|
|
121
134
|
this.addEdge(new edgeInputData({
|
|
122
135
|
id: id1,
|
|
@@ -124,7 +137,7 @@ class Orchestrator {
|
|
|
124
137
|
nodeType,
|
|
125
138
|
options,
|
|
126
139
|
direction: edgeDirection.inboundEdge,
|
|
127
|
-
}), action_1.WriteOperation.Insert);
|
|
140
|
+
}), action_1.WriteOperation.Insert, options?.conditional);
|
|
128
141
|
}
|
|
129
142
|
addOutboundEdge(id2, edgeType, nodeType, options) {
|
|
130
143
|
this.addEdge(new edgeInputData({
|
|
@@ -133,21 +146,21 @@ class Orchestrator {
|
|
|
133
146
|
nodeType,
|
|
134
147
|
options,
|
|
135
148
|
direction: edgeDirection.outboundEdge,
|
|
136
|
-
}), action_1.WriteOperation.Insert);
|
|
149
|
+
}), action_1.WriteOperation.Insert, options?.conditional);
|
|
137
150
|
}
|
|
138
|
-
removeInboundEdge(id1, edgeType) {
|
|
151
|
+
removeInboundEdge(id1, edgeType, options) {
|
|
139
152
|
this.addEdge(new edgeInputData({
|
|
140
153
|
id: id1,
|
|
141
154
|
edgeType,
|
|
142
155
|
direction: edgeDirection.inboundEdge,
|
|
143
|
-
}), action_1.WriteOperation.Delete);
|
|
156
|
+
}), action_1.WriteOperation.Delete, options?.conditional);
|
|
144
157
|
}
|
|
145
|
-
removeOutboundEdge(id2, edgeType) {
|
|
158
|
+
removeOutboundEdge(id2, edgeType, options) {
|
|
146
159
|
this.addEdge(new edgeInputData({
|
|
147
160
|
id: id2,
|
|
148
161
|
edgeType,
|
|
149
162
|
direction: edgeDirection.outboundEdge,
|
|
150
|
-
}), action_1.WriteOperation.Delete);
|
|
163
|
+
}), action_1.WriteOperation.Delete, options?.conditional);
|
|
151
164
|
}
|
|
152
165
|
// this doesn't take a direction as that's an implementation detail
|
|
153
166
|
// it doesn't make any sense to use the same edgeType for inbound and outbound edges
|
|
@@ -170,11 +183,11 @@ class Orchestrator {
|
|
|
170
183
|
m.clear();
|
|
171
184
|
}
|
|
172
185
|
}
|
|
173
|
-
buildMainOp() {
|
|
186
|
+
buildMainOp(conditionalBuilder) {
|
|
174
187
|
// this assumes we have validated fields
|
|
175
188
|
switch (this.actualOperation) {
|
|
176
189
|
case action_1.WriteOperation.Delete:
|
|
177
|
-
return new
|
|
190
|
+
return new operations_1.DeleteNodeOperation(this.existingEnt.id, this.options.builder, {
|
|
178
191
|
tableName: this.options.tableName,
|
|
179
192
|
});
|
|
180
193
|
default:
|
|
@@ -191,14 +204,18 @@ class Orchestrator {
|
|
|
191
204
|
fieldsToResolve: this.fieldsToResolve,
|
|
192
205
|
key: this.options.key,
|
|
193
206
|
loadEntOptions: this.options.loaderOptions,
|
|
194
|
-
placeholderID: this.options.builder.placeholderID,
|
|
195
207
|
whereClause: clause.Eq(this.options.key, this.existingEnt?.id),
|
|
196
208
|
expressions: this.options.expressions,
|
|
209
|
+
onConflict: this.onConflict,
|
|
210
|
+
builder: this.options.builder,
|
|
197
211
|
};
|
|
198
212
|
if (this.logValues) {
|
|
199
213
|
opts.fieldsToLog = this.logValues;
|
|
200
214
|
}
|
|
201
|
-
this.mainOp = new
|
|
215
|
+
this.mainOp = new operations_1.EditNodeOperation(opts, this.existingEnt);
|
|
216
|
+
if (conditionalBuilder) {
|
|
217
|
+
this.mainOp = new operations_1.ConditionalNodeOperation(this.mainOp, conditionalBuilder);
|
|
218
|
+
}
|
|
202
219
|
return this.mainOp;
|
|
203
220
|
}
|
|
204
221
|
}
|
|
@@ -218,10 +235,10 @@ class Orchestrator {
|
|
|
218
235
|
throw new Error(`no nodeType for edge when adding outboundEdge`);
|
|
219
236
|
}
|
|
220
237
|
if (edge.direction === edgeDirection.outboundEdge) {
|
|
221
|
-
return
|
|
238
|
+
return operations_1.EdgeOperation.outboundEdge(this.options.builder, edgeType, edge.id, edge.nodeType, edge.options);
|
|
222
239
|
}
|
|
223
240
|
else {
|
|
224
|
-
return
|
|
241
|
+
return operations_1.EdgeOperation.inboundEdge(this.options.builder, edgeType, edge.id, edge.nodeType, edge.options);
|
|
225
242
|
}
|
|
226
243
|
}
|
|
227
244
|
else if (op === action_1.WriteOperation.Delete) {
|
|
@@ -230,30 +247,53 @@ class Orchestrator {
|
|
|
230
247
|
}
|
|
231
248
|
let id2 = edge.id;
|
|
232
249
|
if (edge.direction === edgeDirection.outboundEdge) {
|
|
233
|
-
return
|
|
250
|
+
return operations_1.EdgeOperation.removeOutboundEdge(this.options.builder, edgeType, id2);
|
|
234
251
|
}
|
|
235
252
|
else {
|
|
236
|
-
return
|
|
253
|
+
return operations_1.EdgeOperation.removeInboundEdge(this.options.builder, edgeType, id2);
|
|
237
254
|
}
|
|
238
255
|
}
|
|
239
256
|
throw new Error("could not find an edge operation from the given parameters");
|
|
240
257
|
}
|
|
241
|
-
async buildEdgeOps(ops) {
|
|
258
|
+
async buildEdgeOps(ops, conditionalBuilder, conditionalOverride) {
|
|
242
259
|
const edgeDatas = await (0, ent_1.loadEdgeDatas)(...Array.from(this.edgeSet.values()));
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
260
|
+
const edges = [
|
|
261
|
+
[this.edges, false],
|
|
262
|
+
[this.conditionalEdges, true],
|
|
263
|
+
];
|
|
264
|
+
// conditional should only apply if onconflict...
|
|
265
|
+
// if no upsert and just create, nothing to do here
|
|
266
|
+
for (const edgeInfo of edges) {
|
|
267
|
+
const [edges, conditionalEdge] = edgeInfo;
|
|
268
|
+
const conditional = conditionalOverride || conditionalEdge;
|
|
269
|
+
for (const [edgeType, m] of edges) {
|
|
270
|
+
for (const [op, m2] of m) {
|
|
271
|
+
for (const [_, edge] of m2) {
|
|
272
|
+
let edgeOp = this.getEdgeOperation(edgeType, op, edge);
|
|
273
|
+
if (conditional) {
|
|
274
|
+
ops.push(new operations_1.ConditionalOperation(edgeOp, conditionalBuilder));
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
ops.push(edgeOp);
|
|
278
|
+
}
|
|
279
|
+
const edgeData = edgeDatas.get(edgeType);
|
|
280
|
+
if (!edgeData) {
|
|
281
|
+
throw new Error(`could not load edge data for '${edgeType}'`);
|
|
282
|
+
}
|
|
283
|
+
if (edgeData.symmetricEdge) {
|
|
284
|
+
let symmetric = edgeOp.symmetricEdge();
|
|
285
|
+
if (conditional) {
|
|
286
|
+
symmetric = new operations_1.ConditionalOperation(symmetric, conditionalBuilder);
|
|
287
|
+
}
|
|
288
|
+
ops.push(symmetric);
|
|
289
|
+
}
|
|
290
|
+
if (edgeData.inverseEdgeType) {
|
|
291
|
+
let inverse = edgeOp.inverseEdge(edgeData);
|
|
292
|
+
if (conditional) {
|
|
293
|
+
inverse = new operations_1.ConditionalOperation(inverse, conditionalBuilder);
|
|
294
|
+
}
|
|
295
|
+
ops.push(inverse);
|
|
296
|
+
}
|
|
257
297
|
}
|
|
258
298
|
}
|
|
259
299
|
}
|
|
@@ -498,6 +538,8 @@ class Orchestrator {
|
|
|
498
538
|
// else apply schema tranformation if it exists
|
|
499
539
|
let transformed = null;
|
|
500
540
|
const sqlOp = this.getSQLStatementOperation();
|
|
541
|
+
// why is transform write technically different from upsert?
|
|
542
|
+
// it's create -> update just at the db level...
|
|
501
543
|
if (action?.transformWrite) {
|
|
502
544
|
transformed = await action.transformWrite({
|
|
503
545
|
builder,
|
|
@@ -539,8 +581,8 @@ class Orchestrator {
|
|
|
539
581
|
}
|
|
540
582
|
}
|
|
541
583
|
if (transformed.changeset) {
|
|
542
|
-
const
|
|
543
|
-
this.changesets.push(
|
|
584
|
+
const changeset = await transformed.changeset();
|
|
585
|
+
this.changesets.push(changeset);
|
|
544
586
|
}
|
|
545
587
|
this.actualOperation = this.getWriteOpForSQLStamentOp(transformed.op);
|
|
546
588
|
if (transformed.existingEnt) {
|
|
@@ -758,13 +800,25 @@ class Orchestrator {
|
|
|
758
800
|
async validWithErrors() {
|
|
759
801
|
return this.validate();
|
|
760
802
|
}
|
|
761
|
-
async
|
|
803
|
+
async buildPlusChangeset(conditionalBuilder, conditionalOverride) {
|
|
762
804
|
// validate everything first
|
|
763
805
|
await this.validX();
|
|
764
|
-
let ops = [
|
|
765
|
-
|
|
806
|
+
let ops = [
|
|
807
|
+
this.buildMainOp(conditionalOverride ? conditionalBuilder : undefined),
|
|
808
|
+
];
|
|
809
|
+
await this.buildEdgeOps(ops, conditionalBuilder, conditionalOverride);
|
|
766
810
|
// TODO throw if we try and create a new changeset after previously creating one
|
|
767
|
-
|
|
811
|
+
// TODO test actualOperation value
|
|
812
|
+
// observers is fine since they're run after and we have the actualOperation value...
|
|
813
|
+
return new EntChangeset(this.options.viewer, this.options.builder, this.options.builder.placeholderID, conditionalOverride, ops, this.dependencies, this.changesets, this.options);
|
|
814
|
+
}
|
|
815
|
+
async build() {
|
|
816
|
+
return this.buildPlusChangeset(this.options.builder, false);
|
|
817
|
+
}
|
|
818
|
+
async buildWithOptions_BETA(options) {
|
|
819
|
+
// set as dependency so that we do the right order of operations
|
|
820
|
+
this.dependencies.set(options.conditionalBuilder.placeholderID, options.conditionalBuilder);
|
|
821
|
+
return this.buildPlusChangeset(options.conditionalBuilder, true);
|
|
768
822
|
}
|
|
769
823
|
async viewerForEntLoad(data) {
|
|
770
824
|
const action = this.options.action;
|
|
@@ -809,18 +863,25 @@ exports.Orchestrator = Orchestrator;
|
|
|
809
863
|
function randomNum() {
|
|
810
864
|
return Math.random().toString(10).substring(2);
|
|
811
865
|
}
|
|
866
|
+
// each changeset is required to have a unique placeholderID
|
|
867
|
+
// used in executor. if we end up creating multiple changesets from a builder, we need
|
|
868
|
+
// different placeholders
|
|
869
|
+
// in practice, only applies to Entchangeset::changesetFrom()
|
|
812
870
|
class EntChangeset {
|
|
813
|
-
constructor(viewer, placeholderID,
|
|
871
|
+
constructor(viewer, builder, placeholderID, conditionalOverride, operations, dependencies, changesets, options) {
|
|
814
872
|
this.viewer = viewer;
|
|
873
|
+
this.builder = builder;
|
|
815
874
|
this.placeholderID = placeholderID;
|
|
816
|
-
this.
|
|
875
|
+
this.conditionalOverride = conditionalOverride;
|
|
817
876
|
this.operations = operations;
|
|
818
877
|
this.dependencies = dependencies;
|
|
819
878
|
this.changesets = changesets;
|
|
820
879
|
this.options = options;
|
|
821
880
|
}
|
|
822
881
|
static changesetFrom(builder, ops) {
|
|
823
|
-
return new EntChangeset(builder.viewer,
|
|
882
|
+
return new EntChangeset(builder.viewer, builder,
|
|
883
|
+
// need unique placeholderID different from the builder. see comment above EntChangeset
|
|
884
|
+
`$ent.idPlaceholderID$ ${randomNum()}-${builder.ent.name}`, false, ops);
|
|
824
885
|
}
|
|
825
886
|
executor() {
|
|
826
887
|
if (this._executor) {
|
|
@@ -831,9 +892,15 @@ class EntChangeset {
|
|
|
831
892
|
// executor and depend on something else in the stack to handle this correctly
|
|
832
893
|
// ComplexExecutor which could be a parent of this should make sure the dependency
|
|
833
894
|
// is resolved beforehand
|
|
834
|
-
return (this._executor = new executor_1.ListBasedExecutor(this.viewer, this.placeholderID, this.operations, this.options
|
|
895
|
+
return (this._executor = new executor_1.ListBasedExecutor(this.viewer, this.placeholderID, this.operations, this.options, {
|
|
896
|
+
conditionalOverride: this.conditionalOverride,
|
|
897
|
+
builder: this.builder,
|
|
898
|
+
}));
|
|
835
899
|
}
|
|
836
|
-
return (this._executor = new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.operations, this.dependencies || new Map(), this.changesets || [], this.options
|
|
900
|
+
return (this._executor = new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.operations, this.dependencies || new Map(), this.changesets || [], this.options, {
|
|
901
|
+
conditionalOverride: this.conditionalOverride,
|
|
902
|
+
builder: this.builder,
|
|
903
|
+
}));
|
|
837
904
|
}
|
|
838
905
|
}
|
|
839
906
|
exports.EntChangeset = EntChangeset;
|
package/core/base.d.ts
CHANGED
|
@@ -88,11 +88,17 @@ export interface LoadRowOptions extends QueryableDataOptions {
|
|
|
88
88
|
}
|
|
89
89
|
export interface LoadRowsOptions extends QueryableDataOptions {
|
|
90
90
|
}
|
|
91
|
+
interface OnConflictOptions {
|
|
92
|
+
onConflictCols: string[];
|
|
93
|
+
onConflictConstraint?: string;
|
|
94
|
+
updateCols?: string[];
|
|
95
|
+
}
|
|
91
96
|
export interface CreateRowOptions extends DataOptions {
|
|
92
97
|
fields: Data;
|
|
93
98
|
fieldsToLog?: Data;
|
|
99
|
+
onConflict?: OnConflictOptions;
|
|
94
100
|
}
|
|
95
|
-
export interface EditRowOptions extends CreateRowOptions {
|
|
101
|
+
export interface EditRowOptions extends Omit<CreateRowOptions, "onConflict"> {
|
|
96
102
|
whereClause: clause.Clause;
|
|
97
103
|
expressions?: Map<string, clause.Clause>;
|
|
98
104
|
}
|
package/core/db.js
CHANGED
|
@@ -238,6 +238,8 @@ class Sqlite {
|
|
|
238
238
|
r = this.db.prepare(query).get(this.convertValues(values));
|
|
239
239
|
}
|
|
240
240
|
else {
|
|
241
|
+
// TODO querySync() with no values seems to do the wrong thing...
|
|
242
|
+
// e.g. querySync('select count(*) as count from table') returns nonsense
|
|
241
243
|
r = this.db.prepare(query).run();
|
|
242
244
|
}
|
|
243
245
|
return {
|
package/core/ent.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Queryer, SyncQueryer } from "./db";
|
|
2
2
|
import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context, CreateRowOptions, QueryDataOptions, SelectCustomDataOptions } from "./base";
|
|
3
|
-
import { Executor } from "../action/action";
|
|
4
3
|
import * as clause from "./clause";
|
|
5
|
-
import { Builder } from "../action";
|
|
6
4
|
import DataLoader from "dataloader";
|
|
7
5
|
export declare function getEntKey<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): string;
|
|
8
6
|
export declare function loadEnt<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
|
|
@@ -24,7 +22,7 @@ export declare function loadEntsList<TEnt extends Ent<TViewer>, TViewer extends
|
|
|
24
22
|
*/
|
|
25
23
|
export declare function loadEntsFromClause<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, clause: clause.Clause, options: LoadEntOptions<TEnt, TViewer>): Promise<Map<ID, TEnt>>;
|
|
26
24
|
export declare function loadCustomEnts<TEnt extends Ent<TViewer>, TViewer extends Viewer, TQueryData extends Data = Data, TResultData extends Data = TQueryData, TKey = keyof TQueryData>(viewer: TViewer, options: LoadCustomEntOptions<TEnt, TViewer, TResultData>, query: CustomQuery<TQueryData, TKey>): Promise<TEnt[]>;
|
|
27
|
-
interface parameterizedQueryOptions {
|
|
25
|
+
export interface parameterizedQueryOptions {
|
|
28
26
|
query: string;
|
|
29
27
|
values?: any[];
|
|
30
28
|
logValues?: any[];
|
|
@@ -81,69 +79,6 @@ interface GroupQueryOptions<T extends Data, K = keyof T> {
|
|
|
81
79
|
limit: number;
|
|
82
80
|
}
|
|
83
81
|
export declare function buildGroupQuery<T extends Data = Data, K = keyof T>(options: GroupQueryOptions<T, K>): [string, clause.Clause<T, K>];
|
|
84
|
-
export interface DataOperation<T extends Ent = Ent> {
|
|
85
|
-
preFetch?(queryer: Queryer, context?: Context): Promise<void>;
|
|
86
|
-
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
87
|
-
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
88
|
-
placeholderID?: ID;
|
|
89
|
-
returnedRow?(): Data | null;
|
|
90
|
-
createdEnt?(viewer: Viewer): T | null;
|
|
91
|
-
resolve?(executor: Executor): void;
|
|
92
|
-
postFetch?(queryer: Queryer, context?: Context): Promise<void>;
|
|
93
|
-
}
|
|
94
|
-
export interface EditNodeOptions<T extends Ent> extends EditRowOptions {
|
|
95
|
-
fieldsToResolve: string[];
|
|
96
|
-
loadEntOptions: LoadEntOptions<T>;
|
|
97
|
-
placeholderID?: ID;
|
|
98
|
-
key: string;
|
|
99
|
-
}
|
|
100
|
-
export declare class RawQueryOperation implements DataOperation {
|
|
101
|
-
private queries;
|
|
102
|
-
constructor(queries: (string | parameterizedQueryOptions)[]);
|
|
103
|
-
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
104
|
-
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
105
|
-
}
|
|
106
|
-
export declare class EditNodeOperation<T extends Ent> implements DataOperation {
|
|
107
|
-
options: EditNodeOptions<T>;
|
|
108
|
-
private existingEnt;
|
|
109
|
-
row: Data | null;
|
|
110
|
-
placeholderID?: ID | undefined;
|
|
111
|
-
constructor(options: EditNodeOptions<T>, existingEnt?: Ent | null);
|
|
112
|
-
resolve<T extends Ent>(executor: Executor): void;
|
|
113
|
-
private hasData;
|
|
114
|
-
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
115
|
-
private reloadRow;
|
|
116
|
-
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
117
|
-
returnedRow(): Data | null;
|
|
118
|
-
createdEnt(viewer: Viewer): T | null;
|
|
119
|
-
}
|
|
120
|
-
export declare class EdgeOperation implements DataOperation {
|
|
121
|
-
private builder;
|
|
122
|
-
edgeInput: AssocEdgeInput;
|
|
123
|
-
private options;
|
|
124
|
-
private edgeData;
|
|
125
|
-
private constructor();
|
|
126
|
-
preFetch(queryer: Queryer, context?: Context): Promise<void>;
|
|
127
|
-
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
128
|
-
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
129
|
-
private getDeleteRowParams;
|
|
130
|
-
private performDeleteWrite;
|
|
131
|
-
private performDeleteWriteSync;
|
|
132
|
-
private getInsertRowParams;
|
|
133
|
-
private performInsertWrite;
|
|
134
|
-
private performInsertWriteSync;
|
|
135
|
-
private resolveImpl;
|
|
136
|
-
resolve(executor: Executor): void;
|
|
137
|
-
symmetricEdge(): EdgeOperation;
|
|
138
|
-
inverseEdge(edgeData: AssocEdgeData): EdgeOperation;
|
|
139
|
-
private static resolveIDs;
|
|
140
|
-
private static isBuilder;
|
|
141
|
-
private static resolveData;
|
|
142
|
-
static inboundEdge<T extends Ent, T2 extends Ent>(builder: Builder<T>, edgeType: string, id1: Builder<T2> | ID, nodeType: string, options?: AssocEdgeInputOptions): EdgeOperation;
|
|
143
|
-
static outboundEdge<T extends Ent, T2 extends Ent>(builder: Builder<T>, edgeType: string, id2: Builder<T2> | ID, nodeType: string, options?: AssocEdgeInputOptions): EdgeOperation;
|
|
144
|
-
static removeInboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id1: ID): EdgeOperation;
|
|
145
|
-
static removeOutboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id2: ID): EdgeOperation;
|
|
146
|
-
}
|
|
147
82
|
export declare function buildInsertQuery(options: CreateRowOptions, suffix?: string): [string, string[], string[]];
|
|
148
83
|
export declare function createRow(queryer: Queryer, options: CreateRowOptions, suffix: string): Promise<Data | null>;
|
|
149
84
|
export declare function createRowSync(queryer: SyncQueryer, options: CreateRowOptions, suffix: string): Data | null;
|
|
@@ -152,13 +87,6 @@ export declare function editRow(queryer: Queryer, options: EditRowOptions, suffi
|
|
|
152
87
|
export declare function editRowSync(queryer: SyncQueryer, options: EditRowOptions, suffix?: string): Data | null;
|
|
153
88
|
export declare function deleteRows(queryer: Queryer, options: DataOptions, cls: clause.Clause): Promise<void>;
|
|
154
89
|
export declare function deleteRowsSync(queryer: SyncQueryer, options: DataOptions, cls: clause.Clause): void;
|
|
155
|
-
export declare class DeleteNodeOperation implements DataOperation {
|
|
156
|
-
private id;
|
|
157
|
-
private options;
|
|
158
|
-
constructor(id: ID, options: DataOptions);
|
|
159
|
-
performWrite(queryer: Queryer, context?: Context): Promise<void>;
|
|
160
|
-
performWriteSync(queryer: SyncQueryer, context?: Context): void;
|
|
161
|
-
}
|
|
162
90
|
export declare class AssocEdge {
|
|
163
91
|
id1: ID;
|
|
164
92
|
id1Type: string;
|
|
@@ -179,17 +107,6 @@ interface cursorOptions {
|
|
|
179
107
|
conv?: (any: any) => any;
|
|
180
108
|
}
|
|
181
109
|
export declare function getCursor(opts: cursorOptions): string;
|
|
182
|
-
export interface AssocEdgeInputOptions {
|
|
183
|
-
time?: Date;
|
|
184
|
-
data?: string | Builder<Ent>;
|
|
185
|
-
}
|
|
186
|
-
export interface AssocEdgeInput extends AssocEdgeInputOptions {
|
|
187
|
-
id1: ID;
|
|
188
|
-
id1Type: string;
|
|
189
|
-
edgeType: string;
|
|
190
|
-
id2: ID;
|
|
191
|
-
id2Type: string;
|
|
192
|
-
}
|
|
193
110
|
export declare class AssocEdgeData {
|
|
194
111
|
edgeType: string;
|
|
195
112
|
edgeName: string;
|