@naturalcycles/db-lib 9.6.0 → 9.7.1
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/dist/commondao/common.dao.d.ts +16 -11
- package/dist/commondao/common.dao.js +67 -77
- package/package.json +2 -2
- package/src/commondao/common.dao.ts +78 -93
|
@@ -19,7 +19,6 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
19
19
|
getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
|
|
20
20
|
getById(id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
|
|
21
21
|
getByIdOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<BM>;
|
|
22
|
-
getByIdAsDBMOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
|
|
23
22
|
getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
|
|
24
23
|
getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>;
|
|
25
24
|
getByIds(ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
|
|
@@ -79,10 +78,6 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
79
78
|
* "Returns", just to have a type of "Saved"
|
|
80
79
|
*/
|
|
81
80
|
assignIdCreatedUpdated<T extends BaseDBEntity>(obj: Partial<T>, opt?: CommonDaoOptions): T;
|
|
82
|
-
/**
|
|
83
|
-
* Mutates with id, created, updated
|
|
84
|
-
*/
|
|
85
|
-
save(bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
|
|
86
81
|
/**
|
|
87
82
|
* 1. Applies the patch
|
|
88
83
|
* 2. If object is the same after patching - skips saving it
|
|
@@ -117,7 +112,11 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
117
112
|
* Like patch, but runs all operations within a Transaction.
|
|
118
113
|
*/
|
|
119
114
|
patchInTransaction(bm: BM, patch: Partial<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM>;
|
|
120
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Mutates with id, created, updated
|
|
117
|
+
*/
|
|
118
|
+
save(bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
|
|
119
|
+
saveAsDBM(dbm: Unsaved<DBM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<DBM>;
|
|
121
120
|
saveBatch(bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM[]>;
|
|
122
121
|
saveBatchAsDBM(dbms: Unsaved<DBM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM[]>;
|
|
123
122
|
/**
|
|
@@ -130,7 +129,6 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
130
129
|
/**
|
|
131
130
|
* @returns number of deleted items
|
|
132
131
|
*/
|
|
133
|
-
deleteById(id: undefined | null, opt?: CommonDaoOptions): Promise<0>;
|
|
134
132
|
deleteById(id?: string | null, opt?: CommonDaoOptions): Promise<number>;
|
|
135
133
|
deleteByIds(ids: string[], opt?: CommonDaoOptions): Promise<number>;
|
|
136
134
|
/**
|
|
@@ -156,10 +154,9 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
156
154
|
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM;
|
|
157
155
|
anyToDBMs(entities: DBM[], opt?: CommonDaoOptions): DBM[];
|
|
158
156
|
/**
|
|
159
|
-
* Returns *converted value
|
|
160
|
-
* Validates (unless `skipValidation=true` passed).
|
|
161
|
-
*
|
|
157
|
+
* Returns *converted value* (NOT the same reference).
|
|
162
158
|
* Does NOT mutate the object.
|
|
159
|
+
* Validates (unless `skipValidation=true` passed).
|
|
163
160
|
*/
|
|
164
161
|
validateAndConvert<T>(obj: Partial<T>, schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined, opt?: CommonDaoOptions): any;
|
|
165
162
|
getTableSchema(): Promise<JsonSchemaRootObject<DBM>>;
|
|
@@ -194,8 +191,16 @@ export declare class CommonDaoTransaction {
|
|
|
194
191
|
rollback(): Promise<void>;
|
|
195
192
|
getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
|
|
196
193
|
getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
|
|
197
|
-
save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: Unsaved<BM>, opt?:
|
|
194
|
+
save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
|
|
198
195
|
saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM[]>;
|
|
196
|
+
/**
|
|
197
|
+
* DaoTransaction.patch does not load from DB.
|
|
198
|
+
* It assumes the bm was previously loaded in the same Transaction, hence could not be
|
|
199
|
+
* concurrently modified. Hence it's safe to not sync with DB.
|
|
200
|
+
*
|
|
201
|
+
* So, this method is a rather simple convenience "Object.assign and then save".
|
|
202
|
+
*/
|
|
203
|
+
patch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: BM, patch: Partial<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
|
|
199
204
|
deleteById(dao: CommonDao<any>, id?: string | null, opt?: CommonDaoOptions): Promise<number>;
|
|
200
205
|
deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number>;
|
|
201
206
|
}
|
|
@@ -71,13 +71,6 @@ class CommonDao {
|
|
|
71
71
|
return bm;
|
|
72
72
|
return this.create({ ...part, id }, opt);
|
|
73
73
|
}
|
|
74
|
-
async getByIdAsDBMOrEmpty(id, part = {}, opt) {
|
|
75
|
-
const dbm = await this.getByIdAsDBM(id, opt);
|
|
76
|
-
if (dbm)
|
|
77
|
-
return dbm;
|
|
78
|
-
const bm = this.create({ ...part, id }, opt);
|
|
79
|
-
return await this.bmToDBM(bm, opt);
|
|
80
|
-
}
|
|
81
74
|
async getByIdAsDBM(id, opt = {}) {
|
|
82
75
|
if (!id)
|
|
83
76
|
return null;
|
|
@@ -451,45 +444,6 @@ class CommonDao {
|
|
|
451
444
|
return obj;
|
|
452
445
|
}
|
|
453
446
|
// SAVE
|
|
454
|
-
/**
|
|
455
|
-
* Mutates with id, created, updated
|
|
456
|
-
*/
|
|
457
|
-
async save(bm, opt = {}) {
|
|
458
|
-
this.requireWriteAccess();
|
|
459
|
-
if (opt.skipIfEquals && (0, js_lib_1._deepJsonEquals)(bm, opt.skipIfEquals)) {
|
|
460
|
-
// Skipping the save operation
|
|
461
|
-
return bm;
|
|
462
|
-
}
|
|
463
|
-
const idWasGenerated = !bm.id && this.cfg.generateId;
|
|
464
|
-
this.assignIdCreatedUpdated(bm, opt); // mutates
|
|
465
|
-
(0, js_lib_1._typeCast)(bm);
|
|
466
|
-
let dbm = await this.bmToDBM(bm, opt); // validates BM
|
|
467
|
-
if (this.cfg.hooks.beforeSave) {
|
|
468
|
-
dbm = (await this.cfg.hooks.beforeSave(dbm));
|
|
469
|
-
if (dbm === null)
|
|
470
|
-
return bm;
|
|
471
|
-
}
|
|
472
|
-
const table = opt.table || this.cfg.table;
|
|
473
|
-
if (opt.ensureUniqueId && idWasGenerated)
|
|
474
|
-
await this.ensureUniqueId(table, dbm);
|
|
475
|
-
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
476
|
-
opt = { ...opt, saveMethod: 'insert' };
|
|
477
|
-
}
|
|
478
|
-
const op = `save(${dbm.id})`;
|
|
479
|
-
const started = this.logSaveStarted(op, bm, table);
|
|
480
|
-
const { excludeFromIndexes } = this.cfg;
|
|
481
|
-
const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds;
|
|
482
|
-
await (opt.tx || this.cfg.db).saveBatch(table, [dbm], {
|
|
483
|
-
excludeFromIndexes,
|
|
484
|
-
assignGeneratedIds,
|
|
485
|
-
...opt,
|
|
486
|
-
});
|
|
487
|
-
if (assignGeneratedIds) {
|
|
488
|
-
bm.id = dbm.id;
|
|
489
|
-
}
|
|
490
|
-
this.logSaveResult(started, op, table);
|
|
491
|
-
return bm;
|
|
492
|
-
}
|
|
493
447
|
/**
|
|
494
448
|
* 1. Applies the patch
|
|
495
449
|
* 2. If object is the same after patching - skips saving it
|
|
@@ -585,6 +539,51 @@ class CommonDao {
|
|
|
585
539
|
return await this.patch(bm, patch, { ...opt, tx: daoTx.tx });
|
|
586
540
|
});
|
|
587
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Mutates with id, created, updated
|
|
544
|
+
*/
|
|
545
|
+
async save(bm, opt = {}) {
|
|
546
|
+
this.requireWriteAccess();
|
|
547
|
+
if (opt.skipIfEquals) {
|
|
548
|
+
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
549
|
+
// which should be removed post-validation, but it breaks the "equality check"
|
|
550
|
+
// Post-validation the equality check should work as intended
|
|
551
|
+
const convertedBM = this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
552
|
+
if ((0, js_lib_1._deepJsonEquals)(convertedBM, opt.skipIfEquals)) {
|
|
553
|
+
// Skipping the save operation
|
|
554
|
+
return bm;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const idWasGenerated = !bm.id && this.cfg.generateId;
|
|
558
|
+
this.assignIdCreatedUpdated(bm, opt); // mutates
|
|
559
|
+
(0, js_lib_1._typeCast)(bm);
|
|
560
|
+
let dbm = await this.bmToDBM(bm, opt); // validates BM
|
|
561
|
+
if (this.cfg.hooks.beforeSave) {
|
|
562
|
+
dbm = (await this.cfg.hooks.beforeSave(dbm));
|
|
563
|
+
if (dbm === null)
|
|
564
|
+
return bm;
|
|
565
|
+
}
|
|
566
|
+
const table = opt.table || this.cfg.table;
|
|
567
|
+
if (opt.ensureUniqueId && idWasGenerated)
|
|
568
|
+
await this.ensureUniqueId(table, dbm);
|
|
569
|
+
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
570
|
+
opt = { ...opt, saveMethod: 'insert' };
|
|
571
|
+
}
|
|
572
|
+
const op = `save(${dbm.id})`;
|
|
573
|
+
const started = this.logSaveStarted(op, bm, table);
|
|
574
|
+
const { excludeFromIndexes } = this.cfg;
|
|
575
|
+
const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds;
|
|
576
|
+
await (opt.tx || this.cfg.db).saveBatch(table, [dbm], {
|
|
577
|
+
excludeFromIndexes,
|
|
578
|
+
assignGeneratedIds,
|
|
579
|
+
...opt,
|
|
580
|
+
});
|
|
581
|
+
if (assignGeneratedIds) {
|
|
582
|
+
bm.id = dbm.id;
|
|
583
|
+
}
|
|
584
|
+
this.logSaveResult(started, op, table);
|
|
585
|
+
return bm;
|
|
586
|
+
}
|
|
588
587
|
async saveAsDBM(dbm, opt = {}) {
|
|
589
588
|
this.requireWriteAccess();
|
|
590
589
|
const table = opt.table || this.cfg.table;
|
|
@@ -736,17 +735,14 @@ class CommonDao {
|
|
|
736
735
|
(0, nodejs_lib_1.writableVoid)(),
|
|
737
736
|
];
|
|
738
737
|
}
|
|
738
|
+
// DELETE
|
|
739
|
+
/**
|
|
740
|
+
* @returns number of deleted items
|
|
741
|
+
*/
|
|
739
742
|
async deleteById(id, opt = {}) {
|
|
740
743
|
if (!id)
|
|
741
744
|
return 0;
|
|
742
|
-
this.
|
|
743
|
-
this.requireObjectMutability(opt);
|
|
744
|
-
const op = `deleteById(${id})`;
|
|
745
|
-
const table = opt.table || this.cfg.table;
|
|
746
|
-
const started = this.logStarted(op, table);
|
|
747
|
-
const count = await this.cfg.db.deleteByIds(table, [id], opt);
|
|
748
|
-
this.logSaveResult(started, op, table);
|
|
749
|
-
return count;
|
|
745
|
+
return await this.deleteByIds([id], opt);
|
|
750
746
|
}
|
|
751
747
|
async deleteByIds(ids, opt = {}) {
|
|
752
748
|
if (!ids.length)
|
|
@@ -830,13 +826,7 @@ class CommonDao {
|
|
|
830
826
|
dbm = this.cfg.hooks.anonymize(dbm);
|
|
831
827
|
}
|
|
832
828
|
// DBM > BM
|
|
833
|
-
|
|
834
|
-
if (this.cfg.hooks.beforeDBMToBM) {
|
|
835
|
-
bm = await this.cfg.hooks.beforeDBMToBM(dbm);
|
|
836
|
-
}
|
|
837
|
-
else {
|
|
838
|
-
bm = dbm;
|
|
839
|
-
}
|
|
829
|
+
const bm = ((await this.cfg.hooks.beforeDBMToBM?.(dbm)) || dbm);
|
|
840
830
|
// Validate/convert BM
|
|
841
831
|
return this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
842
832
|
}
|
|
@@ -846,21 +836,10 @@ class CommonDao {
|
|
|
846
836
|
async bmToDBM(bm, opt) {
|
|
847
837
|
if (bm === undefined)
|
|
848
838
|
return;
|
|
849
|
-
// should not do it on load, but only on save!
|
|
850
|
-
// this.assignIdCreatedUpdated(bm, opt)
|
|
851
839
|
// bm gets assigned to the new reference
|
|
852
840
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
853
841
|
// BM > DBM
|
|
854
|
-
|
|
855
|
-
if (this.cfg.hooks.beforeBMToDBM) {
|
|
856
|
-
dbm = { ...(await this.cfg.hooks.beforeBMToDBM(bm)) };
|
|
857
|
-
}
|
|
858
|
-
else {
|
|
859
|
-
dbm = bm;
|
|
860
|
-
}
|
|
861
|
-
// Validate/convert DBM
|
|
862
|
-
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
863
|
-
return dbm;
|
|
842
|
+
return ((await this.cfg.hooks.beforeBMToDBM?.(bm)) || bm);
|
|
864
843
|
}
|
|
865
844
|
async bmsToDBM(bms, opt = {}) {
|
|
866
845
|
// try/catch?
|
|
@@ -885,10 +864,9 @@ class CommonDao {
|
|
|
885
864
|
return entities.map(entity => this.anyToDBM(entity, opt));
|
|
886
865
|
}
|
|
887
866
|
/**
|
|
888
|
-
* Returns *converted value
|
|
889
|
-
* Validates (unless `skipValidation=true` passed).
|
|
890
|
-
*
|
|
867
|
+
* Returns *converted value* (NOT the same reference).
|
|
891
868
|
* Does NOT mutate the object.
|
|
869
|
+
* Validates (unless `skipValidation=true` passed).
|
|
892
870
|
*/
|
|
893
871
|
validateAndConvert(obj, schema, opt = {}) {
|
|
894
872
|
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
@@ -1060,11 +1038,23 @@ class CommonDaoTransaction {
|
|
|
1060
1038
|
// }
|
|
1061
1039
|
// }
|
|
1062
1040
|
async save(dao, bm, opt) {
|
|
1063
|
-
return
|
|
1041
|
+
return await dao.save(bm, { ...opt, tx: this.tx });
|
|
1064
1042
|
}
|
|
1065
1043
|
async saveBatch(dao, bms, opt) {
|
|
1066
1044
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx });
|
|
1067
1045
|
}
|
|
1046
|
+
/**
|
|
1047
|
+
* DaoTransaction.patch does not load from DB.
|
|
1048
|
+
* It assumes the bm was previously loaded in the same Transaction, hence could not be
|
|
1049
|
+
* concurrently modified. Hence it's safe to not sync with DB.
|
|
1050
|
+
*
|
|
1051
|
+
* So, this method is a rather simple convenience "Object.assign and then save".
|
|
1052
|
+
*/
|
|
1053
|
+
async patch(dao, bm, patch, opt) {
|
|
1054
|
+
const skipIfEquals = (0, js_lib_1._deepCopy)(bm);
|
|
1055
|
+
Object.assign(bm, patch);
|
|
1056
|
+
return await dao.save(bm, { ...opt, skipIfEquals, tx: this.tx });
|
|
1057
|
+
}
|
|
1068
1058
|
async deleteById(dao, id, opt) {
|
|
1069
1059
|
if (!id)
|
|
1070
1060
|
return 0;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/db-lib",
|
|
3
3
|
"scripts": {
|
|
4
|
-
"prepare": "husky
|
|
4
|
+
"prepare": "husky"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@naturalcycles/js-lib": "^14.116.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.12"
|
|
42
42
|
},
|
|
43
|
-
"version": "9.
|
|
43
|
+
"version": "9.7.1",
|
|
44
44
|
"description": "Lowest Common Denominator API to supported Databases",
|
|
45
45
|
"keywords": [
|
|
46
46
|
"db",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Transform } from 'node:stream'
|
|
2
2
|
import {
|
|
3
3
|
_assert,
|
|
4
|
+
_deepCopy,
|
|
4
5
|
_deepJsonEquals,
|
|
5
6
|
_filterUndefinedValues,
|
|
6
7
|
_isTruthy,
|
|
@@ -131,18 +132,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
131
132
|
return this.create({ ...part, id }, opt)
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
async getByIdAsDBMOrEmpty(
|
|
135
|
-
id: string,
|
|
136
|
-
part: Partial<BM> = {},
|
|
137
|
-
opt?: CommonDaoOptions,
|
|
138
|
-
): Promise<DBM> {
|
|
139
|
-
const dbm = await this.getByIdAsDBM(id, opt)
|
|
140
|
-
if (dbm) return dbm
|
|
141
|
-
|
|
142
|
-
const bm = this.create({ ...part, id }, opt)
|
|
143
|
-
return await this.bmToDBM(bm, opt)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
135
|
async getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
147
136
|
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>
|
|
148
137
|
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
|
|
@@ -615,51 +604,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
615
604
|
}
|
|
616
605
|
|
|
617
606
|
// SAVE
|
|
618
|
-
/**
|
|
619
|
-
* Mutates with id, created, updated
|
|
620
|
-
*/
|
|
621
|
-
async save(bm: Unsaved<BM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<BM> {
|
|
622
|
-
this.requireWriteAccess()
|
|
623
|
-
|
|
624
|
-
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
625
|
-
// Skipping the save operation
|
|
626
|
-
return bm as BM
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
const idWasGenerated = !bm.id && this.cfg.generateId
|
|
630
|
-
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
631
|
-
_typeCast<BM>(bm)
|
|
632
|
-
let dbm = await this.bmToDBM(bm, opt) // validates BM
|
|
633
|
-
|
|
634
|
-
if (this.cfg.hooks!.beforeSave) {
|
|
635
|
-
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
636
|
-
if (dbm === null) return bm
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
const table = opt.table || this.cfg.table
|
|
640
|
-
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, dbm)
|
|
641
|
-
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
642
|
-
opt = { ...opt, saveMethod: 'insert' }
|
|
643
|
-
}
|
|
644
|
-
const op = `save(${dbm.id})`
|
|
645
|
-
const started = this.logSaveStarted(op, bm, table)
|
|
646
|
-
const { excludeFromIndexes } = this.cfg
|
|
647
|
-
const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds
|
|
648
|
-
|
|
649
|
-
await (opt.tx || this.cfg.db).saveBatch(table, [dbm], {
|
|
650
|
-
excludeFromIndexes,
|
|
651
|
-
assignGeneratedIds,
|
|
652
|
-
...opt,
|
|
653
|
-
})
|
|
654
|
-
|
|
655
|
-
if (assignGeneratedIds) {
|
|
656
|
-
bm.id = dbm.id
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
this.logSaveResult(started, op, table)
|
|
660
|
-
return bm
|
|
661
|
-
}
|
|
662
|
-
|
|
663
607
|
/**
|
|
664
608
|
* 1. Applies the patch
|
|
665
609
|
* 2. If object is the same after patching - skips saving it
|
|
@@ -782,7 +726,58 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
782
726
|
})
|
|
783
727
|
}
|
|
784
728
|
|
|
785
|
-
|
|
729
|
+
/**
|
|
730
|
+
* Mutates with id, created, updated
|
|
731
|
+
*/
|
|
732
|
+
async save(bm: Unsaved<BM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<BM> {
|
|
733
|
+
this.requireWriteAccess()
|
|
734
|
+
|
|
735
|
+
if (opt.skipIfEquals) {
|
|
736
|
+
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
737
|
+
// which should be removed post-validation, but it breaks the "equality check"
|
|
738
|
+
// Post-validation the equality check should work as intended
|
|
739
|
+
const convertedBM = this.validateAndConvert(bm as Partial<BM>, this.cfg.bmSchema, opt)
|
|
740
|
+
if (_deepJsonEquals(convertedBM, opt.skipIfEquals)) {
|
|
741
|
+
// Skipping the save operation
|
|
742
|
+
return bm as BM
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const idWasGenerated = !bm.id && this.cfg.generateId
|
|
747
|
+
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
748
|
+
_typeCast<BM>(bm)
|
|
749
|
+
let dbm = await this.bmToDBM(bm, opt) // validates BM
|
|
750
|
+
|
|
751
|
+
if (this.cfg.hooks!.beforeSave) {
|
|
752
|
+
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
753
|
+
if (dbm === null) return bm
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const table = opt.table || this.cfg.table
|
|
757
|
+
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, dbm)
|
|
758
|
+
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
759
|
+
opt = { ...opt, saveMethod: 'insert' }
|
|
760
|
+
}
|
|
761
|
+
const op = `save(${dbm.id})`
|
|
762
|
+
const started = this.logSaveStarted(op, bm, table)
|
|
763
|
+
const { excludeFromIndexes } = this.cfg
|
|
764
|
+
const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds
|
|
765
|
+
|
|
766
|
+
await (opt.tx || this.cfg.db).saveBatch(table, [dbm], {
|
|
767
|
+
excludeFromIndexes,
|
|
768
|
+
assignGeneratedIds,
|
|
769
|
+
...opt,
|
|
770
|
+
})
|
|
771
|
+
|
|
772
|
+
if (assignGeneratedIds) {
|
|
773
|
+
bm.id = dbm.id
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
this.logSaveResult(started, op, table)
|
|
777
|
+
return bm
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
async saveAsDBM(dbm: Unsaved<DBM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<DBM> {
|
|
786
781
|
this.requireWriteAccess()
|
|
787
782
|
const table = opt.table || this.cfg.table
|
|
788
783
|
|
|
@@ -979,18 +974,9 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
979
974
|
/**
|
|
980
975
|
* @returns number of deleted items
|
|
981
976
|
*/
|
|
982
|
-
async deleteById(id: undefined | null, opt?: CommonDaoOptions): Promise<0>
|
|
983
|
-
async deleteById(id?: string | null, opt?: CommonDaoOptions): Promise<number>
|
|
984
977
|
async deleteById(id?: string | null, opt: CommonDaoOptions = {}): Promise<number> {
|
|
985
978
|
if (!id) return 0
|
|
986
|
-
this.
|
|
987
|
-
this.requireObjectMutability(opt)
|
|
988
|
-
const op = `deleteById(${id})`
|
|
989
|
-
const table = opt.table || this.cfg.table
|
|
990
|
-
const started = this.logStarted(op, table)
|
|
991
|
-
const count = await this.cfg.db.deleteByIds(table, [id], opt)
|
|
992
|
-
this.logSaveResult(started, op, table)
|
|
993
|
-
return count
|
|
979
|
+
return await this.deleteByIds([id], opt)
|
|
994
980
|
}
|
|
995
981
|
|
|
996
982
|
async deleteByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<number> {
|
|
@@ -1103,15 +1089,9 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1103
1089
|
}
|
|
1104
1090
|
|
|
1105
1091
|
// DBM > BM
|
|
1106
|
-
|
|
1107
|
-
if (this.cfg.hooks!.beforeDBMToBM) {
|
|
1108
|
-
bm = await this.cfg.hooks!.beforeDBMToBM(dbm)
|
|
1109
|
-
} else {
|
|
1110
|
-
bm = dbm as any
|
|
1111
|
-
}
|
|
1092
|
+
const bm = ((await this.cfg.hooks!.beforeDBMToBM?.(dbm)) || dbm) as Partial<BM>
|
|
1112
1093
|
|
|
1113
1094
|
// Validate/convert BM
|
|
1114
|
-
|
|
1115
1095
|
return this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1116
1096
|
}
|
|
1117
1097
|
|
|
@@ -1128,23 +1108,11 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1128
1108
|
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM | undefined> {
|
|
1129
1109
|
if (bm === undefined) return
|
|
1130
1110
|
|
|
1131
|
-
// should not do it on load, but only on save!
|
|
1132
|
-
// this.assignIdCreatedUpdated(bm, opt)
|
|
1133
|
-
|
|
1134
1111
|
// bm gets assigned to the new reference
|
|
1135
1112
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1136
1113
|
|
|
1137
1114
|
// BM > DBM
|
|
1138
|
-
|
|
1139
|
-
if (this.cfg.hooks!.beforeBMToDBM) {
|
|
1140
|
-
dbm = { ...((await this.cfg.hooks!.beforeBMToDBM(bm!)) as DBM) }
|
|
1141
|
-
} else {
|
|
1142
|
-
dbm = bm as any
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
// Validate/convert DBM
|
|
1146
|
-
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1147
|
-
return dbm
|
|
1115
|
+
return ((await this.cfg.hooks!.beforeBMToDBM?.(bm!)) || bm) as DBM
|
|
1148
1116
|
}
|
|
1149
1117
|
|
|
1150
1118
|
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
@@ -1178,10 +1146,9 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1178
1146
|
}
|
|
1179
1147
|
|
|
1180
1148
|
/**
|
|
1181
|
-
* Returns *converted value
|
|
1182
|
-
* Validates (unless `skipValidation=true` passed).
|
|
1183
|
-
*
|
|
1149
|
+
* Returns *converted value* (NOT the same reference).
|
|
1184
1150
|
* Does NOT mutate the object.
|
|
1151
|
+
* Validates (unless `skipValidation=true` passed).
|
|
1185
1152
|
*/
|
|
1186
1153
|
validateAndConvert<T>(
|
|
1187
1154
|
obj: Partial<T>,
|
|
@@ -1395,9 +1362,9 @@ export class CommonDaoTransaction {
|
|
|
1395
1362
|
async save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1396
1363
|
dao: CommonDao<BM, DBM>,
|
|
1397
1364
|
bm: Unsaved<BM>,
|
|
1398
|
-
opt?:
|
|
1365
|
+
opt?: CommonDaoSaveOptions<BM, DBM>,
|
|
1399
1366
|
): Promise<BM> {
|
|
1400
|
-
return
|
|
1367
|
+
return await dao.save(bm, { ...opt, tx: this.tx })
|
|
1401
1368
|
}
|
|
1402
1369
|
|
|
1403
1370
|
async saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
@@ -1408,6 +1375,24 @@ export class CommonDaoTransaction {
|
|
|
1408
1375
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx })
|
|
1409
1376
|
}
|
|
1410
1377
|
|
|
1378
|
+
/**
|
|
1379
|
+
* DaoTransaction.patch does not load from DB.
|
|
1380
|
+
* It assumes the bm was previously loaded in the same Transaction, hence could not be
|
|
1381
|
+
* concurrently modified. Hence it's safe to not sync with DB.
|
|
1382
|
+
*
|
|
1383
|
+
* So, this method is a rather simple convenience "Object.assign and then save".
|
|
1384
|
+
*/
|
|
1385
|
+
async patch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1386
|
+
dao: CommonDao<BM, DBM>,
|
|
1387
|
+
bm: BM,
|
|
1388
|
+
patch: Partial<BM>,
|
|
1389
|
+
opt?: CommonDaoSaveOptions<BM, DBM>,
|
|
1390
|
+
): Promise<BM> {
|
|
1391
|
+
const skipIfEquals = _deepCopy(bm)
|
|
1392
|
+
Object.assign(bm, patch)
|
|
1393
|
+
return await dao.save(bm, { ...opt, skipIfEquals, tx: this.tx })
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1411
1396
|
async deleteById(
|
|
1412
1397
|
dao: CommonDao<any>,
|
|
1413
1398
|
id?: string | null,
|