@itrocks/mysql 0.0.21 → 0.0.23

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/cjs/mysql.d.ts CHANGED
@@ -30,6 +30,7 @@ export declare class Mysql extends DataSource {
30
30
  database: string;
31
31
  };
32
32
  connection?: Connection;
33
+ saveQueue: WeakMap<object, Promise<void | Entity<object>>>;
33
34
  constructor(config: {
34
35
  host: string;
35
36
  user: string;
@@ -51,6 +52,7 @@ export declare class Mysql extends DataSource {
51
52
  }>[]>;
52
53
  readCollectionIds<T extends object, PT extends object>(object: Entity<T>, property: KeyOf<T>, type?: Type<PT>): Promise<Identifier[]>;
53
54
  readMultiple<T extends object>(type: Type<T>, ids: Identifier[]): Promise<Entity<T>[]>;
55
+ runSerialized<T extends object>(object: MayEntity<T>, task: () => Promise<Entity<T>>): Promise<Entity<T>>;
54
56
  save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
55
57
  saveCollection<T extends object>(object: Entity<T>, property: KeyOf<T>, value: (Identifier | MayEntity)[]): Promise<void>;
56
58
  saveComponents<T extends object>(object: Entity<T>, property: KeyOf<T>, components: (Identifier | MayEntity)[]): Promise<void>;
package/cjs/mysql.js CHANGED
@@ -15,6 +15,7 @@ const sort_1 = require("@itrocks/sort");
15
15
  const sort_2 = require("@itrocks/sort");
16
16
  const storage_1 = require("@itrocks/storage");
17
17
  const storage_2 = require("@itrocks/storage");
18
+ const storage_3 = require("@itrocks/storage");
18
19
  const mariadb_1 = require("mariadb");
19
20
  exports.DEBUG = false;
20
21
  const depends = {
@@ -41,6 +42,7 @@ function mysqlDependsOn(dependencies) {
41
42
  class Mysql extends storage_1.DataSource {
42
43
  config;
43
44
  connection;
45
+ saveQueue = new WeakMap();
44
46
  constructor(config) {
45
47
  super();
46
48
  this.config = config;
@@ -200,10 +202,18 @@ class Mysql extends storage_1.DataSource {
200
202
  const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '` WHERE id IN (' + questionMarks + ')', ids);
201
203
  return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
202
204
  }
205
+ async runSerialized(object, task) {
206
+ const prev = this.saveQueue.get(object) || Promise.resolve();
207
+ const next = prev.then(task, task);
208
+ this.saveQueue.set(object, next.then(() => { this.saveQueue.delete(object); }, () => { this.saveQueue.delete(object); }));
209
+ return next;
210
+ }
203
211
  async save(object) {
204
- return this.isObjectConnected(object)
205
- ? this.update(object)
206
- : this.insert(object);
212
+ return this.runSerialized(object, async () => {
213
+ return this.isObjectConnected(object)
214
+ ? this.update(object)
215
+ : this.insert(object);
216
+ });
207
217
  }
208
218
  async saveCollection(object, property, value) {
209
219
  if (property.endsWith('Ids')) {
@@ -288,13 +298,17 @@ class Mysql extends storage_1.DataSource {
288
298
  async search(type, search = {}, options) {
289
299
  const connection = this.connection ?? await this.connect();
290
300
  const propertiesSql = this.propertiesToSqlSelect(type);
301
+ let limitOption = undefined;
291
302
  let sortOption = undefined;
292
303
  for (const option of this.options(options)) {
293
- if (option === storage_2.Sort) {
294
- sortOption = new storage_2.Sort((0, sort_2.sortOf)(type));
304
+ if (option === storage_3.Sort) {
305
+ sortOption = new storage_3.Sort((0, sort_2.sortOf)(type));
306
+ }
307
+ if (option instanceof storage_2.Limit) {
308
+ limitOption = option;
295
309
  }
296
- if (option instanceof storage_2.Sort) {
297
- sortOption = option.properties.length ? option : new storage_2.Sort((0, sort_2.sortOf)(type));
310
+ if (option instanceof storage_3.Sort) {
311
+ sortOption = option.properties.length ? option : new storage_3.Sort((0, sort_2.sortOf)(type));
298
312
  }
299
313
  }
300
314
  Object.setPrototypeOf(search, type.prototype);
@@ -302,13 +316,15 @@ class Mysql extends storage_1.DataSource {
302
316
  const [values] = await this.valuesToDb(search);
303
317
  if (exports.DEBUG)
304
318
  console.log('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql, '[', values, ']');
319
+ const limit = limitOption?.limit ? ' LIMIT ' + limitOption.limit : '';
320
+ const offset = limitOption?.offset ? ' OFFSET ' + limitOption.offset : '';
305
321
  const sort = sortOption?.properties.length
306
322
  ? ' ORDER BY '
307
323
  + sortOption.properties
308
324
  .map(property => '`' + property + '`' + (property instanceof sort_1.Reverse ? ' DESC' : ''))
309
325
  .join(', ')
310
326
  : '';
311
- const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql + sort, Object.values(values));
327
+ const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql + sort + limit + offset, Object.values(values));
312
328
  return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
313
329
  }
314
330
  async update(object) {
package/esm/mysql.d.ts CHANGED
@@ -30,6 +30,7 @@ export declare class Mysql extends DataSource {
30
30
  database: string;
31
31
  };
32
32
  connection?: Connection;
33
+ saveQueue: WeakMap<object, Promise<void | Entity<object>>>;
33
34
  constructor(config: {
34
35
  host: string;
35
36
  user: string;
@@ -51,6 +52,7 @@ export declare class Mysql extends DataSource {
51
52
  }>[]>;
52
53
  readCollectionIds<T extends object, PT extends object>(object: Entity<T>, property: KeyOf<T>, type?: Type<PT>): Promise<Identifier[]>;
53
54
  readMultiple<T extends object>(type: Type<T>, ids: Identifier[]): Promise<Entity<T>[]>;
55
+ runSerialized<T extends object>(object: MayEntity<T>, task: () => Promise<Entity<T>>): Promise<Entity<T>>;
54
56
  save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
55
57
  saveCollection<T extends object>(object: Entity<T>, property: KeyOf<T>, value: (Identifier | MayEntity)[]): Promise<void>;
56
58
  saveComponents<T extends object>(object: Entity<T>, property: KeyOf<T>, components: (Identifier | MayEntity)[]): Promise<void>;
package/esm/mysql.js CHANGED
@@ -9,6 +9,7 @@ import { ReflectProperty } from '@itrocks/reflect';
9
9
  import { Reverse } from '@itrocks/sort';
10
10
  import { sortOf } from '@itrocks/sort';
11
11
  import { DataSource } from '@itrocks/storage';
12
+ import { Limit } from '@itrocks/storage';
12
13
  import { Sort } from '@itrocks/storage';
13
14
  import { createConnection } from 'mariadb';
14
15
  export const DEBUG = false;
@@ -36,6 +37,7 @@ export function mysqlDependsOn(dependencies) {
36
37
  export class Mysql extends DataSource {
37
38
  config;
38
39
  connection;
40
+ saveQueue = new WeakMap();
39
41
  constructor(config) {
40
42
  super();
41
43
  this.config = config;
@@ -195,10 +197,18 @@ export class Mysql extends DataSource {
195
197
  const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '` WHERE id IN (' + questionMarks + ')', ids);
196
198
  return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
197
199
  }
200
+ async runSerialized(object, task) {
201
+ const prev = this.saveQueue.get(object) || Promise.resolve();
202
+ const next = prev.then(task, task);
203
+ this.saveQueue.set(object, next.then(() => { this.saveQueue.delete(object); }, () => { this.saveQueue.delete(object); }));
204
+ return next;
205
+ }
198
206
  async save(object) {
199
- return this.isObjectConnected(object)
200
- ? this.update(object)
201
- : this.insert(object);
207
+ return this.runSerialized(object, async () => {
208
+ return this.isObjectConnected(object)
209
+ ? this.update(object)
210
+ : this.insert(object);
211
+ });
202
212
  }
203
213
  async saveCollection(object, property, value) {
204
214
  if (property.endsWith('Ids')) {
@@ -283,11 +293,15 @@ export class Mysql extends DataSource {
283
293
  async search(type, search = {}, options) {
284
294
  const connection = this.connection ?? await this.connect();
285
295
  const propertiesSql = this.propertiesToSqlSelect(type);
296
+ let limitOption = undefined;
286
297
  let sortOption = undefined;
287
298
  for (const option of this.options(options)) {
288
299
  if (option === Sort) {
289
300
  sortOption = new Sort(sortOf(type));
290
301
  }
302
+ if (option instanceof Limit) {
303
+ limitOption = option;
304
+ }
291
305
  if (option instanceof Sort) {
292
306
  sortOption = option.properties.length ? option : new Sort(sortOf(type));
293
307
  }
@@ -297,13 +311,15 @@ export class Mysql extends DataSource {
297
311
  const [values] = await this.valuesToDb(search);
298
312
  if (DEBUG)
299
313
  console.log('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql, '[', values, ']');
314
+ const limit = limitOption?.limit ? ' LIMIT ' + limitOption.limit : '';
315
+ const offset = limitOption?.offset ? ' OFFSET ' + limitOption.offset : '';
300
316
  const sort = sortOption?.properties.length
301
317
  ? ' ORDER BY '
302
318
  + sortOption.properties
303
319
  .map(property => '`' + property + '`' + (property instanceof Reverse ? ' DESC' : ''))
304
320
  .join(', ')
305
321
  : '';
306
- const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql + sort, Object.values(values));
322
+ const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '`' + sql + sort + limit + offset, Object.values(values));
307
323
  return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
308
324
  }
309
325
  async update(object) {
package/package.json CHANGED
@@ -59,5 +59,5 @@
59
59
  "build:esm": "tsc -p tsconfig.esm.json"
60
60
  },
61
61
  "types": "./esm/mysql.d.ts",
62
- "version": "0.0.21"
62
+ "version": "0.0.23"
63
63
  }