@travetto/model-sql 4.1.3 → 5.0.0-rc.0
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/LICENSE +1 -1
- package/package.json +7 -7
- package/src/connection/base.ts +17 -7
- package/src/connection/decorator.ts +3 -4
- package/src/dialect/base.ts +3 -3
- package/src/internal/util.ts +8 -8
- package/src/service.ts +3 -2
package/LICENSE
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-sql",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-rc.0",
|
|
4
4
|
"description": "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sql",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"directory": "module/model-sql"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/config": "^
|
|
31
|
-
"@travetto/context": "^
|
|
32
|
-
"@travetto/model": "^
|
|
33
|
-
"@travetto/model-query": "^
|
|
30
|
+
"@travetto/config": "^5.0.0-rc.0",
|
|
31
|
+
"@travetto/context": "^5.0.0-rc.0",
|
|
32
|
+
"@travetto/model": "^5.0.0-rc.0",
|
|
33
|
+
"@travetto/model-query": "^5.0.0-rc.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@travetto/command": "^
|
|
37
|
-
"@travetto/test": "^
|
|
36
|
+
"@travetto/command": "^5.0.0-rc.0",
|
|
37
|
+
"@travetto/test": "^5.0.0-rc.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@travetto/command": {
|
package/src/connection/base.ts
CHANGED
|
@@ -16,6 +16,16 @@ export abstract class Connection<C = unknown> {
|
|
|
16
16
|
isolatedTransactions = true;
|
|
17
17
|
nestedTransactions = true;
|
|
18
18
|
|
|
19
|
+
transactionDialect = {
|
|
20
|
+
begin: 'BEGIN;',
|
|
21
|
+
beginNested: 'SAVEPOINT %;',
|
|
22
|
+
isolate: 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED;',
|
|
23
|
+
rollback: 'ROLLBACK;',
|
|
24
|
+
rollbackNested: 'ROLLBACK TO %;',
|
|
25
|
+
commit: 'COMMIT;',
|
|
26
|
+
commitNested: 'RELEASE SAVEPOINT %;'
|
|
27
|
+
};
|
|
28
|
+
|
|
19
29
|
constructor(public readonly context: AsyncContext) {
|
|
20
30
|
|
|
21
31
|
}
|
|
@@ -137,13 +147,13 @@ export abstract class Connection<C = unknown> {
|
|
|
137
147
|
async startTx(conn: C, transactionId?: string): Promise<void> {
|
|
138
148
|
if (transactionId) {
|
|
139
149
|
if (this.nestedTransactions) {
|
|
140
|
-
await this.execute(conn,
|
|
150
|
+
await this.execute(conn, this.transactionDialect.beginNested.replace('%', transactionId));
|
|
141
151
|
}
|
|
142
152
|
} else {
|
|
143
153
|
if (this.isolatedTransactions) {
|
|
144
|
-
await this.execute(conn,
|
|
154
|
+
await this.execute(conn, this.transactionDialect.isolate);
|
|
145
155
|
}
|
|
146
|
-
await this.execute(conn,
|
|
156
|
+
await this.execute(conn, this.transactionDialect.begin);
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
159
|
|
|
@@ -153,10 +163,10 @@ export abstract class Connection<C = unknown> {
|
|
|
153
163
|
async commitTx(conn: C, transactionId?: string): Promise<void> {
|
|
154
164
|
if (transactionId) {
|
|
155
165
|
if (this.nestedTransactions) {
|
|
156
|
-
await this.execute(conn,
|
|
166
|
+
await this.execute(conn, this.transactionDialect.commitNested.replace('%', transactionId));
|
|
157
167
|
}
|
|
158
168
|
} else {
|
|
159
|
-
await this.execute(conn,
|
|
169
|
+
await this.execute(conn, this.transactionDialect.commit);
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
172
|
|
|
@@ -166,10 +176,10 @@ export abstract class Connection<C = unknown> {
|
|
|
166
176
|
async rollbackTx(conn: C, transactionId?: string): Promise<void> {
|
|
167
177
|
if (transactionId) {
|
|
168
178
|
if (this.isolatedTransactions) {
|
|
169
|
-
await this.execute(conn,
|
|
179
|
+
await this.execute(conn, this.transactionDialect.rollbackNested.replace('%', transactionId));
|
|
170
180
|
}
|
|
171
181
|
} else {
|
|
172
|
-
await this.execute(conn,
|
|
182
|
+
await this.execute(conn, this.transactionDialect.rollback);
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { MethodDescriptor } from '@travetto/base';
|
|
2
1
|
import { Connection, TransactionType } from './base';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -12,7 +11,7 @@ export interface ConnectionAware<C = unknown> {
|
|
|
12
11
|
* Decorator to ensure a method runs with a valid connection
|
|
13
12
|
*/
|
|
14
13
|
export function Connected<T extends ConnectionAware>() {
|
|
15
|
-
return function (target: T, prop: string | symbol, desc:
|
|
14
|
+
return function (target: T, prop: string | symbol, desc: TypedPropertyDescriptor<(...params: unknown[]) => Promise<unknown>>): void {
|
|
16
15
|
const og = desc.value!;
|
|
17
16
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
18
17
|
desc.value = async function (this: T, ...args: unknown[]) {
|
|
@@ -25,7 +24,7 @@ export function Connected<T extends ConnectionAware>() {
|
|
|
25
24
|
* Decorator to ensure a method runs with a valid connection
|
|
26
25
|
*/
|
|
27
26
|
export function ConnectedIterator<T extends ConnectionAware>() {
|
|
28
|
-
return function (target: T, prop: string | symbol, desc:
|
|
27
|
+
return function (target: T, prop: string | symbol, desc: TypedPropertyDescriptor<(...params: unknown[]) => AsyncGenerator<unknown>>): void {
|
|
29
28
|
const og = desc.value!;
|
|
30
29
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
31
30
|
desc.value = async function* (this: T, ...args: unknown[]) {
|
|
@@ -38,7 +37,7 @@ export function ConnectedIterator<T extends ConnectionAware>() {
|
|
|
38
37
|
* Decorator to ensure a method runs with a valid transaction
|
|
39
38
|
*/
|
|
40
39
|
export function Transactional<T extends ConnectionAware>(mode: TransactionType = 'required') {
|
|
41
|
-
return function (target: T, prop: string | symbol, desc:
|
|
40
|
+
return function (target: T, prop: string | symbol, desc: TypedPropertyDescriptor<(...params: unknown[]) => Promise<unknown>>): void {
|
|
42
41
|
const og = desc.value!;
|
|
43
42
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
44
43
|
desc.value = function (this: T, ...args: unknown[]) {
|
package/src/dialect/base.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RuntimeIndex } from '@travetto/manifest';
|
|
2
2
|
import { DataUtil, SchemaRegistry, FieldConfig, Schema } from '@travetto/schema';
|
|
3
|
-
import { Class,
|
|
3
|
+
import { Class, AppError, TypedObject } from '@travetto/base';
|
|
4
4
|
import { SelectClause, Query, SortClause, WhereClause, RetainFields } from '@travetto/model-query';
|
|
5
5
|
import { BulkResponse, IndexConfig } from '@travetto/model';
|
|
6
6
|
import { PointImpl } from '@travetto/model-query/src/internal/model/point';
|
|
@@ -424,7 +424,7 @@ export abstract class SQLDialect implements DialectState {
|
|
|
424
424
|
}
|
|
425
425
|
const sPath = this.resolveName(sStack);
|
|
426
426
|
|
|
427
|
-
if (
|
|
427
|
+
if (DataUtil.isPlainObject(top)) {
|
|
428
428
|
const subKey = Object.keys(top)[0];
|
|
429
429
|
if (!subKey.startsWith('$')) {
|
|
430
430
|
const inner = this.getWhereFieldSQL(sStack, top);
|
|
@@ -731,7 +731,7 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
|
|
|
731
731
|
const fields: [string, boolean][] = idx.fields.map(x => {
|
|
732
732
|
const key = TypedObject.keys(x)[0];
|
|
733
733
|
const val = x[key];
|
|
734
|
-
if (
|
|
734
|
+
if (DataUtil.isPlainObject(val)) {
|
|
735
735
|
throw new Error('Unable to supported nested fields for indices');
|
|
736
736
|
}
|
|
737
737
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
package/src/internal/util.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Class, TypedObject
|
|
1
|
+
import { Class, TypedObject } from '@travetto/base';
|
|
2
2
|
import { SelectClause, SortClause } from '@travetto/model-query';
|
|
3
|
-
import { ModelRegistry, ModelType } from '@travetto/model';
|
|
4
|
-
import { SchemaRegistry, ClassConfig, FieldConfig } from '@travetto/schema';
|
|
3
|
+
import { ModelRegistry, ModelType, OptionalId } from '@travetto/model';
|
|
4
|
+
import { SchemaRegistry, ClassConfig, FieldConfig, DataUtil } from '@travetto/schema';
|
|
5
5
|
import { AllViewⲐ } from '@travetto/schema/src/internal/types';
|
|
6
6
|
|
|
7
7
|
import { DialectState, InsertWrapper, VisitHandler, VisitState, VisitInstanceNode, OrderBy } from './types';
|
|
@@ -45,7 +45,7 @@ export class SQLUtil {
|
|
|
45
45
|
static cleanResults<T, U = T>(dct: DialectState, o: T | T[]): U | U[] {
|
|
46
46
|
if (Array.isArray(o)) {
|
|
47
47
|
return o.filter(x => x !== null && x !== undefined).map(x => this.cleanResults(dct, x));
|
|
48
|
-
} else if (!
|
|
48
|
+
} else if (!DataUtil.isSimpleValue(o)) {
|
|
49
49
|
for (const k of TypedObject.keys(o)) {
|
|
50
50
|
if (o[k] === null || o[k] === undefined || k === dct.parentPathField.name || k === dct.pathField.name || k === dct.idxField.name) {
|
|
51
51
|
delete o[k];
|
|
@@ -173,7 +173,7 @@ export class SQLUtil {
|
|
|
173
173
|
/**
|
|
174
174
|
* Process a schema instance by visiting it synchronously. This is synchronous to prevent concurrent calls from breaking
|
|
175
175
|
*/
|
|
176
|
-
static visitSchemaInstance<T extends ModelType>(cls: Class<T>, instance: T
|
|
176
|
+
static visitSchemaInstance<T extends ModelType>(cls: Class<T>, instance: T | OptionalId<T>, handler: VisitHandler<unknown, VisitInstanceNode<unknown>>): void {
|
|
177
177
|
const pathObj: unknown[] = [instance];
|
|
178
178
|
this.visitSchemaSync(SchemaRegistry.get(cls), {
|
|
179
179
|
onRoot: (config) => {
|
|
@@ -236,7 +236,7 @@ export class SQLUtil {
|
|
|
236
236
|
for (const [k, v] of TypedObject.entries(select)) {
|
|
237
237
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
238
238
|
const sk = k as string;
|
|
239
|
-
if (!
|
|
239
|
+
if (!DataUtil.isPlainObject(select[k]) && localMap[sk]) {
|
|
240
240
|
if (!v) {
|
|
241
241
|
if (toGet.size === 0) {
|
|
242
242
|
toGet = new Set(SchemaRegistry.get(cls).views[AllViewⲐ].fields);
|
|
@@ -262,7 +262,7 @@ export class SQLUtil {
|
|
|
262
262
|
const key = Object.keys(cl)[0];
|
|
263
263
|
const val = cl[key];
|
|
264
264
|
const field = { ...schema.views[AllViewⲐ].schema[key] };
|
|
265
|
-
if (
|
|
265
|
+
if (DataUtil.isPrimitive(val)) {
|
|
266
266
|
stack.push(field);
|
|
267
267
|
found = { stack, asc: val === 1 };
|
|
268
268
|
} else {
|
|
@@ -334,7 +334,7 @@ export class SQLUtil {
|
|
|
334
334
|
/**
|
|
335
335
|
* Get insert statements for a given class, and its child tables
|
|
336
336
|
*/
|
|
337
|
-
static async getInserts<T extends ModelType>(cls: Class<T>, els: T[]): Promise<InsertWrapper[]> {
|
|
337
|
+
static async getInserts<T extends ModelType>(cls: Class<T>, els: (T | OptionalId<T>)[]): Promise<InsertWrapper[]> {
|
|
338
338
|
const ins: Record<string, InsertWrapper> = {};
|
|
339
339
|
|
|
340
340
|
const track = (stack: VisitStack[], value: unknown): void => {
|
package/src/service.ts
CHANGED
|
@@ -223,8 +223,9 @@ export class SQLModelService implements
|
|
|
223
223
|
new Map([...existingUpsertedIds.entries()].map(([k, v]) => [v, k]))
|
|
224
224
|
);
|
|
225
225
|
|
|
226
|
-
const get =
|
|
227
|
-
operations.map(x => x[k]).filter((x): x is T => !!x);
|
|
226
|
+
const get = <K extends keyof BulkOp<T>>(k: K): Required<BulkOp<T>>[K][] =>
|
|
227
|
+
operations.map(x => x[k]).filter((x): x is Required<BulkOp<T>>[K] => !!x);
|
|
228
|
+
|
|
228
229
|
const getStatements = async (k: keyof BulkOp<T>): Promise<InsertWrapper[]> =>
|
|
229
230
|
(await SQLUtil.getInserts(cls, get(k))).filter(x => !!x.records.length);
|
|
230
231
|
|