@naturalcycles/db-lib 9.26.3 → 9.28.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.
@@ -20,7 +20,10 @@ function queryInMemory(q, rows = []) {
20
20
  // .filter
21
21
  // eslint-disable-next-line unicorn/no-array-reduce
22
22
  rows = q._filters.reduce((rows, filter) => {
23
- return rows.filter(row => FILTER_FNS[filter.op](row[filter.name], filter.val));
23
+ return rows.filter(row => {
24
+ const value = (0, js_lib_1._get)(row, filter.name);
25
+ return FILTER_FNS[filter.op](value, filter.val);
26
+ });
24
27
  }, rows);
25
28
  // .select(fieldNames)
26
29
  if (q._selectedFieldNames) {
@@ -509,7 +509,7 @@ class CommonDao {
509
509
  }
510
510
  else {
511
511
  const table = opt.table || this.cfg.table;
512
- (0, js_lib_1._assert)(!opt.requireToExist, `${table}.patchById row is required, but missing`, {
512
+ (0, js_lib_1._assert)(opt.createIfMissing, `DB row required, but not found in ${table}`, {
513
513
  id,
514
514
  table,
515
515
  });
@@ -550,26 +550,21 @@ class CommonDao {
550
550
  Object.assign(bm, patch);
551
551
  }
552
552
  else {
553
- const loaded = await this.getById(bm.id, {
553
+ const loaded = await this.requireById(bm.id, {
554
554
  // Skipping validation here for performance reasons.
555
555
  // Validation is going to happen on save anyway, just down below.
556
556
  skipValidation: true,
557
557
  ...opt,
558
558
  });
559
- if (loaded) {
560
- const loadedWithPatch = {
561
- ...loaded,
562
- ...patch,
563
- };
564
- // Make `bm` exactly the same as `loadedWithPatch`
565
- (0, js_lib_1._objectAssignExact)(bm, loadedWithPatch);
566
- if ((0, js_lib_1._deepJsonEquals)(loaded, loadedWithPatch)) {
567
- // Skipping the save operation, as data is the same
568
- return bm;
569
- }
570
- }
571
- else {
572
- Object.assign(bm, patch);
559
+ const loadedWithPatch = {
560
+ ...loaded,
561
+ ...patch,
562
+ };
563
+ // Make `bm` exactly the same as `loadedWithPatch`
564
+ (0, js_lib_1._objectAssignExact)(bm, loadedWithPatch);
565
+ if ((0, js_lib_1._deepJsonEquals)(loaded, loadedWithPatch)) {
566
+ // Skipping the save operation, as data is the same
567
+ return bm;
573
568
  }
574
569
  }
575
570
  return await this.save(bm, opt);
@@ -227,16 +227,18 @@ export interface CommonDaoSaveOptions<BM extends BaseDBEntity, DBM extends BaseD
227
227
  export interface CommonDaoPatchByIdOptions<DBM extends BaseDBEntity> extends CommonDaoSaveBatchOptions<DBM> {
228
228
  /**
229
229
  * Defaults to false.
230
- * With false, if the row doesn't exist - it will be auto-created with `dao.create`.
231
- * With true, if the row doesn't exist - it will throw an error.
230
+ * With false, if the row doesn't exist - it will throw an error.
231
+ * With true, if the row doesn't exist - it will be auto-created with `dao.create`.
232
232
  *
233
233
  * Use true when you expect the row to exist and it would be an error if it doesn't.
234
234
  */
235
- requireToExist?: boolean;
235
+ createIfMissing?: boolean;
236
236
  }
237
237
  export interface CommonDaoPatchOptions<DBM extends BaseDBEntity> extends CommonDaoSaveBatchOptions<DBM> {
238
238
  /**
239
239
  * If true - patch will skip loading from DB, and will just optimistically patch passed object.
240
+ *
241
+ * Consequently, when the row doesn't exist - it will be auto-created with `dao.create`.
240
242
  */
241
243
  skipDBRead?: boolean;
242
244
  }
@@ -151,6 +151,14 @@ function runCommonDaoTest(db, quirks = {}) {
151
151
  rows = (0, js_lib_1._sortBy)(rows, r => r.id);
152
152
  (0, dbTest_1.expectMatch)(expectedItems.filter(i => i.even), rows, quirks);
153
153
  });
154
+ test('query nested property', async () => {
155
+ let rows = await dao
156
+ .query()
157
+ .filter('nested.foo', '==', 1)
158
+ .runQuery();
159
+ rows = (0, js_lib_1._sortBy)(rows, r => r.id);
160
+ (0, dbTest_1.expectMatch)(expectedItems.filter(i => i.nested?.foo === 1), rows, quirks);
161
+ });
154
162
  }
155
163
  if (support.dbQueryOrder) {
156
164
  test('query order by k1 desc', async () => {
@@ -6,6 +6,9 @@ export interface TestItemBM extends BaseDBEntity {
6
6
  k3?: number;
7
7
  even?: boolean;
8
8
  b1?: Buffer;
9
+ nested?: {
10
+ foo: number;
11
+ };
9
12
  }
10
13
  export interface TestItemDBM extends TestItemBM {
11
14
  }
@@ -15,6 +15,9 @@ exports.testItemBMSchema = (0, nodejs_lib_1.objectSchema)({
15
15
  k3: nodejs_lib_1.numberSchema.optional(),
16
16
  even: nodejs_lib_1.booleanSchema.optional(),
17
17
  b1: nodejs_lib_1.binarySchema.optional(),
18
+ nested: (0, nodejs_lib_1.objectSchema)({
19
+ foo: nodejs_lib_1.numberSchema,
20
+ }).optional(),
18
21
  }).concat(nodejs_lib_1.baseDBEntitySchema);
19
22
  exports.testItemTMSchema = (0, nodejs_lib_1.objectSchema)({
20
23
  k1: nodejs_lib_1.stringSchema,
@@ -41,6 +44,7 @@ function createTestItemDBM(num = 1) {
41
44
  k2: `v${num * 2}`,
42
45
  k3: num,
43
46
  even: num % 2 === 0,
47
+ nested: { foo: num },
44
48
  created: MOCK_TS_2018_06_21,
45
49
  updated: MOCK_TS_2018_06_21,
46
50
  };
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  "engines": {
46
46
  "node": ">=22.10.0"
47
47
  },
48
- "version": "9.26.3",
48
+ "version": "9.28.0",
49
49
  "description": "Lowest Common Denominator API to supported Databases",
50
50
  "keywords": [
51
51
  "db",
@@ -1,4 +1,4 @@
1
- import { _pick, ObjectWithId } from '@naturalcycles/js-lib'
1
+ import { _get, _pick, ObjectWithId } from '@naturalcycles/js-lib'
2
2
  import { DBQuery, DBQueryFilterOperator } from '../../query/dbQuery'
3
3
 
4
4
  type FilterFn = (v: any, val: any) => boolean
@@ -22,7 +22,10 @@ export function queryInMemory<ROW extends ObjectWithId>(q: DBQuery<ROW>, rows: R
22
22
  // .filter
23
23
  // eslint-disable-next-line unicorn/no-array-reduce
24
24
  rows = q._filters.reduce((rows, filter) => {
25
- return rows.filter(row => FILTER_FNS[filter.op](row[filter.name], filter.val))
25
+ return rows.filter(row => {
26
+ const value = _get(row, filter.name as string)
27
+ return FILTER_FNS[filter.op](value, filter.val)
28
+ })
26
29
  }, rows)
27
30
 
28
31
  // .select(fieldNames)
@@ -285,18 +285,20 @@ export interface CommonDaoPatchByIdOptions<DBM extends BaseDBEntity>
285
285
  extends CommonDaoSaveBatchOptions<DBM> {
286
286
  /**
287
287
  * Defaults to false.
288
- * With false, if the row doesn't exist - it will be auto-created with `dao.create`.
289
- * With true, if the row doesn't exist - it will throw an error.
288
+ * With false, if the row doesn't exist - it will throw an error.
289
+ * With true, if the row doesn't exist - it will be auto-created with `dao.create`.
290
290
  *
291
291
  * Use true when you expect the row to exist and it would be an error if it doesn't.
292
292
  */
293
- requireToExist?: boolean
293
+ createIfMissing?: boolean
294
294
  }
295
295
 
296
296
  export interface CommonDaoPatchOptions<DBM extends BaseDBEntity>
297
297
  extends CommonDaoSaveBatchOptions<DBM> {
298
298
  /**
299
299
  * If true - patch will skip loading from DB, and will just optimistically patch passed object.
300
+ *
301
+ * Consequently, when the row doesn't exist - it will be auto-created with `dao.create`.
300
302
  */
301
303
  skipDBRead?: boolean
302
304
  }
@@ -679,7 +679,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
679
679
  }
680
680
  } else {
681
681
  const table = opt.table || this.cfg.table
682
- _assert(!opt.requireToExist, `${table}.patchById row is required, but missing`, {
682
+ _assert(opt.createIfMissing, `DB row required, but not found in ${table}`, {
683
683
  id,
684
684
  table,
685
685
  })
@@ -728,28 +728,24 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
728
728
  }
729
729
  Object.assign(bm, patch)
730
730
  } else {
731
- const loaded = await this.getById(bm.id as ID, {
731
+ const loaded = await this.requireById(bm.id as ID, {
732
732
  // Skipping validation here for performance reasons.
733
733
  // Validation is going to happen on save anyway, just down below.
734
734
  skipValidation: true,
735
735
  ...opt,
736
736
  })
737
737
 
738
- if (loaded) {
739
- const loadedWithPatch: BM = {
740
- ...loaded,
741
- ...patch,
742
- }
738
+ const loadedWithPatch: BM = {
739
+ ...loaded,
740
+ ...patch,
741
+ }
743
742
 
744
- // Make `bm` exactly the same as `loadedWithPatch`
745
- _objectAssignExact(bm, loadedWithPatch)
743
+ // Make `bm` exactly the same as `loadedWithPatch`
744
+ _objectAssignExact(bm, loadedWithPatch)
746
745
 
747
- if (_deepJsonEquals(loaded, loadedWithPatch)) {
748
- // Skipping the save operation, as data is the same
749
- return bm
750
- }
751
- } else {
752
- Object.assign(bm, patch)
746
+ if (_deepJsonEquals(loaded, loadedWithPatch)) {
747
+ // Skipping the save operation, as data is the same
748
+ return bm
753
749
  }
754
750
  }
755
751
 
@@ -196,6 +196,19 @@ export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQui
196
196
  quirks,
197
197
  )
198
198
  })
199
+
200
+ test('query nested property', async () => {
201
+ let rows = await dao
202
+ .query()
203
+ .filter('nested.foo' as any, '==', 1)
204
+ .runQuery()
205
+ rows = _sortBy(rows, r => r.id)
206
+ expectMatch(
207
+ expectedItems.filter(i => i.nested?.foo === 1),
208
+ rows,
209
+ quirks,
210
+ )
211
+ })
199
212
  }
200
213
 
201
214
  if (support.dbQueryOrder) {
@@ -24,6 +24,9 @@ export interface TestItemBM extends BaseDBEntity {
24
24
  k3?: number
25
25
  even?: boolean
26
26
  b1?: Buffer
27
+ nested?: {
28
+ foo: number
29
+ }
27
30
  }
28
31
 
29
32
  export interface TestItemDBM extends TestItemBM {}
@@ -39,6 +42,9 @@ export const testItemBMSchema = objectSchema<TestItemBM>({
39
42
  k3: numberSchema.optional(),
40
43
  even: booleanSchema.optional(),
41
44
  b1: binarySchema.optional(),
45
+ nested: objectSchema({
46
+ foo: numberSchema,
47
+ }).optional(),
42
48
  }).concat(baseDBEntitySchema as any)
43
49
 
44
50
  export const testItemTMSchema = objectSchema<TestItemTM>({
@@ -68,6 +74,7 @@ export function createTestItemDBM(num = 1): TestItemDBM {
68
74
  k2: `v${num * 2}`,
69
75
  k3: num,
70
76
  even: num % 2 === 0,
77
+ nested: { foo: num },
71
78
  created: MOCK_TS_2018_06_21,
72
79
  updated: MOCK_TS_2018_06_21,
73
80
  }