@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 ArcSine Technologies
3
+ Copyright (c) 2023 ArcSine Technologies
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model-sql",
3
- "version": "4.1.3",
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": "^4.1.1",
31
- "@travetto/context": "^4.1.1",
32
- "@travetto/model": "^4.1.3",
33
- "@travetto/model-query": "^4.1.3"
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": "^4.1.1",
37
- "@travetto/test": "^4.1.1"
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": {
@@ -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, `SAVEPOINT ${transactionId};`);
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, 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED;');
154
+ await this.execute(conn, this.transactionDialect.isolate);
145
155
  }
146
- await this.execute(conn, 'BEGIN;');
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, `RELEASE SAVEPOINT ${transactionId};`);
166
+ await this.execute(conn, this.transactionDialect.commitNested.replace('%', transactionId));
157
167
  }
158
168
  } else {
159
- await this.execute(conn, 'COMMIT;');
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, `ROLLBACK TO ${transactionId};`);
179
+ await this.execute(conn, this.transactionDialect.rollbackNested.replace('%', transactionId));
170
180
  }
171
181
  } else {
172
- await this.execute(conn, 'ROLLBACK;');
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: MethodDescriptor): void {
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: MethodDescriptor): void {
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: MethodDescriptor): void {
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[]) {
@@ -1,6 +1,6 @@
1
1
  import { RuntimeIndex } from '@travetto/manifest';
2
2
  import { DataUtil, SchemaRegistry, FieldConfig, Schema } from '@travetto/schema';
3
- import { Class, ObjectUtil, AppError, TypedObject } from '@travetto/base';
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 (ObjectUtil.isPlainObject(top)) {
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 (ObjectUtil.isPlainObject(val)) {
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
@@ -1,7 +1,7 @@
1
- import { Class, TypedObject, ObjectUtil } from '@travetto/base';
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 (!ObjectUtil.isSimple(o)) {
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, handler: VisitHandler<unknown, VisitInstanceNode<unknown>>): void {
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 (!ObjectUtil.isPlainObject(select[k]) && localMap[sk]) {
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 (ObjectUtil.isPrimitive(val)) {
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 = (k: keyof BulkOp<T>): T[] =>
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