@snowtop/ent 0.1.0-alpha95 → 0.1.0-alpha96
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 +3 -3
- package/action/executor.js +6 -1
- package/action/experimental_action.d.ts +5 -2
- package/action/experimental_action.js +15 -12
- package/action/index.d.ts +2 -0
- package/action/index.js +7 -1
- package/action/orchestrator.d.ts +4 -2
- package/action/orchestrator.js +6 -0
- package/action/relative_value.d.ts +47 -0
- package/action/relative_value.js +125 -0
- package/action/transaction.d.ts +10 -0
- package/action/transaction.js +23 -0
- package/auth/auth.d.ts +1 -1
- package/core/base.d.ts +4 -2
- package/core/clause.d.ts +6 -1
- package/core/clause.js +25 -4
- package/core/config.d.ts +2 -1
- package/core/config.js +2 -0
- package/core/date.js +1 -5
- package/core/db.d.ts +9 -6
- package/core/db.js +14 -6
- package/core/ent.d.ts +3 -1
- package/core/ent.js +76 -26
- package/core/logger.d.ts +1 -1
- package/core/query/assoc_query.d.ts +2 -2
- package/core/query/shared_assoc_test.js +1 -2
- package/core/query/shared_test.js +0 -1
- package/graphql/graphql.d.ts +6 -6
- package/graphql/graphql.js +1 -0
- package/graphql/query/connection_type.d.ts +1 -1
- package/graphql/query/shared_assoc_test.js +1 -1
- package/graphql/query/shared_edge_connection.js +0 -4
- package/imports/index.d.ts +6 -1
- package/imports/index.js +14 -3
- package/index.d.ts +1 -0
- package/package.json +16 -16
- package/parse_schema/parse.d.ts +7 -7
- package/schema/base_schema.d.ts +3 -3
- package/schema/field.js +2 -2
- package/schema/schema.d.ts +11 -10
- package/schema/schema.js +3 -13
- package/scripts/custom_graphql.js +30 -4
- package/testutils/action/complex_schemas.d.ts +69 -0
- package/testutils/action/complex_schemas.js +398 -0
- package/testutils/builder.d.ts +21 -36
- package/testutils/builder.js +39 -45
- package/testutils/db/temp_db.d.ts +6 -3
- package/testutils/db/temp_db.js +79 -7
- package/testutils/db/value.d.ts +1 -0
- package/testutils/db/value.js +2 -2
- package/testutils/db_mock.d.ts +16 -4
- package/testutils/db_mock.js +48 -5
- package/testutils/ent-graphql-tests/index.d.ts +7 -1
- package/testutils/ent-graphql-tests/index.js +17 -5
- package/testutils/fake_data/fake_contact.d.ts +1 -0
- package/testutils/fake_data/fake_contact.js +6 -5
- package/testutils/fake_data/fake_event.d.ts +1 -0
- package/testutils/fake_data/fake_event.js +4 -3
- package/testutils/fake_data/fake_tag.d.ts +2 -1
- package/testutils/fake_data/fake_tag.js +6 -5
- package/testutils/fake_data/fake_user.d.ts +2 -1
- package/testutils/fake_data/fake_user.js +14 -13
- package/tsc/ast.d.ts +1 -1
package/action/action.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { Queryer } from "../core/db";
|
|
|
4
4
|
import { TransformedUpdateOperation, UpdateOperation } from "../schema";
|
|
5
5
|
import { FieldInfoMap } from "../schema/schema";
|
|
6
6
|
export { WriteOperation };
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
type MaybeNull<T extends Ent> = T | null;
|
|
8
|
+
type TMaybleNullableEnt<T extends Ent> = T | MaybeNull<T>;
|
|
9
9
|
interface BuilderOrchestrator {
|
|
10
10
|
__getOptions(): {
|
|
11
11
|
fieldInfo: FieldInfoMap;
|
|
@@ -38,7 +38,7 @@ export interface Changeset {
|
|
|
38
38
|
changesets?: Changeset[];
|
|
39
39
|
dependencies?: Map<ID, Builder<Ent>>;
|
|
40
40
|
}
|
|
41
|
-
export
|
|
41
|
+
export type TriggerReturn = void | Promise<Changeset | void | (Changeset | void)[]> | Promise<Changeset>[];
|
|
42
42
|
export interface Trigger<TEnt extends Ent<TViewer>, TBuilder extends Builder<TEnt, TViewer, TExistingEnt>, TViewer extends Viewer = Viewer, TInput extends Data = Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> {
|
|
43
43
|
changeset(builder: TBuilder, input: TInput): TriggerReturn;
|
|
44
44
|
}
|
package/action/executor.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.executeOperations = exports.ComplexExecutor = exports.ListBasedExecutor = void 0;
|
|
7
7
|
const graph_data_structure_1 = __importDefault(require("graph-data-structure"));
|
|
8
|
+
const ent_1 = require("../core/ent");
|
|
8
9
|
const db_1 = __importDefault(require("../core/db"));
|
|
9
10
|
const logger_1 = require("../core/logger");
|
|
10
11
|
// private to ent
|
|
@@ -98,7 +99,7 @@ class ComplexExecutor {
|
|
|
98
99
|
changesetMap.set(c.placeholderID.toString(), c);
|
|
99
100
|
graph.addNode(c.placeholderID.toString());
|
|
100
101
|
if (c.dependencies) {
|
|
101
|
-
for (let [
|
|
102
|
+
for (let [_, builder] of c.dependencies) {
|
|
102
103
|
// dependency should go first...
|
|
103
104
|
graph.addEdge(builder.placeholderID.toString(), c.placeholderID.toString(), 1);
|
|
104
105
|
}
|
|
@@ -258,6 +259,7 @@ async function executeOperations(executor, context, trackOps) {
|
|
|
258
259
|
});
|
|
259
260
|
}
|
|
260
261
|
else {
|
|
262
|
+
(0, ent_1.logQuery)("BEGIN", []);
|
|
261
263
|
await client.query("BEGIN");
|
|
262
264
|
for (const operation of executor) {
|
|
263
265
|
if (trackOps) {
|
|
@@ -269,6 +271,7 @@ async function executeOperations(executor, context, trackOps) {
|
|
|
269
271
|
}
|
|
270
272
|
await operation.performWrite(client, context);
|
|
271
273
|
}
|
|
274
|
+
(0, ent_1.logQuery)("COMMIT", []);
|
|
272
275
|
await client.query("COMMIT");
|
|
273
276
|
}
|
|
274
277
|
if (executor.postFetch) {
|
|
@@ -280,6 +283,8 @@ async function executeOperations(executor, context, trackOps) {
|
|
|
280
283
|
}
|
|
281
284
|
catch (e) {
|
|
282
285
|
if (!isSyncClient(client)) {
|
|
286
|
+
// TODO these changes break tests
|
|
287
|
+
(0, ent_1.logQuery)("ROLLBACK", []);
|
|
283
288
|
await client.query("ROLLBACK");
|
|
284
289
|
}
|
|
285
290
|
(0, logger_1.log)("error", e);
|
|
@@ -6,8 +6,8 @@ export interface ActionOptions<TEnt extends Ent<TViewer>, TViewer extends Viewer
|
|
|
6
6
|
input?: TData;
|
|
7
7
|
operation?: WriteOperation;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
type MaybeNull<T extends Ent> = T | null;
|
|
10
|
+
type TMaybleNullableEnt<T extends Ent> = T | MaybeNull<T>;
|
|
11
11
|
export interface EntBuilder<TEnt extends Ent<TViewer>, TViewer extends Viewer, TInput extends Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> extends Builder<TEnt, TViewer, TExistingEnt> {
|
|
12
12
|
valid(): Promise<boolean>;
|
|
13
13
|
validX(): Promise<void>;
|
|
@@ -29,6 +29,9 @@ export declare class BaseAction<TEnt extends Ent<TViewer>, TViewer extends Viewe
|
|
|
29
29
|
getValidators(): Validator<TEnt, EntBuilder<TEnt, TViewer, TInput, TExistingEnt>, TViewer, TInput, TExistingEnt>[];
|
|
30
30
|
constructor(viewer: TViewer, builderCtr: BuilderConstructor<TEnt, TViewer, TInput, TExistingEnt>, options: ActionOptions<TEnt, TViewer, TInput, TExistingEnt>);
|
|
31
31
|
static createBuilder<TEnt extends Ent<TViewer>, TViewer extends Viewer, TInput extends Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt, TViewer, TInput, TExistingEnt>, options: ActionOptions<TEnt, TViewer, TInput, TExistingEnt>): Builder<TEnt>;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated use Transaction
|
|
34
|
+
*/
|
|
32
35
|
static bulkAction<TEnt extends Ent<TViewer>, TViewer extends Viewer, TInput extends Data>(ent: TEnt, builderCtr: BuilderConstructor<TEnt, TViewer, TInput, TEnt>, ...actions: Action<Ent, Builder<Ent, any>>[]): BaseAction<TEnt, TViewer, TInput, TEnt>;
|
|
33
36
|
changeset(): Promise<Changeset>;
|
|
34
37
|
valid(): Promise<boolean>;
|
|
@@ -4,6 +4,18 @@ exports.getSimpleInsertAction = exports.getSimpleDeleteAction = exports.getSimpl
|
|
|
4
4
|
const privacy_1 = require("../core/privacy");
|
|
5
5
|
const action_1 = require("./action");
|
|
6
6
|
class BaseAction {
|
|
7
|
+
getPrivacyPolicy() {
|
|
8
|
+
return privacy_1.AlwaysAllowPrivacyPolicy;
|
|
9
|
+
}
|
|
10
|
+
getTriggers() {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
getObservers() {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
getValidators() {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
7
19
|
constructor(viewer, builderCtr, options) {
|
|
8
20
|
this.viewer = viewer;
|
|
9
21
|
this.builderCtr = builderCtr;
|
|
@@ -19,24 +31,15 @@ class BaseAction {
|
|
|
19
31
|
this.input = options?.input || {};
|
|
20
32
|
this.builder = new builderCtr(viewer, operation, this, options.existingEnt);
|
|
21
33
|
}
|
|
22
|
-
getPrivacyPolicy() {
|
|
23
|
-
return privacy_1.AlwaysAllowPrivacyPolicy;
|
|
24
|
-
}
|
|
25
|
-
getTriggers() {
|
|
26
|
-
return [];
|
|
27
|
-
}
|
|
28
|
-
getObservers() {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
getValidators() {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
34
|
static createBuilder(viewer, builderCtr, options) {
|
|
35
35
|
let action = new BaseAction(viewer, builderCtr, options);
|
|
36
36
|
return action.builder;
|
|
37
37
|
}
|
|
38
38
|
// perform a bulk action in a transaction rooted on ent T
|
|
39
39
|
// it ends up creating triggers and having all the given actions performed in a transaction
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated use Transaction
|
|
42
|
+
*/
|
|
40
43
|
static bulkAction(ent, builderCtr, ...actions) {
|
|
41
44
|
let action = new BaseAction(ent.viewer, builderCtr, {
|
|
42
45
|
existingEnt: ent,
|
package/action/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
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";
|
|
4
|
+
export { RelativeFieldValue, RelativeNumberValue, NumberOps, convertRelativeInput, maybeConvertRelativeInputPlusExpressions, } from "./relative_value";
|
|
5
|
+
export { Transaction } from "./transaction";
|
package/action/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AllowIfBuilder = exports.DenyIfBuilder = exports.EntChangeset = exports.Orchestrator = exports.setEdgeTypeInGroup = exports.saveBuilderX = exports.saveBuilder = exports.WriteOperation = void 0;
|
|
3
|
+
exports.Transaction = exports.maybeConvertRelativeInputPlusExpressions = exports.convertRelativeInput = exports.NumberOps = exports.AllowIfBuilder = exports.DenyIfBuilder = exports.EntChangeset = exports.Orchestrator = exports.setEdgeTypeInGroup = exports.saveBuilderX = exports.saveBuilder = exports.WriteOperation = void 0;
|
|
4
4
|
var action_1 = require("./action");
|
|
5
5
|
Object.defineProperty(exports, "WriteOperation", { enumerable: true, get: function () { return action_1.WriteOperation; } });
|
|
6
6
|
Object.defineProperty(exports, "saveBuilder", { enumerable: true, get: function () { return action_1.saveBuilder; } });
|
|
@@ -12,3 +12,9 @@ Object.defineProperty(exports, "EntChangeset", { enumerable: true, get: function
|
|
|
12
12
|
var privacy_1 = require("./privacy");
|
|
13
13
|
Object.defineProperty(exports, "DenyIfBuilder", { enumerable: true, get: function () { return privacy_1.DenyIfBuilder; } });
|
|
14
14
|
Object.defineProperty(exports, "AllowIfBuilder", { enumerable: true, get: function () { return privacy_1.AllowIfBuilder; } });
|
|
15
|
+
var relative_value_1 = require("./relative_value");
|
|
16
|
+
Object.defineProperty(exports, "NumberOps", { enumerable: true, get: function () { return relative_value_1.NumberOps; } });
|
|
17
|
+
Object.defineProperty(exports, "convertRelativeInput", { enumerable: true, get: function () { return relative_value_1.convertRelativeInput; } });
|
|
18
|
+
Object.defineProperty(exports, "maybeConvertRelativeInputPlusExpressions", { enumerable: true, get: function () { return relative_value_1.maybeConvertRelativeInputPlusExpressions; } });
|
|
19
|
+
var transaction_1 = require("./transaction");
|
|
20
|
+
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } });
|
package/action/orchestrator.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { AssocEdgeInputOptions, DataOperation } from "../core/ent";
|
|
|
3
3
|
import { SchemaInputType, FieldInfoMap } from "../schema/schema";
|
|
4
4
|
import { Changeset, Executor } from "../action/action";
|
|
5
5
|
import { WriteOperation, Builder, Action } from "../action";
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import * as clause from "../core/clause";
|
|
7
|
+
type MaybeNull<T extends Ent> = T | null;
|
|
8
|
+
type TMaybleNullableEnt<T extends Ent> = T | MaybeNull<T>;
|
|
8
9
|
export interface OrchestratorOptions<TEnt extends Ent<TViewer>, TInput extends Data, TViewer extends Viewer, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> {
|
|
9
10
|
viewer: Viewer;
|
|
10
11
|
operation: WriteOperation;
|
|
@@ -16,6 +17,7 @@ export interface OrchestratorOptions<TEnt extends Ent<TViewer>, TInput extends D
|
|
|
16
17
|
schema: SchemaInputType;
|
|
17
18
|
editedFields(): Map<string, any> | Promise<Map<string, any>>;
|
|
18
19
|
updateInput?: (data: TInput) => void;
|
|
20
|
+
expressions?: Map<string, clause.Clause>;
|
|
19
21
|
fieldInfo: FieldInfoMap;
|
|
20
22
|
}
|
|
21
23
|
interface edgeInputDataOpts {
|
package/action/orchestrator.js
CHANGED
|
@@ -180,6 +180,10 @@ class Orchestrator {
|
|
|
180
180
|
if (this.actualOperation === action_1.WriteOperation.Edit && !this.existingEnt) {
|
|
181
181
|
throw new Error(`existing ent required with operation ${this.actualOperation}`);
|
|
182
182
|
}
|
|
183
|
+
if (this.options.expressions &&
|
|
184
|
+
this.actualOperation !== action_1.WriteOperation.Edit) {
|
|
185
|
+
throw new Error(`expressions are only supported in edit operations for now`);
|
|
186
|
+
}
|
|
183
187
|
const opts = {
|
|
184
188
|
fields: this.validatedFields,
|
|
185
189
|
tableName: this.options.tableName,
|
|
@@ -188,6 +192,7 @@ class Orchestrator {
|
|
|
188
192
|
loadEntOptions: this.options.loaderOptions,
|
|
189
193
|
placeholderID: this.options.builder.placeholderID,
|
|
190
194
|
whereClause: clause.Eq(this.options.key, this.existingEnt?.id),
|
|
195
|
+
expressions: this.options.expressions,
|
|
191
196
|
};
|
|
192
197
|
if (this.logValues) {
|
|
193
198
|
opts.fieldsToLog = this.logValues;
|
|
@@ -713,6 +718,7 @@ class Orchestrator {
|
|
|
713
718
|
await this.validX();
|
|
714
719
|
let ops = [this.buildMainOp()];
|
|
715
720
|
await this.buildEdgeOps(ops);
|
|
721
|
+
// TODO throw if we try and create a new changeset after previously creating one
|
|
716
722
|
return new EntChangeset(this.options.viewer, this.options.builder.placeholderID, this.options.loaderOptions.ent, ops, this.dependencies, this.changesets, this.options);
|
|
717
723
|
}
|
|
718
724
|
async viewerForEntLoad(data) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Clause } from "../core/clause";
|
|
2
|
+
export interface RelativeFieldValue<T = BigInt | number> {
|
|
3
|
+
delta: T;
|
|
4
|
+
sqlExpression: (col: string) => Clause;
|
|
5
|
+
eval: (curr: T) => T;
|
|
6
|
+
}
|
|
7
|
+
export interface RelativeNumberValue<T> {
|
|
8
|
+
add?: T;
|
|
9
|
+
subtract?: T;
|
|
10
|
+
divide?: T;
|
|
11
|
+
multiply?: T;
|
|
12
|
+
modulo?: T;
|
|
13
|
+
}
|
|
14
|
+
declare function addNumber(delta: number): RelativeFieldValue<number>;
|
|
15
|
+
declare function addNumber(delta: BigInt): RelativeFieldValue<BigInt>;
|
|
16
|
+
declare function subtractNumber(delta: number): RelativeFieldValue<number>;
|
|
17
|
+
declare function subtractNumber(delta: BigInt): RelativeFieldValue<BigInt>;
|
|
18
|
+
declare function multiplyNumber(delta: number): RelativeFieldValue<number>;
|
|
19
|
+
declare function multiplyNumber(delta: BigInt): RelativeFieldValue<BigInt>;
|
|
20
|
+
declare function divideNumber(delta: number): RelativeFieldValue<number>;
|
|
21
|
+
declare function divideNumber(delta: BigInt): RelativeFieldValue<BigInt>;
|
|
22
|
+
declare function moduloNumber(delta: number): RelativeFieldValue<number>;
|
|
23
|
+
declare function moduloNumber(delta: BigInt): RelativeFieldValue<BigInt>;
|
|
24
|
+
export declare const NumberOps: {
|
|
25
|
+
addNumber: typeof addNumber;
|
|
26
|
+
moduloNumber: typeof moduloNumber;
|
|
27
|
+
divideNumber: typeof divideNumber;
|
|
28
|
+
subtractNumber: typeof subtractNumber;
|
|
29
|
+
multiplyNumber: typeof multiplyNumber;
|
|
30
|
+
};
|
|
31
|
+
export declare function convertRelativeInput(rel: RelativeNumberValue<BigInt>, col: string, existing: BigInt): {
|
|
32
|
+
value: BigInt;
|
|
33
|
+
clause: Clause;
|
|
34
|
+
};
|
|
35
|
+
export declare function convertRelativeInput(rel: RelativeNumberValue<number>, col: string, existing: number): {
|
|
36
|
+
value: number;
|
|
37
|
+
clause: Clause;
|
|
38
|
+
};
|
|
39
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: number | RelativeNumberValue<number>, col: string, existing: number, expressions: Map<string, Clause>): number;
|
|
40
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: number | RelativeNumberValue<number> | undefined, col: string, existing: number, expressions: Map<string, Clause>): number | undefined;
|
|
41
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: number | RelativeNumberValue<number> | null, col: string, existing: number | null, expressions: Map<string, Clause>): number | null;
|
|
42
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: number | RelativeNumberValue<number> | null | undefined, col: string, existing: number | null, expressions: Map<string, Clause>): number | undefined | null;
|
|
43
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: BigInt | RelativeNumberValue<BigInt>, col: string, existing: BigInt, expressions: Map<string, Clause>): BigInt;
|
|
44
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: BigInt | RelativeNumberValue<BigInt> | undefined, col: string, existing: BigInt, expressions: Map<string, Clause>): BigInt | undefined;
|
|
45
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: BigInt | RelativeNumberValue<BigInt> | null, col: string, existing: BigInt | null, expressions: Map<string, Clause>): BigInt | null;
|
|
46
|
+
export declare function maybeConvertRelativeInputPlusExpressions(rel: BigInt | RelativeNumberValue<BigInt> | null | undefined, col: string, existing: BigInt | null, expressions: Map<string, Clause>): BigInt | null | undefined;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maybeConvertRelativeInputPlusExpressions = exports.convertRelativeInput = exports.NumberOps = void 0;
|
|
4
|
+
const clause_1 = require("../core/clause");
|
|
5
|
+
function addNumber(delta) {
|
|
6
|
+
return {
|
|
7
|
+
delta,
|
|
8
|
+
sqlExpression(col) {
|
|
9
|
+
return (0, clause_1.Add)(col, delta);
|
|
10
|
+
},
|
|
11
|
+
eval(curr) {
|
|
12
|
+
// @ts-expect-error
|
|
13
|
+
return curr + delta;
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function subtractNumber(delta) {
|
|
18
|
+
return {
|
|
19
|
+
delta,
|
|
20
|
+
sqlExpression(col) {
|
|
21
|
+
return (0, clause_1.Subtract)(col, delta);
|
|
22
|
+
},
|
|
23
|
+
eval(curr) {
|
|
24
|
+
// @ts-expect-error
|
|
25
|
+
return curr - delta;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function multiplyNumber(delta) {
|
|
30
|
+
return {
|
|
31
|
+
delta,
|
|
32
|
+
sqlExpression(col) {
|
|
33
|
+
return (0, clause_1.Multiply)(col, delta);
|
|
34
|
+
},
|
|
35
|
+
eval(curr) {
|
|
36
|
+
// @ts-expect-error
|
|
37
|
+
return curr * delta;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function divideNumber(delta) {
|
|
42
|
+
return {
|
|
43
|
+
delta,
|
|
44
|
+
sqlExpression(col) {
|
|
45
|
+
return (0, clause_1.Divide)(col, delta);
|
|
46
|
+
},
|
|
47
|
+
eval(curr) {
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
return curr / delta;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function moduloNumber(delta) {
|
|
54
|
+
return {
|
|
55
|
+
delta,
|
|
56
|
+
sqlExpression(col) {
|
|
57
|
+
return (0, clause_1.Modulo)(col, delta);
|
|
58
|
+
},
|
|
59
|
+
eval(curr) {
|
|
60
|
+
// @ts-expect-error
|
|
61
|
+
return curr % delta;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
exports.NumberOps = {
|
|
66
|
+
addNumber,
|
|
67
|
+
moduloNumber,
|
|
68
|
+
divideNumber,
|
|
69
|
+
subtractNumber,
|
|
70
|
+
multiplyNumber,
|
|
71
|
+
};
|
|
72
|
+
function convertRelativeInput(rel, col, existing) {
|
|
73
|
+
if (Object.keys(rel).length !== 1) {
|
|
74
|
+
throw new Error(`only 1 key is expected. ${Object.keys(rel).length} given`);
|
|
75
|
+
}
|
|
76
|
+
const ret = (relField) => {
|
|
77
|
+
return {
|
|
78
|
+
value: relField.eval(existing),
|
|
79
|
+
clause: relField.sqlExpression(col),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
if (rel.add !== undefined) {
|
|
83
|
+
// @ts-expect-error
|
|
84
|
+
return ret(addNumber(rel.add));
|
|
85
|
+
}
|
|
86
|
+
if (rel.subtract !== undefined) {
|
|
87
|
+
// @ts-expect-error
|
|
88
|
+
return ret(subtractNumber(rel.subtract));
|
|
89
|
+
}
|
|
90
|
+
if (rel.multiply !== undefined) {
|
|
91
|
+
// @ts-expect-error
|
|
92
|
+
return ret(multiplyNumber(rel.multiply));
|
|
93
|
+
}
|
|
94
|
+
if (rel.divide !== undefined) {
|
|
95
|
+
// @ts-expect-error
|
|
96
|
+
return ret(divideNumber(rel.divide));
|
|
97
|
+
}
|
|
98
|
+
if (rel.modulo !== undefined) {
|
|
99
|
+
// @ts-expect-error
|
|
100
|
+
return ret(moduloNumber(rel.modulo));
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`error in convertRelativeInput. shouldn't have gotten here`);
|
|
103
|
+
}
|
|
104
|
+
exports.convertRelativeInput = convertRelativeInput;
|
|
105
|
+
function maybeConvertRelativeInputPlusExpressions(rel, col, existing, expressions) {
|
|
106
|
+
if (rel === null) {
|
|
107
|
+
return rel;
|
|
108
|
+
}
|
|
109
|
+
if (rel === undefined) {
|
|
110
|
+
return rel;
|
|
111
|
+
}
|
|
112
|
+
if (typeof rel === "bigint" || typeof rel === "number") {
|
|
113
|
+
return rel;
|
|
114
|
+
}
|
|
115
|
+
// // TODO is this the behavior we want? should we coalesce as 0?
|
|
116
|
+
// if (existing === null) {
|
|
117
|
+
// throw new Error(`cannot perform a relative operation on null`);
|
|
118
|
+
// }
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
// shouldn't be failing like it currently is. it thinks rel can be bigint and it shouldn't be???
|
|
121
|
+
const { clause, value } = convertRelativeInput(rel, col, existing);
|
|
122
|
+
expressions.set(col, clause);
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
exports.maybeConvertRelativeInputPlusExpressions = maybeConvertRelativeInputPlusExpressions;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Ent, Viewer } from "../core/base";
|
|
2
|
+
import { Action, Builder } from "./action";
|
|
3
|
+
type ActionAny = Action<Ent<Viewer<any, any>>, Builder<Ent<Viewer<any, any>>, Viewer<any, any>, any>, Viewer<any, any>, any, any>;
|
|
4
|
+
export declare class Transaction {
|
|
5
|
+
private viewer;
|
|
6
|
+
private actions;
|
|
7
|
+
constructor(viewer: Viewer, actions: ActionAny[]);
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transaction = void 0;
|
|
4
|
+
const executor_1 = require("./executor");
|
|
5
|
+
class Transaction {
|
|
6
|
+
constructor(viewer,
|
|
7
|
+
// independent operations
|
|
8
|
+
actions) {
|
|
9
|
+
this.viewer = viewer;
|
|
10
|
+
this.actions = actions;
|
|
11
|
+
}
|
|
12
|
+
async run() {
|
|
13
|
+
const changesets = [];
|
|
14
|
+
await Promise.all(this.actions.map(async (action) => {
|
|
15
|
+
const c = await action.changeset();
|
|
16
|
+
changesets.push(c);
|
|
17
|
+
}));
|
|
18
|
+
const executor = new executor_1.ComplexExecutor(this.viewer, "", // no placeholder, no opers
|
|
19
|
+
[], new Map(), changesets);
|
|
20
|
+
await executor.execute();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.Transaction = Transaction;
|
package/auth/auth.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Viewer } from "../core/base";
|
|
3
3
|
import { RequestContext } from "../core/context";
|
|
4
4
|
import { IncomingMessage, ServerResponse } from "http";
|
|
5
|
-
export
|
|
5
|
+
export type AuthViewer = Viewer | null;
|
|
6
6
|
export interface AuthHandler {
|
|
7
7
|
authViewer(ctx: RequestContext): AuthViewer | Promise<AuthViewer>;
|
|
8
8
|
}
|
package/core/base.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ interface LoaderFactoryWithLoaderMany<T, V> extends LoaderFactory<T, V> {
|
|
|
18
18
|
export interface ConfigurableLoaderFactory<T, V> extends LoaderFactory<T, V> {
|
|
19
19
|
createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): Loader<T, V>;
|
|
20
20
|
}
|
|
21
|
-
export
|
|
21
|
+
export type EdgeQueryableDataOptions = Partial<Pick<QueryableDataOptions, "limit" | "orderby" | "clause">>;
|
|
22
22
|
export interface PrimableLoader<T, V> extends Loader<T, V> {
|
|
23
23
|
prime(d: Data): void;
|
|
24
24
|
primeAll?(d: Data): void;
|
|
@@ -53,6 +53,7 @@ export interface Ent<TViewer extends Viewer = Viewer> {
|
|
|
53
53
|
viewer: TViewer;
|
|
54
54
|
getPrivacyPolicy(): PrivacyPolicy<this, TViewer>;
|
|
55
55
|
nodeType: string;
|
|
56
|
+
__setRawDBData<T extends Data = Data>(data: T): any;
|
|
56
57
|
}
|
|
57
58
|
export declare type Data = {
|
|
58
59
|
[key: string]: any;
|
|
@@ -60,7 +61,7 @@ export declare type Data = {
|
|
|
60
61
|
export interface EntConstructor<TEnt extends Ent, TViewer extends Viewer = Viewer> {
|
|
61
62
|
new (viewer: TViewer, data: Data): TEnt;
|
|
62
63
|
}
|
|
63
|
-
export
|
|
64
|
+
export type ID = string | number;
|
|
64
65
|
export interface DataOptions {
|
|
65
66
|
tableName: string;
|
|
66
67
|
context?: Context;
|
|
@@ -92,6 +93,7 @@ export interface CreateRowOptions extends DataOptions {
|
|
|
92
93
|
}
|
|
93
94
|
export interface EditRowOptions extends CreateRowOptions {
|
|
94
95
|
whereClause: clause.Clause;
|
|
96
|
+
expressions?: Map<string, clause.Clause>;
|
|
95
97
|
}
|
|
96
98
|
interface LoadableEntOptions<TEnt extends Ent, TViewer extends Viewer = Viewer> {
|
|
97
99
|
loaderFactory: LoaderFactoryWithOptions;
|
package/core/clause.d.ts
CHANGED
|
@@ -117,7 +117,7 @@ export declare function TsVectorWebsearchToTsQuery(col: string, val: string | Ts
|
|
|
117
117
|
export declare function sensitiveValue(val: any): SensitiveValue;
|
|
118
118
|
export declare function JSONObjectFieldKeyASJSON(col: string, field: string): string;
|
|
119
119
|
export declare function JSONObjectFieldKeyAsText(col: string, field: string): string;
|
|
120
|
-
|
|
120
|
+
type predicate = "==" | ">" | "<" | "!=" | ">=" | "<=";
|
|
121
121
|
export declare function JSONPathValuePredicate(dbCol: string, path: string, val: any, pred: predicate): Clause;
|
|
122
122
|
declare class paginationMultipleColumnsSubQueryClause implements Clause {
|
|
123
123
|
private col;
|
|
@@ -134,4 +134,9 @@ declare class paginationMultipleColumnsSubQueryClause implements Clause {
|
|
|
134
134
|
instanceKey(): string;
|
|
135
135
|
}
|
|
136
136
|
export declare function PaginationMultipleColsSubQuery(col: string, op: string, tableName: string, uniqueCol: string, val: any): paginationMultipleColumnsSubQueryClause;
|
|
137
|
+
export declare function Add(col: string, value: any): Clause;
|
|
138
|
+
export declare function Subtract(col: string, value: any): Clause;
|
|
139
|
+
export declare function Multiply(col: string, value: any): Clause;
|
|
140
|
+
export declare function Divide(col: string, value: any): Clause;
|
|
141
|
+
export declare function Modulo(col: string, value: any): Clause;
|
|
137
142
|
export {};
|
package/core/clause.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.PaginationMultipleColsSubQuery = exports.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.OrOptional = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = exports.inClause = void 0;
|
|
26
|
+
exports.Modulo = exports.Divide = exports.Multiply = exports.Subtract = exports.Add = exports.PaginationMultipleColsSubQuery = exports.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.OrOptional = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = exports.inClause = void 0;
|
|
27
27
|
const db_1 = __importStar(require("./db"));
|
|
28
28
|
function isSensitive(val) {
|
|
29
29
|
return (val !== null &&
|
|
@@ -229,14 +229,14 @@ class postgresArrayOperatorList extends postgresArrayOperator {
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
class inClause {
|
|
232
|
+
static getPostgresInClauseValuesThreshold() {
|
|
233
|
+
return 70;
|
|
234
|
+
}
|
|
232
235
|
constructor(col, value, type = "uuid") {
|
|
233
236
|
this.col = col;
|
|
234
237
|
this.value = value;
|
|
235
238
|
this.type = type;
|
|
236
239
|
}
|
|
237
|
-
static getPostgresInClauseValuesThreshold() {
|
|
238
|
-
return 70;
|
|
239
|
-
}
|
|
240
240
|
clause(idx) {
|
|
241
241
|
// do a simple = when only one item
|
|
242
242
|
if (this.value.length === 1) {
|
|
@@ -708,3 +708,24 @@ function PaginationMultipleColsSubQuery(col, op, tableName, uniqueCol, val) {
|
|
|
708
708
|
return new paginationMultipleColumnsSubQueryClause(col, op, tableName, uniqueCol, val);
|
|
709
709
|
}
|
|
710
710
|
exports.PaginationMultipleColsSubQuery = PaginationMultipleColsSubQuery;
|
|
711
|
+
// These 5 are used on the RHS of an expression
|
|
712
|
+
function Add(col, value) {
|
|
713
|
+
return new simpleClause(col, value, "+", new isNullClause(col));
|
|
714
|
+
}
|
|
715
|
+
exports.Add = Add;
|
|
716
|
+
function Subtract(col, value) {
|
|
717
|
+
return new simpleClause(col, value, "-", new isNullClause(col));
|
|
718
|
+
}
|
|
719
|
+
exports.Subtract = Subtract;
|
|
720
|
+
function Multiply(col, value) {
|
|
721
|
+
return new simpleClause(col, value, "*", new isNullClause(col));
|
|
722
|
+
}
|
|
723
|
+
exports.Multiply = Multiply;
|
|
724
|
+
function Divide(col, value) {
|
|
725
|
+
return new simpleClause(col, value, "/", new isNullClause(col));
|
|
726
|
+
}
|
|
727
|
+
exports.Divide = Divide;
|
|
728
|
+
function Modulo(col, value) {
|
|
729
|
+
return new simpleClause(col, value, "%", new isNullClause(col));
|
|
730
|
+
}
|
|
731
|
+
exports.Modulo = Modulo;
|
package/core/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Database, DBDict } from "./db";
|
|
3
|
-
|
|
3
|
+
type logType = "query" | "warn" | "info" | "error" | "debug";
|
|
4
4
|
declare enum graphqlMutationName {
|
|
5
5
|
NOUN_VERB = "NounVerb",
|
|
6
6
|
VERB_NOUN = "VerbNoun"
|
|
@@ -19,6 +19,7 @@ export interface Config {
|
|
|
19
19
|
db?: Database | DBDict;
|
|
20
20
|
log?: logType | logType[];
|
|
21
21
|
codegen?: CodegenConfig;
|
|
22
|
+
logQueryWithError?: boolean;
|
|
22
23
|
customGraphQLJSONPath?: string;
|
|
23
24
|
globalSchemaPath?: string;
|
|
24
25
|
}
|
package/core/config.js
CHANGED
|
@@ -32,6 +32,7 @@ const js_yaml_1 = require("js-yaml");
|
|
|
32
32
|
const db_1 = __importDefault(require("./db"));
|
|
33
33
|
const path = __importStar(require("path"));
|
|
34
34
|
const logger_1 = require("./logger");
|
|
35
|
+
const ent_1 = require("./ent");
|
|
35
36
|
// ent.config.ts eventually. for now ent.yml
|
|
36
37
|
// or ent.yml?
|
|
37
38
|
var graphqlMutationName;
|
|
@@ -60,6 +61,7 @@ function setConfig(cfg) {
|
|
|
60
61
|
db: cfg.db,
|
|
61
62
|
});
|
|
62
63
|
}
|
|
64
|
+
(0, ent_1.___setLogQueryErrorWithError)(cfg.logQueryWithError);
|
|
63
65
|
}
|
|
64
66
|
function isBuffer(b) {
|
|
65
67
|
return b.write !== undefined;
|
package/core/date.js
CHANGED
|
@@ -10,11 +10,7 @@ function parseDate(val, throwErr) {
|
|
|
10
10
|
else if (typeof val === "string") {
|
|
11
11
|
dt = luxon_1.DateTime.fromISO(val);
|
|
12
12
|
if (!dt.isValid) {
|
|
13
|
-
|
|
14
|
-
if (ms === NaN) {
|
|
15
|
-
throw throwErr(`invalid input for type Time ${val}`);
|
|
16
|
-
}
|
|
17
|
-
dt = luxon_1.DateTime.fromMillis(ms);
|
|
13
|
+
dt = luxon_1.DateTime.fromMillis(Date.parse(val));
|
|
18
14
|
}
|
|
19
15
|
}
|
|
20
16
|
else if (val instanceof Date) {
|
package/core/db.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface Database extends PoolConfig {
|
|
|
7
7
|
port?: number;
|
|
8
8
|
sslmode?: string;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
10
|
+
export type env = "production" | "test" | "development";
|
|
11
11
|
export declare type DBDict = Partial<Record<env, Database>>;
|
|
12
12
|
export declare enum Dialect {
|
|
13
13
|
Postgres = "postgres",
|
|
@@ -18,6 +18,11 @@ interface DatabaseInfo {
|
|
|
18
18
|
config: PoolConfig;
|
|
19
19
|
filePath?: string;
|
|
20
20
|
}
|
|
21
|
+
interface clientConfigArgs {
|
|
22
|
+
connectionString?: string;
|
|
23
|
+
dbFile?: string;
|
|
24
|
+
db?: Database | DBDict;
|
|
25
|
+
}
|
|
21
26
|
export default class DB {
|
|
22
27
|
db: DatabaseInfo;
|
|
23
28
|
static instance: DB;
|
|
@@ -30,13 +35,10 @@ export default class DB {
|
|
|
30
35
|
getNewClient(): Promise<Client>;
|
|
31
36
|
getSQLiteClient(): Sqlite;
|
|
32
37
|
endPool(): Promise<void>;
|
|
38
|
+
emitsExplicitTransactionStatements(): boolean;
|
|
33
39
|
static getInstance(): DB;
|
|
34
40
|
static getDialect(): Dialect;
|
|
35
|
-
static initDB(args?:
|
|
36
|
-
connectionString?: string;
|
|
37
|
-
dbFile?: string;
|
|
38
|
-
db?: Database | DBDict;
|
|
39
|
-
}): void;
|
|
41
|
+
static initDB(args?: clientConfigArgs): void;
|
|
40
42
|
}
|
|
41
43
|
export declare const defaultTimestampParser: any;
|
|
42
44
|
export interface Queryer {
|
|
@@ -53,6 +55,7 @@ export interface Connection extends Queryer {
|
|
|
53
55
|
self(): Queryer;
|
|
54
56
|
newClient(): Promise<Client>;
|
|
55
57
|
close(): Promise<void>;
|
|
58
|
+
runInTransaction?(cb: () => void | Promise<void>): any;
|
|
56
59
|
}
|
|
57
60
|
export interface QueryResultRow {
|
|
58
61
|
[column: string]: any;
|