@snowtop/ent 0.1.0-alpha56 → 0.1.0-alpha58
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/orchestrator.js +21 -0
- package/core/base.d.ts +1 -1
- package/core/clause.d.ts +6 -3
- package/core/clause.js +39 -14
- package/core/config.d.ts +5 -2
- package/core/ent.d.ts +16 -3
- package/core/ent.js +147 -35
- package/core/loaders/assoc_count_loader.js +6 -1
- package/core/query/shared_assoc_test.d.ts +1 -1
- package/core/query/shared_assoc_test.js +17 -5
- package/core/query/shared_test.d.ts +3 -0
- package/core/query/shared_test.js +95 -17
- package/index.d.ts +1 -1
- package/index.js +3 -2
- package/package.json +1 -1
- package/parse_schema/parse.d.ts +8 -2
- package/parse_schema/parse.js +22 -2
- package/schema/index.d.ts +1 -1
- package/schema/schema.d.ts +15 -0
- package/scripts/custom_graphql.js +1 -1
- package/scripts/read_schema.js +10 -1
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +4 -2
- package/testutils/db/{test_db.js → temp_db.js} +16 -5
- package/testutils/fake_data/fake_contact.d.ts +1 -1
- package/testutils/fake_data/fake_contact.js +2 -2
- package/testutils/fake_data/fake_event.d.ts +1 -1
- package/testutils/fake_data/fake_event.js +3 -3
- package/testutils/fake_data/fake_user.d.ts +1 -1
- package/testutils/fake_data/fake_user.js +2 -2
- package/testutils/fake_data/test_helpers.d.ts +2 -2
- package/testutils/fake_data/test_helpers.js +5 -5
- package/testutils/parse_sql.js +4 -0
- package/testutils/test_edge_global_schema.d.ts +15 -0
- package/testutils/test_edge_global_schema.js +58 -0
- package/testutils/write.d.ts +2 -2
- package/testutils/write.js +3 -3
- package/tsc/ast.d.ts +1 -0
- package/tsc/ast.js +3 -0
package/action/orchestrator.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
2
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
23
|
};
|
|
@@ -11,6 +30,7 @@ const privacy_1 = require("../core/privacy");
|
|
|
11
30
|
const executor_1 = require("./executor");
|
|
12
31
|
const logger_1 = require("../core/logger");
|
|
13
32
|
const memoizee_1 = __importDefault(require("memoizee"));
|
|
33
|
+
const clause = __importStar(require("../core/clause"));
|
|
14
34
|
var edgeDirection;
|
|
15
35
|
(function (edgeDirection) {
|
|
16
36
|
edgeDirection[edgeDirection["inboundEdge"] = 0] = "inboundEdge";
|
|
@@ -159,6 +179,7 @@ class Orchestrator {
|
|
|
159
179
|
key: this.options.key,
|
|
160
180
|
loadEntOptions: this.options.loaderOptions,
|
|
161
181
|
placeholderID: this.options.builder.placeholderID,
|
|
182
|
+
whereClause: clause.Eq(this.options.key, this.existingEnt?.id),
|
|
162
183
|
};
|
|
163
184
|
if (this.logValues) {
|
|
164
185
|
opts.fieldsToLog = this.logValues;
|
package/core/base.d.ts
CHANGED
|
@@ -82,7 +82,7 @@ export interface CreateRowOptions extends DataOptions {
|
|
|
82
82
|
fieldsToLog?: Data;
|
|
83
83
|
}
|
|
84
84
|
export interface EditRowOptions extends CreateRowOptions {
|
|
85
|
-
|
|
85
|
+
whereClause: clause.Clause;
|
|
86
86
|
}
|
|
87
87
|
interface LoadableEntOptions<TEnt extends Ent, TViewer extends Viewer = Viewer> {
|
|
88
88
|
loaderFactory: LoaderFactory<any, Data | null>;
|
package/core/clause.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface Clause {
|
|
2
2
|
clause(idx: number): string;
|
|
3
|
+
columns(): string[];
|
|
3
4
|
values(): any[];
|
|
4
5
|
instanceKey(): string;
|
|
5
6
|
logValues(): any[];
|
|
@@ -12,10 +13,11 @@ declare class simpleClause implements Clause {
|
|
|
12
13
|
protected col: string;
|
|
13
14
|
private value;
|
|
14
15
|
private op;
|
|
15
|
-
private
|
|
16
|
-
constructor(col: string, value: any, op: string,
|
|
16
|
+
private handleNull?;
|
|
17
|
+
constructor(col: string, value: any, op: string, handleNull?: Clause | undefined);
|
|
17
18
|
clause(idx: number): string;
|
|
18
|
-
private
|
|
19
|
+
private nullClause;
|
|
20
|
+
columns(): string[];
|
|
19
21
|
values(): any[];
|
|
20
22
|
logValues(): any[];
|
|
21
23
|
instanceKey(): string;
|
|
@@ -25,6 +27,7 @@ declare class compositeClause implements Clause {
|
|
|
25
27
|
private sep;
|
|
26
28
|
constructor(clauses: Clause[], sep: string);
|
|
27
29
|
clause(idx: number): string;
|
|
30
|
+
columns(): string[];
|
|
28
31
|
values(): any[];
|
|
29
32
|
logValues(): any[];
|
|
30
33
|
instanceKey(): string;
|
package/core/clause.js
CHANGED
|
@@ -33,33 +33,33 @@ function rawValue(val) {
|
|
|
33
33
|
return val;
|
|
34
34
|
}
|
|
35
35
|
class simpleClause {
|
|
36
|
-
constructor(col, value, op,
|
|
36
|
+
constructor(col, value, op, handleNull) {
|
|
37
37
|
this.col = col;
|
|
38
38
|
this.value = value;
|
|
39
39
|
this.op = op;
|
|
40
|
-
this.
|
|
40
|
+
this.handleNull = handleNull;
|
|
41
41
|
}
|
|
42
42
|
clause(idx) {
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
return
|
|
43
|
+
const nullClause = this.nullClause();
|
|
44
|
+
if (nullClause) {
|
|
45
|
+
return nullClause.clause(idx);
|
|
46
46
|
}
|
|
47
47
|
if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
|
|
48
48
|
return `${this.col} ${this.op} $${idx}`;
|
|
49
49
|
}
|
|
50
50
|
return `${this.col} ${this.op} ?`;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
if (!this.
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (db_1.default.getDialect() !== db_1.Dialect.SQLite) {
|
|
52
|
+
nullClause() {
|
|
53
|
+
if (!this.handleNull || this.value !== null) {
|
|
57
54
|
return;
|
|
58
55
|
}
|
|
59
|
-
return this.
|
|
56
|
+
return this.handleNull;
|
|
57
|
+
}
|
|
58
|
+
columns() {
|
|
59
|
+
return [this.col];
|
|
60
60
|
}
|
|
61
61
|
values() {
|
|
62
|
-
const sqliteClause = this.
|
|
62
|
+
const sqliteClause = this.nullClause();
|
|
63
63
|
if (sqliteClause) {
|
|
64
64
|
return sqliteClause.values();
|
|
65
65
|
}
|
|
@@ -69,7 +69,7 @@ class simpleClause {
|
|
|
69
69
|
return [this.value];
|
|
70
70
|
}
|
|
71
71
|
logValues() {
|
|
72
|
-
const sqliteClause = this.
|
|
72
|
+
const sqliteClause = this.nullClause();
|
|
73
73
|
if (sqliteClause) {
|
|
74
74
|
return sqliteClause.logValues();
|
|
75
75
|
}
|
|
@@ -79,7 +79,7 @@ class simpleClause {
|
|
|
79
79
|
return [this.value];
|
|
80
80
|
}
|
|
81
81
|
instanceKey() {
|
|
82
|
-
const sqliteClause = this.
|
|
82
|
+
const sqliteClause = this.nullClause();
|
|
83
83
|
if (sqliteClause) {
|
|
84
84
|
return sqliteClause.instanceKey();
|
|
85
85
|
}
|
|
@@ -93,6 +93,9 @@ class isNullClause {
|
|
|
93
93
|
clause(idx) {
|
|
94
94
|
return `${this.col} IS NULL`;
|
|
95
95
|
}
|
|
96
|
+
columns() {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
96
99
|
values() {
|
|
97
100
|
return [];
|
|
98
101
|
}
|
|
@@ -110,6 +113,9 @@ class isNotNullClause {
|
|
|
110
113
|
clause(idx) {
|
|
111
114
|
return `${this.col} IS NOT NULL`;
|
|
112
115
|
}
|
|
116
|
+
columns() {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
113
119
|
values() {
|
|
114
120
|
return [];
|
|
115
121
|
}
|
|
@@ -132,6 +138,9 @@ class arraySimpleClause {
|
|
|
132
138
|
}
|
|
133
139
|
return `${this.col} ${this.op} ?`;
|
|
134
140
|
}
|
|
141
|
+
columns() {
|
|
142
|
+
return [this.col];
|
|
143
|
+
}
|
|
135
144
|
values() {
|
|
136
145
|
if (isSensitive(this.value)) {
|
|
137
146
|
return [this.value.value()];
|
|
@@ -163,6 +172,9 @@ class postgresArrayContains {
|
|
|
163
172
|
}
|
|
164
173
|
throw new Error(`not supported`);
|
|
165
174
|
}
|
|
175
|
+
columns() {
|
|
176
|
+
return [this.col];
|
|
177
|
+
}
|
|
166
178
|
values() {
|
|
167
179
|
if (isSensitive(this.value)) {
|
|
168
180
|
return [`{${this.value.value()}}`];
|
|
@@ -225,6 +237,9 @@ class inClause {
|
|
|
225
237
|
// or change to a sqlx.Rebind format
|
|
226
238
|
// here's what sqlx does: https://play.golang.org/p/vPzvYqeAcP0
|
|
227
239
|
}
|
|
240
|
+
columns() {
|
|
241
|
+
return [this.col];
|
|
242
|
+
}
|
|
228
243
|
values() {
|
|
229
244
|
const result = [];
|
|
230
245
|
for (const value of this.value) {
|
|
@@ -266,6 +281,13 @@ class compositeClause {
|
|
|
266
281
|
}
|
|
267
282
|
return clauses.join(this.sep);
|
|
268
283
|
}
|
|
284
|
+
columns() {
|
|
285
|
+
const ret = [];
|
|
286
|
+
for (const cls of this.clauses) {
|
|
287
|
+
ret.push(...cls.columns());
|
|
288
|
+
}
|
|
289
|
+
return ret;
|
|
290
|
+
}
|
|
269
291
|
values() {
|
|
270
292
|
let result = [];
|
|
271
293
|
for (const clause of this.clauses) {
|
|
@@ -315,6 +337,9 @@ class tsQueryClause {
|
|
|
315
337
|
// FYI this doesn't actually work for sqlite since different
|
|
316
338
|
return `${this.col} @@ ${this.getFunction()}('${language}', ?)`;
|
|
317
339
|
}
|
|
340
|
+
columns() {
|
|
341
|
+
return [this.col];
|
|
342
|
+
}
|
|
318
343
|
values() {
|
|
319
344
|
const { value } = this.getInfo();
|
|
320
345
|
return [value];
|
package/core/config.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface Config {
|
|
|
20
20
|
log?: logType | logType[];
|
|
21
21
|
codegen?: CodegenConfig;
|
|
22
22
|
customGraphQLJSONPath?: string;
|
|
23
|
+
globalSchemaPath?: string;
|
|
23
24
|
}
|
|
24
25
|
interface CodegenConfig {
|
|
25
26
|
defaultEntPolicy?: PrivacyConfig;
|
|
@@ -35,7 +36,8 @@ interface CodegenConfig {
|
|
|
35
36
|
schemaSQLFilePath?: boolean;
|
|
36
37
|
databaseToCompareTo?: string;
|
|
37
38
|
fieldPrivacyEvaluated?: fieldPrivacyEvaluated;
|
|
38
|
-
templatizedViewer?:
|
|
39
|
+
templatizedViewer?: importedObject;
|
|
40
|
+
customAssocEdgePath?: importedObject;
|
|
39
41
|
}
|
|
40
42
|
interface PrettierConfig {
|
|
41
43
|
custom?: boolean;
|
|
@@ -46,9 +48,10 @@ interface PrivacyConfig {
|
|
|
46
48
|
policyName: string;
|
|
47
49
|
class?: boolean;
|
|
48
50
|
}
|
|
49
|
-
interface
|
|
51
|
+
interface importedObject {
|
|
50
52
|
path: string;
|
|
51
53
|
name: string;
|
|
54
|
+
alias?: string;
|
|
52
55
|
}
|
|
53
56
|
export declare function loadConfig(file?: string | Buffer | Config): void;
|
|
54
57
|
export {};
|
package/core/ent.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Executor } from "../action/action";
|
|
|
4
4
|
import * as clause from "./clause";
|
|
5
5
|
import { Builder } from "../action";
|
|
6
6
|
import DataLoader from "dataloader";
|
|
7
|
+
import { GlobalSchema } from "../schema/";
|
|
7
8
|
export declare function loadEnt<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
|
|
8
9
|
export declare function loadEntViaKey<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, key: any, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
|
|
9
10
|
export declare function loadEntX<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt>;
|
|
@@ -52,6 +53,7 @@ export interface EditNodeOptions<T extends Ent> extends EditRowOptions {
|
|
|
52
53
|
fieldsToResolve: string[];
|
|
53
54
|
loadEntOptions: LoadEntOptions<T>;
|
|
54
55
|
placeholderID?: ID;
|
|
56
|
+
key: string;
|
|
55
57
|
}
|
|
56
58
|
export declare class EditNodeOperation<T extends Ent> implements DataOperation {
|
|
57
59
|
options: EditNodeOptions<T>;
|
|
@@ -67,7 +69,11 @@ export declare class EditNodeOperation<T extends Ent> implements DataOperation {
|
|
|
67
69
|
returnedRow(): Data | null;
|
|
68
70
|
createdEnt(viewer: Viewer): T | null;
|
|
69
71
|
}
|
|
72
|
+
export declare function setGlobalSchema(val: GlobalSchema): void;
|
|
73
|
+
export declare function clearGlobalSchema(): void;
|
|
74
|
+
export declare function __hasGlobalSchema(): boolean;
|
|
70
75
|
export declare class EdgeOperation implements DataOperation {
|
|
76
|
+
private builder;
|
|
71
77
|
edgeInput: AssocEdgeInput;
|
|
72
78
|
private options;
|
|
73
79
|
private edgeData;
|
|
@@ -96,9 +102,9 @@ export declare class EdgeOperation implements DataOperation {
|
|
|
96
102
|
export declare function buildInsertQuery(options: CreateRowOptions, suffix?: string): [string, string[], string[]];
|
|
97
103
|
export declare function createRow(queryer: Queryer, options: CreateRowOptions, suffix: string): Promise<Data | null>;
|
|
98
104
|
export declare function createRowSync(queryer: SyncQueryer, options: CreateRowOptions, suffix: string): Data | null;
|
|
99
|
-
export declare function buildUpdateQuery(options: EditRowOptions,
|
|
100
|
-
export declare function editRow(queryer: Queryer, options: EditRowOptions,
|
|
101
|
-
export declare function editRowSync(queryer: SyncQueryer, options: EditRowOptions,
|
|
105
|
+
export declare function buildUpdateQuery(options: EditRowOptions, suffix?: string): [string, any[], any[]];
|
|
106
|
+
export declare function editRow(queryer: Queryer, options: EditRowOptions, suffix?: string): Promise<Data | null>;
|
|
107
|
+
export declare function editRowSync(queryer: SyncQueryer, options: EditRowOptions, suffix?: string): Data | null;
|
|
102
108
|
export declare function deleteRows(queryer: Queryer, options: DataOptions, cls: clause.Clause): Promise<void>;
|
|
103
109
|
export declare function deleteRowsSync(queryer: SyncQueryer, options: DataOptions, cls: clause.Clause): void;
|
|
104
110
|
export declare class DeleteNodeOperation implements DataOperation {
|
|
@@ -116,7 +122,9 @@ export declare class AssocEdge {
|
|
|
116
122
|
id2Type: string;
|
|
117
123
|
time: Date;
|
|
118
124
|
data?: string | null;
|
|
125
|
+
private rawData;
|
|
119
126
|
constructor(data: Data);
|
|
127
|
+
__getRawData(): Data;
|
|
120
128
|
getCursor(): string;
|
|
121
129
|
}
|
|
122
130
|
interface cursorOptions {
|
|
@@ -156,6 +164,7 @@ interface loadEdgesOptions {
|
|
|
156
164
|
edgeType: string;
|
|
157
165
|
context?: Context;
|
|
158
166
|
queryOptions?: EdgeQueryableDataOptions;
|
|
167
|
+
disableTransformations?: boolean;
|
|
159
168
|
}
|
|
160
169
|
interface loadCustomEdgesOptions<T extends AssocEdge> extends loadEdgesOptions {
|
|
161
170
|
ctr: AssocEdgeConstructor<T>;
|
|
@@ -163,6 +172,10 @@ interface loadCustomEdgesOptions<T extends AssocEdge> extends loadEdgesOptions {
|
|
|
163
172
|
export declare const DefaultLimit = 1000;
|
|
164
173
|
export declare function defaultEdgeQueryOptions(id1: ID, edgeType: string): EdgeQueryableDataOptions;
|
|
165
174
|
export declare function loadEdges(options: loadEdgesOptions): Promise<AssocEdge[]>;
|
|
175
|
+
export declare function getEdgeClauseAndFields(cls: clause.Clause, options: loadEdgesOptions): {
|
|
176
|
+
cls: clause.Clause;
|
|
177
|
+
fields: string[];
|
|
178
|
+
};
|
|
166
179
|
export declare function loadCustomEdges<T extends AssocEdge>(options: loadCustomEdgesOptions<T>): Promise<T[]>;
|
|
167
180
|
export declare function loadUniqueEdge(options: loadEdgesOptions): Promise<AssocEdge | null>;
|
|
168
181
|
export declare function loadUniqueNode<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id1: ID, edgeType: string, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
|
package/core/ent.js
CHANGED
|
@@ -22,13 +22,15 @@ 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.
|
|
25
|
+
exports.applyPrivacyPolicyForRow = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadCustomEdges = exports.getEdgeClauseAndFields = exports.loadEdges = exports.defaultEdgeQueryOptions = exports.DefaultLimit = exports.loadEdgeDatas = exports.loadEdgeData = exports.assocEdgeLoader = exports.AssocEdgeData = exports.getCursor = exports.AssocEdge = exports.DeleteNodeOperation = exports.deleteRowsSync = exports.deleteRows = exports.editRowSync = exports.editRow = exports.buildUpdateQuery = exports.createRowSync = exports.createRow = exports.buildInsertQuery = exports.EdgeOperation = exports.__hasGlobalSchema = exports.clearGlobalSchema = exports.setGlobalSchema = exports.EditNodeOperation = exports.buildGroupQuery = exports.buildQuery = exports.loadRows = exports.performRawQuery = exports.loadRow = exports.loadRowX = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEntsList = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
|
|
26
|
+
exports.getEdgeTypeInGroup = exports.applyPrivacyPolicyForRows = exports.applyPrivacyPolicyForRowX = void 0;
|
|
26
27
|
const db_1 = __importStar(require("./db"));
|
|
27
28
|
const privacy_1 = require("./privacy");
|
|
28
29
|
const clause = __importStar(require("./clause"));
|
|
29
30
|
const action_1 = require("../action");
|
|
30
31
|
const logger_1 = require("./logger");
|
|
31
32
|
const dataloader_1 = __importDefault(require("dataloader"));
|
|
33
|
+
const schema_1 = require("../schema/");
|
|
32
34
|
// TODO kill this and createDataLoader
|
|
33
35
|
class cacheMap {
|
|
34
36
|
constructor(options) {
|
|
@@ -473,7 +475,7 @@ class EditNodeOperation {
|
|
|
473
475
|
if (this.hasData(options.fields)) {
|
|
474
476
|
// even this with returning * may not always work if transformed...
|
|
475
477
|
// we can have a transformed flag to see if it should be returned?
|
|
476
|
-
this.row = await editRow(queryer, options,
|
|
478
|
+
this.row = await editRow(queryer, options, "RETURNING *");
|
|
477
479
|
}
|
|
478
480
|
else {
|
|
479
481
|
// @ts-ignore
|
|
@@ -523,7 +525,7 @@ class EditNodeOperation {
|
|
|
523
525
|
};
|
|
524
526
|
if (this.existingEnt) {
|
|
525
527
|
if (this.hasData(this.options.fields)) {
|
|
526
|
-
editRowSync(queryer, options,
|
|
528
|
+
editRowSync(queryer, options, "RETURNING *");
|
|
527
529
|
this.reloadRow(queryer, this.existingEnt.id, options);
|
|
528
530
|
}
|
|
529
531
|
else {
|
|
@@ -548,8 +550,23 @@ class EditNodeOperation {
|
|
|
548
550
|
}
|
|
549
551
|
}
|
|
550
552
|
exports.EditNodeOperation = EditNodeOperation;
|
|
553
|
+
let globalSchema;
|
|
554
|
+
function setGlobalSchema(val) {
|
|
555
|
+
globalSchema = val;
|
|
556
|
+
}
|
|
557
|
+
exports.setGlobalSchema = setGlobalSchema;
|
|
558
|
+
function clearGlobalSchema() {
|
|
559
|
+
globalSchema = undefined;
|
|
560
|
+
}
|
|
561
|
+
exports.clearGlobalSchema = clearGlobalSchema;
|
|
562
|
+
// used by tests. no guarantee will always exist
|
|
563
|
+
function __hasGlobalSchema() {
|
|
564
|
+
return globalSchema !== undefined;
|
|
565
|
+
}
|
|
566
|
+
exports.__hasGlobalSchema = __hasGlobalSchema;
|
|
551
567
|
class EdgeOperation {
|
|
552
|
-
constructor(edgeInput, options) {
|
|
568
|
+
constructor(builder, edgeInput, options) {
|
|
569
|
+
this.builder = builder;
|
|
553
570
|
this.edgeInput = edgeInput;
|
|
554
571
|
this.options = options;
|
|
555
572
|
}
|
|
@@ -585,7 +602,31 @@ class EdgeOperation {
|
|
|
585
602
|
}
|
|
586
603
|
}
|
|
587
604
|
getDeleteRowParams(edgeData, edge, context) {
|
|
605
|
+
let transformed = null;
|
|
606
|
+
let op = schema_1.SQLStatementOperation.Delete;
|
|
607
|
+
let updateData = null;
|
|
608
|
+
// TODO respect disableTransformations
|
|
609
|
+
if (globalSchema?.transformEdgeWrite) {
|
|
610
|
+
transformed = globalSchema.transformEdgeWrite({
|
|
611
|
+
op: schema_1.SQLStatementOperation.Delete,
|
|
612
|
+
edge,
|
|
613
|
+
});
|
|
614
|
+
if (transformed) {
|
|
615
|
+
op = transformed.op;
|
|
616
|
+
if (transformed.op === schema_1.SQLStatementOperation.Insert) {
|
|
617
|
+
throw new Error(`cannot currently transform a delete into an insert`);
|
|
618
|
+
}
|
|
619
|
+
if (transformed.op === schema_1.SQLStatementOperation.Update) {
|
|
620
|
+
if (!transformed.data) {
|
|
621
|
+
throw new Error(`cannot transform a delete into an update without providing data`);
|
|
622
|
+
}
|
|
623
|
+
updateData = transformed.data;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
588
627
|
return {
|
|
628
|
+
op,
|
|
629
|
+
updateData,
|
|
589
630
|
options: {
|
|
590
631
|
tableName: edgeData.edgeTable,
|
|
591
632
|
context,
|
|
@@ -595,11 +636,35 @@ class EdgeOperation {
|
|
|
595
636
|
}
|
|
596
637
|
async performDeleteWrite(q, edgeData, edge, context) {
|
|
597
638
|
const params = this.getDeleteRowParams(edgeData, edge, context);
|
|
598
|
-
|
|
639
|
+
if (params.op === schema_1.SQLStatementOperation.Delete) {
|
|
640
|
+
return deleteRows(q, params.options, params.clause);
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
if (params.op !== schema_1.SQLStatementOperation.Update) {
|
|
644
|
+
throw new Error(`invalid operation ${params.op}`);
|
|
645
|
+
}
|
|
646
|
+
await editRow(q, {
|
|
647
|
+
tableName: params.options.tableName,
|
|
648
|
+
whereClause: params.clause,
|
|
649
|
+
fields: params.updateData,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
599
652
|
}
|
|
600
653
|
performDeleteWriteSync(q, edgeData, edge, context) {
|
|
601
654
|
const params = this.getDeleteRowParams(edgeData, edge, context);
|
|
602
|
-
|
|
655
|
+
if (params.op === schema_1.SQLStatementOperation.Delete) {
|
|
656
|
+
return deleteRowsSync(q, params.options, params.clause);
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
if (params.op !== schema_1.SQLStatementOperation.Update) {
|
|
660
|
+
throw new Error(`invalid operation ${params.op}`);
|
|
661
|
+
}
|
|
662
|
+
editRowSync(q, {
|
|
663
|
+
tableName: params.options.tableName,
|
|
664
|
+
whereClause: params.clause,
|
|
665
|
+
fields: params.updateData,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
603
668
|
}
|
|
604
669
|
getInsertRowParams(edgeData, edge, context) {
|
|
605
670
|
const fields = {
|
|
@@ -618,6 +683,30 @@ class EdgeOperation {
|
|
|
618
683
|
// maybe when actions exist?
|
|
619
684
|
fields["time"] = new Date().toISOString();
|
|
620
685
|
}
|
|
686
|
+
const onConflictFields = ["data"];
|
|
687
|
+
if (globalSchema?.extraEdgeFields) {
|
|
688
|
+
for (const name in globalSchema.extraEdgeFields) {
|
|
689
|
+
const f = globalSchema.extraEdgeFields[name];
|
|
690
|
+
if (f.defaultValueOnCreate) {
|
|
691
|
+
const storageKey = (0, schema_1.getStorageKey)(f, name);
|
|
692
|
+
fields[storageKey] = f.defaultValueOnCreate(this.builder, {});
|
|
693
|
+
// onconflict make sure we override the default values
|
|
694
|
+
// e.g. setting deleted_at = null for soft delete
|
|
695
|
+
onConflictFields.push(storageKey);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
// TODO respect disableTransformations
|
|
700
|
+
let transformed = null;
|
|
701
|
+
if (globalSchema?.transformEdgeWrite) {
|
|
702
|
+
transformed = globalSchema.transformEdgeWrite({
|
|
703
|
+
op: schema_1.SQLStatementOperation.Insert,
|
|
704
|
+
edge,
|
|
705
|
+
});
|
|
706
|
+
if (transformed) {
|
|
707
|
+
throw new Error(`transforming an insert edge not currently supported`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
621
710
|
return [
|
|
622
711
|
{
|
|
623
712
|
tableName: edgeData.edgeTable,
|
|
@@ -625,7 +714,9 @@ class EdgeOperation {
|
|
|
625
714
|
fieldsToLog: fields,
|
|
626
715
|
context,
|
|
627
716
|
},
|
|
628
|
-
|
|
717
|
+
`ON CONFLICT(id1, edge_type, id2) DO UPDATE SET ${onConflictFields
|
|
718
|
+
.map((f) => `${f} = EXCLUDED.${f}`)
|
|
719
|
+
.join(", ")}`,
|
|
629
720
|
];
|
|
630
721
|
}
|
|
631
722
|
async performInsertWrite(q, edgeData, edge, context) {
|
|
@@ -662,7 +753,7 @@ class EdgeOperation {
|
|
|
662
753
|
}
|
|
663
754
|
}
|
|
664
755
|
symmetricEdge() {
|
|
665
|
-
return new EdgeOperation({
|
|
756
|
+
return new EdgeOperation(this.builder, {
|
|
666
757
|
id1: this.edgeInput.id2,
|
|
667
758
|
id1Type: this.edgeInput.id2Type,
|
|
668
759
|
id2: this.edgeInput.id1,
|
|
@@ -678,7 +769,7 @@ class EdgeOperation {
|
|
|
678
769
|
});
|
|
679
770
|
}
|
|
680
771
|
inverseEdge(edgeData) {
|
|
681
|
-
return new EdgeOperation({
|
|
772
|
+
return new EdgeOperation(this.builder, {
|
|
682
773
|
id1: this.edgeInput.id2,
|
|
683
774
|
id1Type: this.edgeInput.id2Type,
|
|
684
775
|
id2: this.edgeInput.id1,
|
|
@@ -746,7 +837,7 @@ class EdgeOperation {
|
|
|
746
837
|
if (data) {
|
|
747
838
|
edge.data = data;
|
|
748
839
|
}
|
|
749
|
-
return new EdgeOperation(edge, {
|
|
840
|
+
return new EdgeOperation(builder, edge, {
|
|
750
841
|
operation: action_1.WriteOperation.Insert,
|
|
751
842
|
id2Placeholder,
|
|
752
843
|
id1Placeholder,
|
|
@@ -767,7 +858,7 @@ class EdgeOperation {
|
|
|
767
858
|
if (data) {
|
|
768
859
|
edge.data = data;
|
|
769
860
|
}
|
|
770
|
-
return new EdgeOperation(edge, {
|
|
861
|
+
return new EdgeOperation(builder, edge, {
|
|
771
862
|
operation: action_1.WriteOperation.Insert,
|
|
772
863
|
id1Placeholder,
|
|
773
864
|
id2Placeholder,
|
|
@@ -785,7 +876,7 @@ class EdgeOperation {
|
|
|
785
876
|
id2Type: "",
|
|
786
877
|
id1Type: "",
|
|
787
878
|
};
|
|
788
|
-
return new EdgeOperation(edge, {
|
|
879
|
+
return new EdgeOperation(builder, edge, {
|
|
789
880
|
operation: action_1.WriteOperation.Delete,
|
|
790
881
|
});
|
|
791
882
|
}
|
|
@@ -800,7 +891,7 @@ class EdgeOperation {
|
|
|
800
891
|
id2Type: "",
|
|
801
892
|
id1Type: "",
|
|
802
893
|
};
|
|
803
|
-
return new EdgeOperation(edge, {
|
|
894
|
+
return new EdgeOperation(builder, edge, {
|
|
804
895
|
operation: action_1.WriteOperation.Delete,
|
|
805
896
|
});
|
|
806
897
|
}
|
|
@@ -897,43 +988,42 @@ function createRowSync(queryer, options, suffix) {
|
|
|
897
988
|
return null;
|
|
898
989
|
}
|
|
899
990
|
exports.createRowSync = createRowSync;
|
|
900
|
-
function buildUpdateQuery(options,
|
|
991
|
+
function buildUpdateQuery(options, suffix) {
|
|
901
992
|
let valsString = [];
|
|
902
993
|
let values = [];
|
|
903
994
|
let logValues = [];
|
|
904
995
|
const dialect = db_1.default.getDialect();
|
|
905
996
|
let idx = 1;
|
|
906
997
|
for (const key in options.fields) {
|
|
907
|
-
|
|
998
|
+
const val = options.fields[key];
|
|
999
|
+
values.push(val);
|
|
908
1000
|
if (options.fieldsToLog) {
|
|
909
1001
|
logValues.push(options.fieldsToLog[key]);
|
|
910
1002
|
}
|
|
1003
|
+
// TODO would be nice to use clause here. need update version of the queries so that
|
|
1004
|
+
// we don't have to handle dialect specifics here
|
|
1005
|
+
// can't use clause because of IS NULL
|
|
1006
|
+
// valsString.push(clause.Eq(key, val).clause(idx));
|
|
911
1007
|
if (dialect === db_1.Dialect.Postgres) {
|
|
912
1008
|
valsString.push(`${key} = $${idx}`);
|
|
913
|
-
idx++;
|
|
914
1009
|
}
|
|
915
1010
|
else {
|
|
916
1011
|
valsString.push(`${key} = ?`);
|
|
917
1012
|
}
|
|
1013
|
+
idx++;
|
|
918
1014
|
}
|
|
919
1015
|
const vals = valsString.join(", ");
|
|
920
1016
|
let query = `UPDATE ${options.tableName} SET ${vals} WHERE `;
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
924
|
-
else {
|
|
925
|
-
query = query + `${options.key} = ?`;
|
|
926
|
-
}
|
|
1017
|
+
query = query + options.whereClause.clause(idx);
|
|
1018
|
+
values.push(...options.whereClause.values());
|
|
927
1019
|
if (suffix) {
|
|
928
1020
|
query = query + " " + suffix;
|
|
929
1021
|
}
|
|
930
1022
|
return [query, values, logValues];
|
|
931
1023
|
}
|
|
932
1024
|
exports.buildUpdateQuery = buildUpdateQuery;
|
|
933
|
-
async function editRow(queryer, options,
|
|
934
|
-
const [query, values, logValues] = buildUpdateQuery(options,
|
|
935
|
-
// add id as value to prepared query
|
|
936
|
-
values.push(id);
|
|
1025
|
+
async function editRow(queryer, options, suffix) {
|
|
1026
|
+
const [query, values, logValues] = buildUpdateQuery(options, suffix);
|
|
937
1027
|
const res = await mutateRow(queryer, query, values, logValues, options);
|
|
938
1028
|
if (res?.rowCount == 1) {
|
|
939
1029
|
// for now assume id primary key
|
|
@@ -944,10 +1034,8 @@ async function editRow(queryer, options, id, suffix) {
|
|
|
944
1034
|
return null;
|
|
945
1035
|
}
|
|
946
1036
|
exports.editRow = editRow;
|
|
947
|
-
function editRowSync(queryer, options,
|
|
948
|
-
const [query, values, logValues] = buildUpdateQuery(options,
|
|
949
|
-
// add id as value to prepared query
|
|
950
|
-
values.push(id);
|
|
1037
|
+
function editRowSync(queryer, options, suffix) {
|
|
1038
|
+
const [query, values, logValues] = buildUpdateQuery(options, suffix);
|
|
951
1039
|
const res = mutateRowSync(queryer, query, values, logValues, options);
|
|
952
1040
|
if (res?.rowCount == 1) {
|
|
953
1041
|
// for now assume id primary key
|
|
@@ -998,6 +1086,12 @@ class AssocEdge {
|
|
|
998
1086
|
this.edgeType = data.edge_type;
|
|
999
1087
|
this.time = data.time;
|
|
1000
1088
|
this.data = data.data;
|
|
1089
|
+
this.rawData = data;
|
|
1090
|
+
}
|
|
1091
|
+
__getRawData() {
|
|
1092
|
+
// incase there's extra db fields. useful for tests
|
|
1093
|
+
// in production, a subclass of this should be in use so we won't need this...
|
|
1094
|
+
return this.rawData;
|
|
1001
1095
|
}
|
|
1002
1096
|
getCursor() {
|
|
1003
1097
|
return getCursor({
|
|
@@ -1104,6 +1198,21 @@ async function loadEdges(options) {
|
|
|
1104
1198
|
return loadCustomEdges({ ...options, ctr: AssocEdge });
|
|
1105
1199
|
}
|
|
1106
1200
|
exports.loadEdges = loadEdges;
|
|
1201
|
+
function getEdgeClauseAndFields(cls, options) {
|
|
1202
|
+
let fields = edgeFields;
|
|
1203
|
+
if (globalSchema?.transformEdgeRead) {
|
|
1204
|
+
const transformClause = globalSchema.transformEdgeRead();
|
|
1205
|
+
if (!options.disableTransformations) {
|
|
1206
|
+
cls = clause.And(cls, transformClause);
|
|
1207
|
+
}
|
|
1208
|
+
fields = edgeFields.concat(transformClause.columns());
|
|
1209
|
+
}
|
|
1210
|
+
return {
|
|
1211
|
+
cls,
|
|
1212
|
+
fields,
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
exports.getEdgeClauseAndFields = getEdgeClauseAndFields;
|
|
1107
1216
|
async function loadCustomEdges(options) {
|
|
1108
1217
|
const { id1, edgeType, context } = options;
|
|
1109
1218
|
const edgeData = await loadEdgeData(edgeType);
|
|
@@ -1115,10 +1224,11 @@ async function loadCustomEdges(options) {
|
|
|
1115
1224
|
if (options.queryOptions?.clause) {
|
|
1116
1225
|
cls = clause.And(cls, options.queryOptions.clause);
|
|
1117
1226
|
}
|
|
1227
|
+
const { cls: actualClause, fields } = getEdgeClauseAndFields(cls, options);
|
|
1118
1228
|
const rows = await loadRows({
|
|
1119
1229
|
tableName: edgeData.edgeTable,
|
|
1120
|
-
fields:
|
|
1121
|
-
clause:
|
|
1230
|
+
fields: fields,
|
|
1231
|
+
clause: actualClause,
|
|
1122
1232
|
orderby: options.queryOptions?.orderby || defaultOptions.orderby,
|
|
1123
1233
|
limit: options.queryOptions?.limit || defaultOptions.limit,
|
|
1124
1234
|
context,
|
|
@@ -1134,10 +1244,11 @@ async function loadUniqueEdge(options) {
|
|
|
1134
1244
|
if (!edgeData) {
|
|
1135
1245
|
throw new Error(`error loading edge data for ${edgeType}`);
|
|
1136
1246
|
}
|
|
1247
|
+
const { cls, fields } = getEdgeClauseAndFields(clause.And(clause.Eq("id1", id1), clause.Eq("edge_type", edgeType)), options);
|
|
1137
1248
|
const row = await loadRow({
|
|
1138
1249
|
tableName: edgeData.edgeTable,
|
|
1139
|
-
fields:
|
|
1140
|
-
clause:
|
|
1250
|
+
fields: fields,
|
|
1251
|
+
clause: cls,
|
|
1141
1252
|
context,
|
|
1142
1253
|
});
|
|
1143
1254
|
if (!row) {
|
|
@@ -1164,11 +1275,12 @@ async function loadRawEdgeCountX(options) {
|
|
|
1164
1275
|
if (!edgeData) {
|
|
1165
1276
|
throw new Error(`error loading edge data for ${edgeType}`);
|
|
1166
1277
|
}
|
|
1278
|
+
const { cls } = getEdgeClauseAndFields(clause.And(clause.Eq("id1", id1), clause.Eq("edge_type", edgeType)), options);
|
|
1167
1279
|
const row = await loadRowX({
|
|
1168
1280
|
tableName: edgeData.edgeTable,
|
|
1169
1281
|
// sqlite needs as count otherwise it returns count(1)
|
|
1170
1282
|
fields: ["count(1) as count"],
|
|
1171
|
-
clause:
|
|
1283
|
+
clause: cls,
|
|
1172
1284
|
context,
|
|
1173
1285
|
});
|
|
1174
1286
|
return parseInt(row["count"], 10) || 0;
|