@naturalcycles/db-lib 8.55.1 → 8.56.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.
|
@@ -4,7 +4,7 @@ import { AnyObject, AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectW
|
|
|
4
4
|
import { AjvSchema, ObjectSchema, ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
5
5
|
import { DBDeleteByIdsOperation, DBModelType, DBOperation, DBPatch, DBSaveBatchOperation, RunQueryResult } from '../db.model';
|
|
6
6
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
|
|
7
|
-
import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
|
|
7
|
+
import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveBatchOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
|
|
8
8
|
/**
|
|
9
9
|
* Lowest common denominator API between supported Databases.
|
|
10
10
|
*
|
|
@@ -86,28 +86,38 @@ export declare class CommonDao<BM extends Partial<ObjectWithId<ID>>, DBM extends
|
|
|
86
86
|
assignIdCreatedUpdated(obj: BM, opt?: CommonDaoOptions): Saved<BM>;
|
|
87
87
|
assignIdCreatedUpdated(obj: Unsaved<BM>, opt?: CommonDaoOptions): Saved<BM>;
|
|
88
88
|
tx: {
|
|
89
|
-
save: (bm: Unsaved<BM>, opt?:
|
|
90
|
-
saveBatch: (bms: Unsaved<BM>[], opt?:
|
|
89
|
+
save: (bm: Unsaved<BM>, opt?: CommonDaoSaveBatchOptions<DBM>) => Promise<DBSaveBatchOperation | undefined>;
|
|
90
|
+
saveBatch: (bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>) => Promise<DBSaveBatchOperation | undefined>;
|
|
91
91
|
deleteByIds: (ids: ID[], opt?: CommonDaoOptions) => Promise<DBDeleteByIdsOperation | undefined>;
|
|
92
92
|
deleteById: (id: ID | null | undefined, opt?: CommonDaoOptions) => Promise<DBDeleteByIdsOperation | undefined>;
|
|
93
93
|
};
|
|
94
94
|
/**
|
|
95
95
|
* Mutates with id, created, updated
|
|
96
96
|
*/
|
|
97
|
-
save(bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>>;
|
|
97
|
+
save(bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<Saved<BM>>;
|
|
98
98
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* Saves (as fast as possible) with the Patch applied.
|
|
99
|
+
* 1. Applies the patch
|
|
100
|
+
* 2. If object is the same after patching - skips saving it
|
|
101
|
+
* 3. Otherwise - saves the patched object and returns it
|
|
103
102
|
*
|
|
104
|
-
*
|
|
103
|
+
* Similar to `save` with skipIfEquals.
|
|
104
|
+
* Similar to `patch`, but doesn't load the object from the Database.
|
|
105
|
+
*/
|
|
106
|
+
savePatch(bm: Saved<BM>, patch: Partial<BM>, opt: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>>;
|
|
107
|
+
/**
|
|
108
|
+
* Convenience method to replace 3 operations (loading+patching+saving) with one:
|
|
109
|
+
*
|
|
110
|
+
* 1. Loads the row by id.
|
|
111
|
+
* 1.1 Creates the row (via this.create()) if it doesn't exist
|
|
112
|
+
* (this will cause a validation error if Patch has not enough data for the row to be valid).
|
|
113
|
+
* 2. Applies the patch on top of loaded data.
|
|
114
|
+
* 3. Saves (as fast as possible since the read) with the Patch applied.
|
|
105
115
|
*/
|
|
106
|
-
patch(id: ID, patch: Partial<BM>, opt?:
|
|
107
|
-
patchAsDBM(id: ID, patch: Partial<DBM>, opt?:
|
|
108
|
-
saveAsDBM(dbm: DBM, opt?:
|
|
109
|
-
saveBatch(bms: Unsaved<BM>[], opt?:
|
|
110
|
-
saveBatchAsDBM(dbms: DBM[], opt?:
|
|
116
|
+
patch(id: ID, patch: Partial<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>>;
|
|
117
|
+
patchAsDBM(id: ID, patch: Partial<DBM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM>;
|
|
118
|
+
saveAsDBM(dbm: DBM, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM>;
|
|
119
|
+
saveBatch(bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>[]>;
|
|
120
|
+
saveBatchAsDBM(dbms: DBM[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM[]>;
|
|
111
121
|
/**
|
|
112
122
|
* "Streaming" is implemented by buffering incoming rows into **batches**
|
|
113
123
|
* (of size opt.batchSize, which defaults to 500),
|
|
@@ -555,6 +555,10 @@ class CommonDao {
|
|
|
555
555
|
*/
|
|
556
556
|
async save(bm, opt = {}) {
|
|
557
557
|
this.requireWriteAccess();
|
|
558
|
+
if (opt.skipIfEquals && (0, js_lib_1._deepJsonEquals)(bm, opt.skipIfEquals)) {
|
|
559
|
+
// Skipping the save operation
|
|
560
|
+
return bm;
|
|
561
|
+
}
|
|
558
562
|
const idWasGenerated = !bm.id && this.cfg.createId;
|
|
559
563
|
this.assignIdCreatedUpdated(bm, opt); // mutates
|
|
560
564
|
let dbm = await this.bmToDBM(bm, opt);
|
|
@@ -589,26 +593,70 @@ class CommonDao {
|
|
|
589
593
|
return bm;
|
|
590
594
|
}
|
|
591
595
|
/**
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
* Saves (as fast as possible) with the Patch applied.
|
|
596
|
+
* 1. Applies the patch
|
|
597
|
+
* 2. If object is the same after patching - skips saving it
|
|
598
|
+
* 3. Otherwise - saves the patched object and returns it
|
|
596
599
|
*
|
|
597
|
-
*
|
|
600
|
+
* Similar to `save` with skipIfEquals.
|
|
601
|
+
* Similar to `patch`, but doesn't load the object from the Database.
|
|
598
602
|
*/
|
|
599
|
-
async
|
|
600
|
-
|
|
601
|
-
...
|
|
603
|
+
async savePatch(bm, patch, opt) {
|
|
604
|
+
const patched = {
|
|
605
|
+
...bm,
|
|
602
606
|
...patch,
|
|
603
|
-
}
|
|
607
|
+
};
|
|
608
|
+
if ((0, js_lib_1._deepJsonEquals)(bm, patched)) {
|
|
609
|
+
// Skipping the save operation, as data is the same
|
|
610
|
+
return bm;
|
|
611
|
+
}
|
|
612
|
+
// Actually apply the patch by mutating the original object (by design)
|
|
613
|
+
Object.assign(bm, patch);
|
|
614
|
+
return await this.save(bm, opt);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Convenience method to replace 3 operations (loading+patching+saving) with one:
|
|
618
|
+
*
|
|
619
|
+
* 1. Loads the row by id.
|
|
620
|
+
* 1.1 Creates the row (via this.create()) if it doesn't exist
|
|
621
|
+
* (this will cause a validation error if Patch has not enough data for the row to be valid).
|
|
622
|
+
* 2. Applies the patch on top of loaded data.
|
|
623
|
+
* 3. Saves (as fast as possible since the read) with the Patch applied.
|
|
624
|
+
*/
|
|
625
|
+
async patch(id, patch, opt = {}) {
|
|
626
|
+
const bm = await this.getById(id, opt);
|
|
627
|
+
let patched;
|
|
628
|
+
if (bm) {
|
|
629
|
+
patched = {
|
|
630
|
+
...bm,
|
|
631
|
+
...patch,
|
|
632
|
+
};
|
|
633
|
+
if ((0, js_lib_1._deepJsonEquals)(bm, patched)) {
|
|
634
|
+
// Skipping the save operation, as data is the same
|
|
635
|
+
return bm;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
patched = this.create({ ...patch, id }, opt);
|
|
640
|
+
}
|
|
641
|
+
return await this.save(patched, opt);
|
|
604
642
|
}
|
|
605
643
|
async patchAsDBM(id, patch, opt = {}) {
|
|
606
|
-
const dbm =
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
644
|
+
const dbm = await this.getByIdAsDBM(id, opt);
|
|
645
|
+
let patched;
|
|
646
|
+
if (dbm) {
|
|
647
|
+
patched = {
|
|
648
|
+
...dbm,
|
|
649
|
+
...patch,
|
|
650
|
+
};
|
|
651
|
+
if ((0, js_lib_1._deepJsonEquals)(dbm, patched)) {
|
|
652
|
+
// Skipping the save operation, as data is the same
|
|
653
|
+
return dbm;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
patched = this.create({ ...patch, id }, opt);
|
|
658
|
+
}
|
|
659
|
+
return await this.saveAsDBM(patched, opt);
|
|
612
660
|
}
|
|
613
661
|
async saveAsDBM(dbm, opt = {}) {
|
|
614
662
|
this.requireWriteAccess();
|
|
@@ -237,10 +237,21 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
237
237
|
*/
|
|
238
238
|
tx?: boolean;
|
|
239
239
|
}
|
|
240
|
+
export interface CommonDaoSaveOptions<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId> extends CommonDaoSaveBatchOptions<DBM> {
|
|
241
|
+
/**
|
|
242
|
+
* If provided - a check will be made.
|
|
243
|
+
* If the object for saving equals to the object passed to `skipIfEquals` - save operation will be skipped.
|
|
244
|
+
*
|
|
245
|
+
* Equality is checked with _deepJsonEquals (aka "deep equals after JSON.stringify/parse", which removes keys with undefined values).
|
|
246
|
+
*
|
|
247
|
+
* It's supposed to be used to prevent "unnecessary saves", when data is not changed.
|
|
248
|
+
*/
|
|
249
|
+
skipIfEquals?: BM;
|
|
250
|
+
}
|
|
240
251
|
/**
|
|
241
252
|
* All properties default to undefined.
|
|
242
253
|
*/
|
|
243
|
-
export interface
|
|
254
|
+
export interface CommonDaoSaveBatchOptions<DBM extends ObjectWithId> extends CommonDaoOptions, CommonDBSaveOptions<DBM> {
|
|
244
255
|
/**
|
|
245
256
|
* @default false
|
|
246
257
|
*
|
|
@@ -254,7 +265,7 @@ export interface CommonDaoSaveOptions<DBM extends ObjectWithId> extends CommonDa
|
|
|
254
265
|
}
|
|
255
266
|
export interface CommonDaoStreamDeleteOptions<DBM extends ObjectWithId> extends CommonDaoStreamOptions<DBM> {
|
|
256
267
|
}
|
|
257
|
-
export interface CommonDaoStreamSaveOptions<DBM extends ObjectWithId> extends
|
|
268
|
+
export interface CommonDaoStreamSaveOptions<DBM extends ObjectWithId> extends CommonDaoSaveBatchOptions<DBM>, CommonDaoStreamOptions<DBM> {
|
|
258
269
|
}
|
|
259
270
|
export interface CommonDaoStreamForEachOptions<IN> extends CommonDaoStreamOptions<IN>, TransformMapOptions<IN, any> {
|
|
260
271
|
}
|
package/package.json
CHANGED
|
@@ -298,10 +298,23 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
298
298
|
tx?: boolean
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
export interface CommonDaoSaveOptions<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>
|
|
302
|
+
extends CommonDaoSaveBatchOptions<DBM> {
|
|
303
|
+
/**
|
|
304
|
+
* If provided - a check will be made.
|
|
305
|
+
* If the object for saving equals to the object passed to `skipIfEquals` - save operation will be skipped.
|
|
306
|
+
*
|
|
307
|
+
* Equality is checked with _deepJsonEquals (aka "deep equals after JSON.stringify/parse", which removes keys with undefined values).
|
|
308
|
+
*
|
|
309
|
+
* It's supposed to be used to prevent "unnecessary saves", when data is not changed.
|
|
310
|
+
*/
|
|
311
|
+
skipIfEquals?: BM
|
|
312
|
+
}
|
|
313
|
+
|
|
301
314
|
/**
|
|
302
315
|
* All properties default to undefined.
|
|
303
316
|
*/
|
|
304
|
-
export interface
|
|
317
|
+
export interface CommonDaoSaveBatchOptions<DBM extends ObjectWithId>
|
|
305
318
|
extends CommonDaoOptions,
|
|
306
319
|
CommonDBSaveOptions<DBM> {
|
|
307
320
|
/**
|
|
@@ -320,7 +333,7 @@ export interface CommonDaoStreamDeleteOptions<DBM extends ObjectWithId>
|
|
|
320
333
|
extends CommonDaoStreamOptions<DBM> {}
|
|
321
334
|
|
|
322
335
|
export interface CommonDaoStreamSaveOptions<DBM extends ObjectWithId>
|
|
323
|
-
extends
|
|
336
|
+
extends CommonDaoSaveBatchOptions<DBM>,
|
|
324
337
|
CommonDaoStreamOptions<DBM> {}
|
|
325
338
|
|
|
326
339
|
export interface CommonDaoStreamForEachOptions<IN>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Transform } from 'node:stream'
|
|
2
2
|
import {
|
|
3
3
|
_assert,
|
|
4
|
+
_deepJsonEquals,
|
|
4
5
|
_filterNullishValues,
|
|
5
6
|
_filterUndefinedValues,
|
|
6
7
|
_isTruthy,
|
|
@@ -57,6 +58,7 @@ import {
|
|
|
57
58
|
CommonDaoHooks,
|
|
58
59
|
CommonDaoLogLevel,
|
|
59
60
|
CommonDaoOptions,
|
|
61
|
+
CommonDaoSaveBatchOptions,
|
|
60
62
|
CommonDaoSaveOptions,
|
|
61
63
|
CommonDaoStreamDeleteOptions,
|
|
62
64
|
CommonDaoStreamForEachOptions,
|
|
@@ -697,7 +699,7 @@ export class CommonDao<
|
|
|
697
699
|
tx = {
|
|
698
700
|
save: async (
|
|
699
701
|
bm: Unsaved<BM>,
|
|
700
|
-
opt:
|
|
702
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
701
703
|
): Promise<DBSaveBatchOperation | undefined> => {
|
|
702
704
|
// .save actually returns DBM (not BM) when it detects `opt.tx === true`
|
|
703
705
|
const row: DBM | null = (await this.save(bm, { ...opt, tx: true })) as any
|
|
@@ -715,7 +717,7 @@ export class CommonDao<
|
|
|
715
717
|
},
|
|
716
718
|
saveBatch: async (
|
|
717
719
|
bms: Unsaved<BM>[],
|
|
718
|
-
opt:
|
|
720
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
719
721
|
): Promise<DBSaveBatchOperation | undefined> => {
|
|
720
722
|
const rows: DBM[] = (await this.saveBatch(bms, { ...opt, tx: true })) as any
|
|
721
723
|
if (!rows.length) return
|
|
@@ -760,8 +762,14 @@ export class CommonDao<
|
|
|
760
762
|
/**
|
|
761
763
|
* Mutates with id, created, updated
|
|
762
764
|
*/
|
|
763
|
-
async save(bm: Unsaved<BM>, opt: CommonDaoSaveOptions<DBM> = {}): Promise<Saved<BM>> {
|
|
765
|
+
async save(bm: Unsaved<BM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<Saved<BM>> {
|
|
764
766
|
this.requireWriteAccess()
|
|
767
|
+
|
|
768
|
+
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
769
|
+
// Skipping the save operation
|
|
770
|
+
return bm as Saved<BM>
|
|
771
|
+
}
|
|
772
|
+
|
|
765
773
|
const idWasGenerated = !bm.id && this.cfg.createId
|
|
766
774
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
767
775
|
let dbm = await this.bmToDBM(bm as BM, opt)
|
|
@@ -801,38 +809,94 @@ export class CommonDao<
|
|
|
801
809
|
}
|
|
802
810
|
|
|
803
811
|
/**
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
812
|
+
* 1. Applies the patch
|
|
813
|
+
* 2. If object is the same after patching - skips saving it
|
|
814
|
+
* 3. Otherwise - saves the patched object and returns it
|
|
815
|
+
*
|
|
816
|
+
* Similar to `save` with skipIfEquals.
|
|
817
|
+
* Similar to `patch`, but doesn't load the object from the Database.
|
|
818
|
+
*/
|
|
819
|
+
async savePatch(
|
|
820
|
+
bm: Saved<BM>,
|
|
821
|
+
patch: Partial<BM>,
|
|
822
|
+
opt: CommonDaoSaveBatchOptions<DBM>,
|
|
823
|
+
): Promise<Saved<BM>> {
|
|
824
|
+
const patched: Saved<BM> = {
|
|
825
|
+
...bm,
|
|
826
|
+
...patch,
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (_deepJsonEquals(bm, patched)) {
|
|
830
|
+
// Skipping the save operation, as data is the same
|
|
831
|
+
return bm
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Actually apply the patch by mutating the original object (by design)
|
|
835
|
+
Object.assign(bm, patch)
|
|
836
|
+
|
|
837
|
+
return await this.save(bm, opt)
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* Convenience method to replace 3 operations (loading+patching+saving) with one:
|
|
808
842
|
*
|
|
809
|
-
*
|
|
843
|
+
* 1. Loads the row by id.
|
|
844
|
+
* 1.1 Creates the row (via this.create()) if it doesn't exist
|
|
845
|
+
* (this will cause a validation error if Patch has not enough data for the row to be valid).
|
|
846
|
+
* 2. Applies the patch on top of loaded data.
|
|
847
|
+
* 3. Saves (as fast as possible since the read) with the Patch applied.
|
|
810
848
|
*/
|
|
811
|
-
async patch(
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
849
|
+
async patch(
|
|
850
|
+
id: ID,
|
|
851
|
+
patch: Partial<BM>,
|
|
852
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
853
|
+
): Promise<Saved<BM>> {
|
|
854
|
+
const bm = await this.getById(id, opt)
|
|
855
|
+
let patched: Saved<BM>
|
|
856
|
+
|
|
857
|
+
if (bm) {
|
|
858
|
+
patched = {
|
|
859
|
+
...bm,
|
|
815
860
|
...patch,
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
if (_deepJsonEquals(bm, patched)) {
|
|
864
|
+
// Skipping the save operation, as data is the same
|
|
865
|
+
return bm
|
|
866
|
+
}
|
|
867
|
+
} else {
|
|
868
|
+
patched = this.create({ ...patch, id }, opt)
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return await this.save(patched, opt)
|
|
819
872
|
}
|
|
820
873
|
|
|
821
|
-
async patchAsDBM(
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
874
|
+
async patchAsDBM(
|
|
875
|
+
id: ID,
|
|
876
|
+
patch: Partial<DBM>,
|
|
877
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
878
|
+
): Promise<DBM> {
|
|
879
|
+
const dbm = await this.getByIdAsDBM(id, opt)
|
|
880
|
+
let patched: DBM
|
|
825
881
|
|
|
826
|
-
|
|
827
|
-
{
|
|
882
|
+
if (dbm) {
|
|
883
|
+
patched = {
|
|
828
884
|
...dbm,
|
|
829
885
|
...patch,
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
if (_deepJsonEquals(dbm, patched)) {
|
|
889
|
+
// Skipping the save operation, as data is the same
|
|
890
|
+
return dbm
|
|
891
|
+
}
|
|
892
|
+
} else {
|
|
893
|
+
patched = this.create({ ...patch, id } as Partial<BM>, opt) as any as DBM
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
return await this.saveAsDBM(patched, opt)
|
|
833
897
|
}
|
|
834
898
|
|
|
835
|
-
async saveAsDBM(dbm: DBM, opt:
|
|
899
|
+
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM> {
|
|
836
900
|
this.requireWriteAccess()
|
|
837
901
|
const table = opt.table || this.cfg.table
|
|
838
902
|
|
|
@@ -872,7 +936,10 @@ export class CommonDao<
|
|
|
872
936
|
return row
|
|
873
937
|
}
|
|
874
938
|
|
|
875
|
-
async saveBatch(
|
|
939
|
+
async saveBatch(
|
|
940
|
+
bms: Unsaved<BM>[],
|
|
941
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
942
|
+
): Promise<Saved<BM>[]> {
|
|
876
943
|
if (!bms.length) return []
|
|
877
944
|
this.requireWriteAccess()
|
|
878
945
|
const table = opt.table || this.cfg.table
|
|
@@ -920,7 +987,7 @@ export class CommonDao<
|
|
|
920
987
|
return bms as any[]
|
|
921
988
|
}
|
|
922
989
|
|
|
923
|
-
async saveBatchAsDBM(dbms: DBM[], opt:
|
|
990
|
+
async saveBatchAsDBM(dbms: DBM[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM[]> {
|
|
924
991
|
if (!dbms.length) return []
|
|
925
992
|
this.requireWriteAccess()
|
|
926
993
|
const table = opt.table || this.cfg.table
|