dobo 2.18.2 → 2.19.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.
package/index.js CHANGED
@@ -539,23 +539,47 @@ async function factory (pkgName) {
539
539
  return nql(sanitized).parse()
540
540
  }
541
541
 
542
- parseQuery = (query, silent = true) => {
543
- const { isPlainObject, trim } = this.app.lib._
542
+ parseAny = (query, model) => {
543
+ const { isEmpty } = this.app.lib._
544
+ let q = {}
545
+ if (!model) throw this.error('invalidQuery')
546
+ let scanables = [...model.scanables]
547
+ if (scanables.length === 0) scanables = [...model.sortables]
548
+ const fields = scanables.filter(f => {
549
+ const field = find(model.properties, { name: f, type: 'string' })
550
+ return !!field
551
+ })
552
+ const parts = fields.map(f => {
553
+ if (query[0] === '*') return `${f}:~$'${query.replaceAll('*', '')}'`
554
+ if (query[query.length - 1] === '*') return `${f}:~^'${query.replaceAll('*', '')}'`
555
+ return `${f}:~'${query.replaceAll('*', '')}'`
556
+ })
557
+ if (parts.length === 1) q = this.parseNql(parts[0])
558
+ else if (parts.length > 1) q = this.parseNql(parts.join(','))
559
+ if (isEmpty(q)) throw this.error('invalidQuery')
560
+ return q
561
+ }
562
+
563
+ parseQuery = (query, model, silent = true) => {
564
+ const { isEmpty, isPlainObject, trim } = this.app.lib._
544
565
  let result = {}
545
566
  if (isPlainObject(query)) result = query
546
567
  else {
547
568
  query = trim(query)
569
+ if (isEmpty(query)) return result
548
570
  try {
549
571
  if (query.startsWith('{')) result = JSON.parse(query)
550
- else result = this.parseNql(query)
572
+ else if (query.includes(':')) result = this.parseNql(query)
573
+ else result = this.parseAny(query, model)
551
574
  } catch (err) {
552
575
  if (silent) return {}
553
576
  throw err
554
577
  }
555
578
  }
579
+ let strQ = this.replaceRegexInJson(result)
580
+ if (model && model.driver.idField.name !== 'id') strQ = strQ.replaceAll('"id"', `"${model.driver.idField.name}"`)
556
581
  try {
557
- const text = JSON.stringify(result)
558
- if (text.includes('["__REGEXP__",')) result = this.reviveRegexInJson(text)
582
+ result = this.reviveRegexInJson(strQ)
559
583
  } catch (err) {}
560
584
  return result
561
585
  }
@@ -575,7 +599,7 @@ async function factory (pkgName) {
575
599
  const { isPlainObject } = this.app.lib._
576
600
  if (isPlainObject(input)) input = JSON.stringify(input)
577
601
  const result = JSON.parse(input, (key, value) => {
578
- if (Array.isArray(value) && value[0] === '__REGEXP__') return { $regex: new RegExp(value[1], value[2]) }
602
+ if (Array.isArray(value) && value[0] === '__REGEXP__') return new RegExp(value[1], value[2])
579
603
  return value
580
604
  })
581
605
  return returnObject ? result : JSON.stringify(result)
@@ -77,7 +77,6 @@ export async function getFilterAndOptions (filter = {}, options = {}, action) {
77
77
  if (!nOptions.noModelHook) await runModelHook(this, 'beforeBuilSearch', nFilter.search, nOptions)
78
78
  nFilter.search = buildFilterSearch.call(this, nFilter) ?? {}
79
79
  if (!nOptions.noModelHook) await runModelHook(this, 'afterBuildSearch', nFilter.search, nOptions)
80
- if (this.driver.idField.name !== 'id') replaceIdInQuerySearch.call(this, nFilter)
81
80
  const { limit, page, skip, sort } = preparePagination.call(this, nFilter, nOptions)
82
81
  nFilter.limit = limit
83
82
  nFilter.page = page
@@ -190,7 +189,7 @@ export async function getSingleRef (record = {}, options = {}) {
190
189
  let query = {}
191
190
  query[ref.field] = record[prop.name]
192
191
  if (ref.field === 'id') query[ref.field] = this.sanitizeId(query[ref.field])
193
- if (ref.query) query = { $and: [query, parseQuery(ref.query)] }
192
+ if (ref.query) query = { $and: [query, parseQuery(ref.query, rModel)] }
194
193
  const filter = { query }
195
194
  const resp = await _getRef.call(this, { ref, rModel, prop, key, options, filter })
196
195
  if (!resp) continue
@@ -228,7 +227,7 @@ export async function getMultiRefs (records = [], options = {}) {
228
227
  matches = uniq(without(matches, undefined, null, NaN))
229
228
  let query = {}
230
229
  query[ref.field] = { $in: matches }
231
- if (ref.query) query = { $and: [query, parseQuery(ref.query)] }
230
+ if (ref.query) query = { $and: [query, parseQuery(ref.query, rModel)] }
232
231
  const filter = { query, limit: matches.length }
233
232
  const resp = await _getRef.call(this, { ref, rModel, prop, key, options, filter })
234
233
  if (!resp) continue
@@ -247,35 +246,9 @@ export async function getMultiRefs (records = [], options = {}) {
247
246
  }
248
247
 
249
248
  export function buildFilterQuery (filter = {}) {
250
- const { trim, find, isString, isPlainObject } = this.app.lib._
251
- const { parseNql } = this.app.dobo
252
- let query = filter.query ?? {}
253
- let q = {}
254
- if (isString(query)) {
255
- try {
256
- query = trim(query)
257
- if (query.startsWith('{')) q = JSON.parse(query) // JSON formatted query
258
- else if (query.includes(':')) q = parseNql(query) // NQL
259
- else {
260
- let scanables = [...this.scanables]
261
- if (scanables.length === 0) scanables = [...this.sortables]
262
- const fields = scanables.filter(f => {
263
- const field = find(this.properties, { name: f, type: 'string' })
264
- return !!field
265
- })
266
- const parts = fields.map(f => {
267
- if (query[0] === '*') return `${f}:~$'${query.replaceAll('*', '')}'`
268
- if (query[query.length - 1] === '*') return `${f}:~^'${query.replaceAll('*', '')}'`
269
- return `${f}:~'${query.replaceAll('*', '')}'`
270
- })
271
- if (parts.length === 1) q = parseNql(parts[0])
272
- else if (parts.length > 1) q = parseNql(parts.join(','))
273
- }
274
- } catch (err) {
275
- this.plugin.error('invalidQuery', { orgMessage: err.message })
276
- }
277
- } else if (isPlainObject(query)) q = query
278
- return sanitizeQuery.call(this, q)
249
+ const { parseQuery } = this.app.dobo
250
+ const query = parseQuery(filter.query ?? {}, this, false)
251
+ return sanitizeQuery.call(this, query)
279
252
  }
280
253
 
281
254
  function sanitizeQuery (query = {}, parent) {
@@ -346,7 +319,7 @@ export function buildFilterSearch (filter = {}) {
346
319
  items[part.field].push(...part.value.split(' ').filter(v => ![''].includes(v)))
347
320
  }
348
321
  }
349
- const s = {}
322
+ let s = {}
350
323
  for (const index of this.indexes.filter(i => i.type === 'fulltext')) {
351
324
  for (const f of index.fields) {
352
325
  const value = []
@@ -357,22 +330,15 @@ export function buildFilterSearch (filter = {}) {
357
330
  }
358
331
  }
359
332
  if (has(items, '*')) s['*'] = items['*']
333
+ if (this.driver.idField.name !== 'id') {
334
+ const search = JSON.stringify(s).replaceAll('"id"', `"${this.driver.idField.name}"`)
335
+ try {
336
+ s = JSON.parse(search)
337
+ } catch (err) {}
338
+ }
360
339
  return s
361
340
  }
362
341
 
363
- export function replaceIdInQuerySearch (filter) {
364
- const { replaceRegexInJson, reviveRegexInJson } = this.app.dobo
365
- const query = replaceRegexInJson(filter.query).replaceAll('"id"', `"${this.driver.idField.name}"`)
366
- try {
367
- filter.query = reviveRegexInJson(query)
368
- } catch (err) {}
369
- // search
370
- const search = JSON.stringify(filter.search ?? {}).replaceAll('"id"', `"${this.driver.idField.name}"`)
371
- try {
372
- filter.search = JSON.parse(search)
373
- } catch (err) {}
374
- }
375
-
376
342
  /**
377
343
  * Prepare records pagination:
378
344
  * - making sure records limit is obeyed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dobo",
3
- "version": "2.18.2",
3
+ "version": "2.19.0",
4
4
  "description": "DBMS for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-04-19
4
+
5
+ - [2.19.0] Add ```queryAny()``` for query using model's scanables fields
6
+ - [2.19.0] Bug fix in ```reviveRegexInJson()```
7
+ - [2.19.0] Bug fix in query sanitizing especially for regex existance
8
+ - [2.19.0] Remove ```replaceIdInQuerySearch()``` in ```_util.js``` as it isn't needed anymore
9
+
3
10
  ## 2026-04-18
4
11
 
5
12
  - [2.18.2] Bug fix in ```config``` object