@naturalcycles/db-lib 8.56.0 → 8.57.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.
@@ -111,10 +111,16 @@ export declare class CommonDao<BM extends Partial<ObjectWithId<ID>>, DBM extends
111
111
  * 1.1 Creates the row (via this.create()) if it doesn't exist
112
112
  * (this will cause a validation error if Patch has not enough data for the row to be valid).
113
113
  * 2. Applies the patch on top of loaded data.
114
- * 3. Saves (as fast as possible since the read) with the Patch applied.
114
+ * 3. Saves (as fast as possible since the read) with the Patch applied, but only if the data has changed.
115
115
  */
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>;
116
+ patchById(id: ID, patch: Partial<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>>;
117
+ /**
118
+ * Same as patchById, but takes the whole object as input.
119
+ * This "whole object" is mutated with the patch and returned.
120
+ * Otherwise, similar behavior as patchById.
121
+ * It still loads the row from the DB.
122
+ */
123
+ patch(bm: Saved<BM>, patch: Partial<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>>;
118
124
  saveAsDBM(dbm: DBM, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM>;
119
125
  saveBatch(bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>[]>;
120
126
  saveBatchAsDBM(dbms: DBM[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<DBM[]>;
@@ -620,19 +620,16 @@ class CommonDao {
620
620
  * 1.1 Creates the row (via this.create()) if it doesn't exist
621
621
  * (this will cause a validation error if Patch has not enough data for the row to be valid).
622
622
  * 2. Applies the patch on top of loaded data.
623
- * 3. Saves (as fast as possible since the read) with the Patch applied.
623
+ * 3. Saves (as fast as possible since the read) with the Patch applied, but only if the data has changed.
624
624
  */
625
- async patch(id, patch, opt = {}) {
626
- const bm = await this.getById(id, opt);
625
+ async patchById(id, patch, opt = {}) {
627
626
  let patched;
628
- if (bm) {
629
- patched = {
630
- ...bm,
631
- ...patch,
632
- };
633
- if ((0, js_lib_1._deepJsonEquals)(bm, patched)) {
627
+ const loaded = await this.getById(id, opt);
628
+ if (loaded) {
629
+ patched = { ...loaded, ...patch };
630
+ if ((0, js_lib_1._deepJsonEquals)(loaded, patched)) {
634
631
  // Skipping the save operation, as data is the same
635
- return bm;
632
+ return patched;
636
633
  }
637
634
  }
638
635
  else {
@@ -640,23 +637,30 @@ class CommonDao {
640
637
  }
641
638
  return await this.save(patched, opt);
642
639
  }
643
- async patchAsDBM(id, patch, opt = {}) {
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)) {
640
+ /**
641
+ * Same as patchById, but takes the whole object as input.
642
+ * This "whole object" is mutated with the patch and returned.
643
+ * Otherwise, similar behavior as patchById.
644
+ * It still loads the row from the DB.
645
+ */
646
+ async patch(bm, patch, opt = {}) {
647
+ (0, js_lib_1._assert)(bm.id, 'patch argument object should have an id', {
648
+ bm,
649
+ });
650
+ const loaded = await this.getById(bm.id, opt);
651
+ if (loaded) {
652
+ Object.assign(loaded, patch);
653
+ if ((0, js_lib_1._deepJsonEquals)(loaded, bm)) {
652
654
  // Skipping the save operation, as data is the same
653
- return dbm;
655
+ return bm;
654
656
  }
657
+ // Make `bm` exactly the same as `loaded`
658
+ (0, js_lib_1._objectAssignExact)(bm, loaded);
655
659
  }
656
660
  else {
657
- patched = this.create({ ...patch, id }, opt);
661
+ Object.assign(bm, patch);
658
662
  }
659
- return await this.saveAsDBM(patched, opt);
663
+ return await this.save(bm, opt);
660
664
  }
661
665
  async saveAsDBM(dbm, opt = {}) {
662
666
  this.requireWriteAccess();
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "engines": {
41
41
  "node": ">=18.12"
42
42
  },
43
- "version": "8.56.0",
43
+ "version": "8.57.0",
44
44
  "description": "Lowest Common Denominator API to supported Databases",
45
45
  "keywords": [
46
46
  "db",
@@ -5,6 +5,7 @@ import {
5
5
  _filterNullishValues,
6
6
  _filterUndefinedValues,
7
7
  _isTruthy,
8
+ _objectAssignExact,
8
9
  _passthroughPredicate,
9
10
  _since,
10
11
  _truncate,
@@ -844,25 +845,22 @@ export class CommonDao<
844
845
  * 1.1 Creates the row (via this.create()) if it doesn't exist
845
846
  * (this will cause a validation error if Patch has not enough data for the row to be valid).
846
847
  * 2. Applies the patch on top of loaded data.
847
- * 3. Saves (as fast as possible since the read) with the Patch applied.
848
+ * 3. Saves (as fast as possible since the read) with the Patch applied, but only if the data has changed.
848
849
  */
849
- async patch(
850
+ async patchById(
850
851
  id: ID,
851
852
  patch: Partial<BM>,
852
853
  opt: CommonDaoSaveBatchOptions<DBM> = {},
853
854
  ): Promise<Saved<BM>> {
854
- const bm = await this.getById(id, opt)
855
855
  let patched: Saved<BM>
856
+ const loaded = await this.getById(id, opt)
856
857
 
857
- if (bm) {
858
- patched = {
859
- ...bm,
860
- ...patch,
861
- }
858
+ if (loaded) {
859
+ patched = { ...loaded, ...patch }
862
860
 
863
- if (_deepJsonEquals(bm, patched)) {
861
+ if (_deepJsonEquals(loaded, patched)) {
864
862
  // Skipping the save operation, as data is the same
865
- return bm
863
+ return patched
866
864
  }
867
865
  } else {
868
866
  patched = this.create({ ...patch, id }, opt)
@@ -871,29 +869,38 @@ export class CommonDao<
871
869
  return await this.save(patched, opt)
872
870
  }
873
871
 
874
- async patchAsDBM(
875
- id: ID,
876
- patch: Partial<DBM>,
872
+ /**
873
+ * Same as patchById, but takes the whole object as input.
874
+ * This "whole object" is mutated with the patch and returned.
875
+ * Otherwise, similar behavior as patchById.
876
+ * It still loads the row from the DB.
877
+ */
878
+ async patch(
879
+ bm: Saved<BM>,
880
+ patch: Partial<BM>,
877
881
  opt: CommonDaoSaveBatchOptions<DBM> = {},
878
- ): Promise<DBM> {
879
- const dbm = await this.getByIdAsDBM(id, opt)
880
- let patched: DBM
882
+ ): Promise<Saved<BM>> {
883
+ _assert(bm.id, 'patch argument object should have an id', {
884
+ bm,
885
+ })
881
886
 
882
- if (dbm) {
883
- patched = {
884
- ...dbm,
885
- ...patch,
886
- }
887
+ const loaded = await this.getById(bm.id, opt)
887
888
 
888
- if (_deepJsonEquals(dbm, patched)) {
889
+ if (loaded) {
890
+ Object.assign(loaded, patch)
891
+
892
+ if (_deepJsonEquals(loaded, bm)) {
889
893
  // Skipping the save operation, as data is the same
890
- return dbm
894
+ return bm
891
895
  }
896
+
897
+ // Make `bm` exactly the same as `loaded`
898
+ _objectAssignExact(bm, loaded)
892
899
  } else {
893
- patched = this.create({ ...patch, id } as Partial<BM>, opt) as any as DBM
900
+ Object.assign(bm, patch)
894
901
  }
895
902
 
896
- return await this.saveAsDBM(patched, opt)
903
+ return await this.save(bm, opt)
897
904
  }
898
905
 
899
906
  async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM> {