@naturalcycles/db-lib 10.21.0 → 10.23.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.
@@ -175,9 +175,9 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
175
175
  private static multiGetMapByTableById;
176
176
  private static prepareMultiGetOutput;
177
177
  /**
178
- * Very @experimental.
178
+ * @experimental.
179
179
  */
180
- static multiDeleteByIds(inputs: DaoWithIds<AnyDao>[], _opt?: CommonDaoOptions): Promise<NonNegativeInteger>;
180
+ static multiDelete(inputs: (DaoWithId<AnyDao> | DaoWithIds<AnyDao>)[], opt?: CommonDaoOptions): Promise<NonNegativeInteger>;
181
181
  static multiSave(inputs: (DaoWithRows<AnyDao> | DaoWithRow<AnyDao>)[], opt?: CommonDaoSaveBatchOptions<any>): Promise<void>;
182
182
  createTransaction(opt?: CommonDBTransactionOptions): Promise<CommonDaoTransaction>;
183
183
  runInTransaction<T = void>(fn: CommonDaoTransactionFn<T>, opt?: CommonDBTransactionOptions): Promise<T>;
@@ -854,17 +854,27 @@ export class CommonDao {
854
854
  return bmsByProp;
855
855
  }
856
856
  /**
857
- * Very @experimental.
857
+ * @experimental.
858
858
  */
859
- static async multiDeleteByIds(inputs, _opt = {}) {
859
+ static async multiDelete(inputs, opt = {}) {
860
860
  if (!inputs.length)
861
861
  return 0;
862
862
  const { db } = inputs[0].dao.cfg;
863
863
  const idsByTable = {};
864
- for (const { dao, ids } of inputs) {
865
- idsByTable[dao.cfg.table] = ids;
864
+ for (const input of inputs) {
865
+ const { dao } = input;
866
+ const { table } = dao.cfg;
867
+ dao.requireWriteAccess();
868
+ dao.requireObjectMutability(opt);
869
+ idsByTable[table] ||= [];
870
+ if ('id' in input) {
871
+ idsByTable[table].push(input.id);
872
+ }
873
+ else {
874
+ idsByTable[table].push(...input.ids);
875
+ }
866
876
  }
867
- return await db.multiDelete(idsByTable);
877
+ return await db.multiDelete(idsByTable, opt);
868
878
  }
869
879
  static async multiSave(inputs, opt = {}) {
870
880
  if (!inputs.length)
@@ -188,6 +188,7 @@ export interface CommonDBSupport {
188
188
  bufferValues?: boolean;
189
189
  nullValues?: boolean;
190
190
  transactions?: boolean;
191
+ createTransaction?: boolean;
191
192
  timeMachine?: boolean;
192
193
  multiTableOperations?: boolean;
193
194
  }
@@ -20,6 +20,7 @@ export const commonDBFullSupport = {
20
20
  bufferValues: true,
21
21
  nullValues: true,
22
22
  transactions: true,
23
+ createTransaction: true,
23
24
  timeMachine: true,
24
25
  multiTableOperations: true,
25
26
  };
@@ -263,36 +263,38 @@ export async function runCommonDaoTest(db, quirks = {}) {
263
263
  const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
264
264
  expectMatch(expected, rows, quirks);
265
265
  });
266
- test('createTransaction happy path', async () => {
267
- // cleanup
268
- await dao.query().deleteByQuery();
269
- // Test that id, created, updated are created
270
- const now = localTime.nowUnix();
271
- const row = _omit(item1, ['id', 'created', 'updated']);
272
- let tx = await dao.createTransaction();
273
- await tx.save(dao, row);
274
- await tx.commit();
275
- const loaded = await dao.query().runQuery();
276
- expect(loaded.length).toBe(1);
277
- expect(loaded[0].id).toBeDefined();
278
- expect(loaded[0].created).toBeGreaterThanOrEqual(now);
279
- expect(loaded[0].updated).toBe(loaded[0].created);
280
- tx = await dao.createTransaction();
281
- await tx.deleteById(dao, loaded[0].id);
282
- await tx.commit();
283
- // saveBatch [item1, 2, 3]
284
- // save item3 with k1: k1_mod
285
- // delete item2
286
- // remaining: item1, item3_with_k1_mod
287
- tx = await dao.createTransaction();
288
- await tx.saveBatch(dao, items);
289
- await tx.save(dao, { ...items[2], k1: 'k1_mod' });
290
- await tx.deleteById(dao, items[1].id);
291
- await tx.commit();
292
- const rows = await dao.query().runQuery();
293
- const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
294
- expectMatch(expected, rows, quirks);
295
- });
266
+ if (support.createTransaction) {
267
+ test('createTransaction happy path', async () => {
268
+ // cleanup
269
+ await dao.query().deleteByQuery();
270
+ // Test that id, created, updated are created
271
+ const now = localTime.nowUnix();
272
+ const row = _omit(item1, ['id', 'created', 'updated']);
273
+ let tx = await dao.createTransaction();
274
+ await tx.save(dao, row);
275
+ await tx.commit();
276
+ const loaded = await dao.query().runQuery();
277
+ expect(loaded.length).toBe(1);
278
+ expect(loaded[0].id).toBeDefined();
279
+ expect(loaded[0].created).toBeGreaterThanOrEqual(now);
280
+ expect(loaded[0].updated).toBe(loaded[0].created);
281
+ tx = await dao.createTransaction();
282
+ await tx.deleteById(dao, loaded[0].id);
283
+ await tx.commit();
284
+ // saveBatch [item1, 2, 3]
285
+ // save item3 with k1: k1_mod
286
+ // delete item2
287
+ // remaining: item1, item3_with_k1_mod
288
+ tx = await dao.createTransaction();
289
+ await tx.saveBatch(dao, items);
290
+ await tx.save(dao, { ...items[2], k1: 'k1_mod' });
291
+ await tx.deleteById(dao, items[1].id);
292
+ await tx.commit();
293
+ const rows = await dao.query().runQuery();
294
+ const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
295
+ expectMatch(expected, rows, quirks);
296
+ });
297
+ }
296
298
  test('transaction rollback', async () => {
297
299
  const expected = await prepare();
298
300
  let err;
@@ -310,23 +312,25 @@ export async function runCommonDaoTest(db, quirks = {}) {
310
312
  const rows = await dao.query().runQuery();
311
313
  expectMatch(expected, rows, quirks);
312
314
  });
313
- test('createTransaction rollback', async () => {
314
- const expected = await prepare();
315
- let err;
316
- try {
317
- const tx = await dao.createTransaction();
318
- await tx.deleteById(dao, items[2].id);
319
- await tx.save(dao, { ...items[0], k1: 5 }); // it should fail here
320
- await tx.commit();
321
- }
322
- catch (err_) {
323
- err = err_;
324
- }
325
- expect(err).toBeDefined();
326
- expect(err).toBeInstanceOf(Error);
327
- const rows = await dao.query().runQuery();
328
- expectMatch(expected, rows, quirks);
329
- });
315
+ if (support.createTransaction) {
316
+ test('createTransaction rollback', async () => {
317
+ const expected = await prepare();
318
+ let err;
319
+ try {
320
+ const tx = await dao.createTransaction();
321
+ await tx.deleteById(dao, items[2].id);
322
+ await tx.save(dao, { ...items[0], k1: 5 }); // it should fail here
323
+ await tx.commit();
324
+ }
325
+ catch (err_) {
326
+ err = err_;
327
+ }
328
+ expect(err).toBeDefined();
329
+ expect(err).toBeInstanceOf(Error);
330
+ const rows = await dao.query().runQuery();
331
+ expectMatch(expected, rows, quirks);
332
+ });
333
+ }
330
334
  if (support.queries) {
331
335
  test('transaction cleanup', async () => {
332
336
  await dao.query().deleteByQuery();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/db-lib",
3
3
  "type": "module",
4
- "version": "10.21.0",
4
+ "version": "10.23.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@naturalcycles/nodejs-lib": "^15"
@@ -1139,20 +1139,30 @@ export class CommonDao<
1139
1139
  }
1140
1140
 
1141
1141
  /**
1142
- * Very @experimental.
1142
+ * @experimental.
1143
1143
  */
1144
- static async multiDeleteByIds(
1145
- inputs: DaoWithIds<AnyDao>[],
1146
- _opt: CommonDaoOptions = {},
1144
+ static async multiDelete(
1145
+ inputs: (DaoWithId<AnyDao> | DaoWithIds<AnyDao>)[],
1146
+ opt: CommonDaoOptions = {},
1147
1147
  ): Promise<NonNegativeInteger> {
1148
1148
  if (!inputs.length) return 0
1149
1149
  const { db } = inputs[0]!.dao.cfg
1150
1150
  const idsByTable: StringMap<string[]> = {}
1151
- for (const { dao, ids } of inputs) {
1152
- idsByTable[dao.cfg.table] = ids
1151
+ for (const input of inputs) {
1152
+ const { dao } = input
1153
+ const { table } = dao.cfg
1154
+ dao.requireWriteAccess()
1155
+ dao.requireObjectMutability(opt)
1156
+ idsByTable[table] ||= []
1157
+
1158
+ if ('id' in input) {
1159
+ idsByTable[table].push(input.id)
1160
+ } else {
1161
+ idsByTable[table].push(...input.ids)
1162
+ }
1153
1163
  }
1154
1164
 
1155
- return await db.multiDelete(idsByTable)
1165
+ return await db.multiDelete(idsByTable, opt)
1156
1166
  }
1157
1167
 
1158
1168
  static async multiSave(
@@ -273,6 +273,7 @@ export interface CommonDBSupport {
273
273
  bufferValues?: boolean
274
274
  nullValues?: boolean
275
275
  transactions?: boolean
276
+ createTransaction?: boolean
276
277
  timeMachine?: boolean
277
278
  multiTableOperations?: boolean
278
279
  }
@@ -294,6 +295,7 @@ export const commonDBFullSupport: Required<CommonDBSupport> = {
294
295
  bufferValues: true,
295
296
  nullValues: true,
296
297
  transactions: true,
298
+ createTransaction: true,
297
299
  timeMachine: true,
298
300
  multiTableOperations: true,
299
301
  }
@@ -358,42 +358,44 @@ export async function runCommonDaoTest(
358
358
  expectMatch(expected, rows, quirks)
359
359
  })
360
360
 
361
- test('createTransaction happy path', async () => {
362
- // cleanup
363
- await dao.query().deleteByQuery()
361
+ if (support.createTransaction) {
362
+ test('createTransaction happy path', async () => {
363
+ // cleanup
364
+ await dao.query().deleteByQuery()
364
365
 
365
- // Test that id, created, updated are created
366
- const now = localTime.nowUnix()
366
+ // Test that id, created, updated are created
367
+ const now = localTime.nowUnix()
367
368
 
368
- const row = _omit(item1, ['id', 'created', 'updated'])
369
- let tx = await dao.createTransaction()
370
- await tx.save(dao, row)
371
- await tx.commit()
369
+ const row = _omit(item1, ['id', 'created', 'updated'])
370
+ let tx = await dao.createTransaction()
371
+ await tx.save(dao, row)
372
+ await tx.commit()
372
373
 
373
- const loaded = await dao.query().runQuery()
374
- expect(loaded.length).toBe(1)
375
- expect(loaded[0]!.id).toBeDefined()
376
- expect(loaded[0]!.created).toBeGreaterThanOrEqual(now)
377
- expect(loaded[0]!.updated).toBe(loaded[0]!.created)
374
+ const loaded = await dao.query().runQuery()
375
+ expect(loaded.length).toBe(1)
376
+ expect(loaded[0]!.id).toBeDefined()
377
+ expect(loaded[0]!.created).toBeGreaterThanOrEqual(now)
378
+ expect(loaded[0]!.updated).toBe(loaded[0]!.created)
378
379
 
379
- tx = await dao.createTransaction()
380
- await tx.deleteById(dao, loaded[0]!.id)
381
- await tx.commit()
380
+ tx = await dao.createTransaction()
381
+ await tx.deleteById(dao, loaded[0]!.id)
382
+ await tx.commit()
382
383
 
383
- // saveBatch [item1, 2, 3]
384
- // save item3 with k1: k1_mod
385
- // delete item2
386
- // remaining: item1, item3_with_k1_mod
387
- tx = await dao.createTransaction()
388
- await tx.saveBatch(dao, items)
389
- await tx.save(dao, { ...items[2]!, k1: 'k1_mod' })
390
- await tx.deleteById(dao, items[1]!.id)
391
- await tx.commit()
384
+ // saveBatch [item1, 2, 3]
385
+ // save item3 with k1: k1_mod
386
+ // delete item2
387
+ // remaining: item1, item3_with_k1_mod
388
+ tx = await dao.createTransaction()
389
+ await tx.saveBatch(dao, items)
390
+ await tx.save(dao, { ...items[2]!, k1: 'k1_mod' })
391
+ await tx.deleteById(dao, items[1]!.id)
392
+ await tx.commit()
392
393
 
393
- const rows = await dao.query().runQuery()
394
- const expected = [items[0], { ...items[2]!, k1: 'k1_mod' }]
395
- expectMatch(expected, rows, quirks)
396
- })
394
+ const rows = await dao.query().runQuery()
395
+ const expected = [items[0], { ...items[2]!, k1: 'k1_mod' }]
396
+ expectMatch(expected, rows, quirks)
397
+ })
398
+ }
397
399
 
398
400
  test('transaction rollback', async () => {
399
401
  const expected = await prepare()
@@ -416,25 +418,27 @@ export async function runCommonDaoTest(
416
418
  expectMatch(expected, rows, quirks)
417
419
  })
418
420
 
419
- test('createTransaction rollback', async () => {
420
- const expected = await prepare()
421
+ if (support.createTransaction) {
422
+ test('createTransaction rollback', async () => {
423
+ const expected = await prepare()
421
424
 
422
- let err: any
423
- try {
424
- const tx = await dao.createTransaction()
425
- await tx.deleteById(dao, items[2]!.id)
426
- await tx.save(dao, { ...items[0]!, k1: 5 as any }) // it should fail here
427
- await tx.commit()
428
- } catch (err_) {
429
- err = err_
430
- }
425
+ let err: any
426
+ try {
427
+ const tx = await dao.createTransaction()
428
+ await tx.deleteById(dao, items[2]!.id)
429
+ await tx.save(dao, { ...items[0]!, k1: 5 as any }) // it should fail here
430
+ await tx.commit()
431
+ } catch (err_) {
432
+ err = err_
433
+ }
431
434
 
432
- expect(err).toBeDefined()
433
- expect(err).toBeInstanceOf(Error)
435
+ expect(err).toBeDefined()
436
+ expect(err).toBeInstanceOf(Error)
434
437
 
435
- const rows = await dao.query().runQuery()
436
- expectMatch(expected, rows, quirks)
437
- })
438
+ const rows = await dao.query().runQuery()
439
+ expectMatch(expected, rows, quirks)
440
+ })
441
+ }
438
442
 
439
443
  if (support.queries) {
440
444
  test('transaction cleanup', async () => {