dobo 2.37.1 → 2.38.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.
@@ -1,6 +1,6 @@
1
1
  import postProcess from './lib/post-process.js'
2
2
 
3
- async function createAggregate (path, ...args) {
3
+ async function aggregate (path, ...args) {
4
4
  const { importPkg } = this.app.bajo
5
5
  const { isEmpty, map } = this.app.lib._
6
6
  const { parseKvString } = this.app.lib.aneka
@@ -26,8 +26,8 @@ async function createAggregate (path, ...args) {
26
26
  })
27
27
  }
28
28
  params = isEmpty(params) ? {} : parseKvString(params)
29
- await postProcess.call(this, { noConfirmation: true, handler: 'createAggregate', params: [model, filter, params, options], path, processMsg: 'Create aggregate' })
29
+ await postProcess.call(this, { noConfirmation: true, handler: 'aggregate', params: [model, filter, params, options], path, processMsg: 'Create aggregate' })
30
30
  this.app.exit()
31
31
  }
32
32
 
33
- export default createAggregate
33
+ export default aggregate
@@ -1,6 +1,6 @@
1
1
  import postProcess from './lib/post-process.js'
2
2
 
3
- async function createHistogram (path, ...args) {
3
+ async function histogram (path, ...args) {
4
4
  const { importPkg } = this.app.bajo
5
5
  const { isEmpty, map } = this.app.lib._
6
6
  const { parseKvString } = this.app.lib.aneka
@@ -26,8 +26,8 @@ async function createHistogram (path, ...args) {
26
26
  })
27
27
  }
28
28
  params = isEmpty(params) ? {} : parseKvString(params)
29
- await postProcess.call(this, { noConfirmation: true, handler: 'createHistogram', params: [model, filter, params, options], path, processMsg: 'Create histogram' })
29
+ await postProcess.call(this, { noConfirmation: true, handler: 'histogram', params: [model, filter, params, options], path, processMsg: 'Create histogram' })
30
30
  this.app.exit()
31
31
  }
32
32
 
33
- export default createHistogram
33
+ export default histogram
@@ -149,13 +149,13 @@ async function memoryAdapterFactory () {
149
149
  return { data }
150
150
  }
151
151
 
152
- async createAggregate (model, filter = {}, params = {}, options = {}) {
152
+ async aggregate (model, filter = {}, params = {}, options = {}) {
153
153
  const item = await this.findAllRecord(model, filter, options)
154
154
  const result = this.app.dobo.calcAggregate({ data: item.data, ...params })
155
155
  return { data: result }
156
156
  }
157
157
 
158
- async createHistogram (model, filter = {}, params = {}, options = {}) {
158
+ async histogram (model, filter = {}, params = {}, options = {}) {
159
159
  const item = await this.findAllRecord(model, filter, options)
160
160
  const result = this.app.dobo.calcHistogram({ data: item.data, ...params })
161
161
  return { data: result }
package/index.js CHANGED
@@ -613,12 +613,33 @@ async function factory (pkgName) {
613
613
  }
614
614
 
615
615
  reviveRegexInJson = (input, returnObject = true) => {
616
- const { isPlainObject } = this.app.lib._
616
+ const { isPlainObject, isArray } = this.app.lib._
617
617
  if (isPlainObject(input)) input = JSON.stringify(input)
618
618
  const result = JSON.parse(input, (key, value) => {
619
- if (Array.isArray(value) && value[0] === '__REGEXP__') return new RegExp(value[1], value[2])
619
+ if (Array.isArray(value) && value[0] === '__REGEXP__') {
620
+ return { $regex: new RegExp(value[1], value[2]) }
621
+ }
620
622
  return value
621
623
  })
624
+
625
+ const cleanRegex = (obj) => {
626
+ const keys = Object.keys(obj)
627
+ keys.forEach(k => {
628
+ const v = obj[k]
629
+ if (isPlainObject(v)) {
630
+ if (k === '$regex' && isPlainObject(v) && v.$regex) obj[k] = v.$regex
631
+ else obj[k] = cleanRegex(v)
632
+ } else if (isArray(v)) {
633
+ v.forEach((i, idx) => {
634
+ if (isPlainObject(i) && i.$regex && i.$regex.$regex) obj[k][idx] = i.$regex.$regex
635
+ else obj[k][idx] = cleanRegex(i)
636
+ })
637
+ }
638
+ })
639
+ return obj
640
+ }
641
+ cleanRegex(result)
642
+
622
643
  return returnObject ? result : JSON.stringify(result)
623
644
  }
624
645
  }
@@ -14,8 +14,8 @@
14
14
  * @property {string[]} [findAllRecord=['filter']]
15
15
  * @property {string[]} [findAllRecords=['filter']] - Alias of `findAllRecord`
16
16
  * @property {string[]} [countRecord=['params']]
17
- * @property {string[]} [createAggregate=['params']]
18
- * @property {string[]} [createHistogram=['params']]
17
+ * @property {string[]} [aggregate=['params']]
18
+ * @property {string[]} [histogram=['params']]
19
19
  * @property {string[]} [createAttachment=['id']]
20
20
  * @property {string[]} [findAttachment=['id']]
21
21
  * @property {string[]} [getAttachment=['id', 'field', 'file']]
@@ -34,8 +34,8 @@ const methods = {
34
34
  findAllRecord: ['filter'],
35
35
  findAllRecords: ['filter'],
36
36
  countRecord: ['params'],
37
- createAggregate: ['params'],
38
- createHistogram: ['params'],
37
+ aggregate: ['params'],
38
+ histogram: ['params'],
39
39
  createAttachment: ['id'],
40
40
  findAttachment: ['id'],
41
41
  getAttachment: ['id', 'field', 'file'],
@@ -452,7 +452,7 @@ async function adapterFactory () {
452
452
  if (!this.support.uniqueIndex) await this._checkUnique(model, body, options)
453
453
  }
454
454
  if (!options.noIdCheck && isSet(body.id)) {
455
- const resp = await this.getRecord(model, body.id, { ...options, noMagic: true })
455
+ const resp = await this.getRecord(model, body.id, { noMagic: true })
456
456
  if (!isEmpty(resp.data)) throw this.plugin.error('recordExists%s%s', body.id, model.name)
457
457
  }
458
458
  body = this.sanitizeBody(model, body)
@@ -536,7 +536,7 @@ async function adapterFactory () {
536
536
  if (!this.support.uniqueIndex) await this._checkUnique(model, body, options)
537
537
  }
538
538
  if (!options._data) {
539
- const resp = await this.getRecord(model, id, { ...options, noMagic: true })
539
+ const resp = await this.getRecord(model, id, { noMagic: true })
540
540
  if (!resp.data) throw this.plugin.error('recordNotFound%s%s', id, model.name)
541
541
  options._data = resp.data
542
542
  }
@@ -573,7 +573,7 @@ async function adapterFactory () {
573
573
  }
574
574
  if (isSet(body.id)) {
575
575
  if (!options._data) {
576
- const resp = await this.getRecord(model, body.id, { ...options, noMagic: true })
576
+ const resp = await this.getRecord(model, body.id, { noMagic: true })
577
577
  if (!resp.data) throw this.plugin.error('recordNotFound%s%s', body.id, model.name)
578
578
  options._data = resp.data
579
579
  }
@@ -604,7 +604,7 @@ async function adapterFactory () {
604
604
  */
605
605
  async _removeRecord (model, id, options = {}) {
606
606
  if (!options._data) {
607
- const resp = await this.getRecord(model, id, { ...options, noMagic: true })
607
+ const resp = await this.getRecord(model, id, { noMagic: true })
608
608
  if (!resp.data) throw this.plugin.error('recordNotFound%s%s', id, model.name)
609
609
  options._data = resp.data
610
610
  }
@@ -731,7 +731,7 @@ async function adapterFactory () {
731
731
  }
732
732
 
733
733
  /**
734
- * Wrapper for the {@link DoboAdapter#createAggregate} method, called internally by `model` to make sure
734
+ * Wrapper for the {@link DoboAdapter#aggregate} method, called internally by `model` to make sure
735
735
  * all adapter hooks are executed accordingly, and all inputs and outputs are sanitized.
736
736
  * @internal
737
737
  * @async
@@ -742,7 +742,7 @@ async function adapterFactory () {
742
742
  * @param {object} options
743
743
  * @returns {Promise<object>}
744
744
  */
745
- async _createAggregate (model, filter = {}, params = {}, options = {}) {
745
+ async _aggregate (model, filter = {}, params = {}, options = {}) {
746
746
  const fieldPropTypes = ['integer', 'smallint', 'float', 'double']
747
747
  const groupPropTypes = ['string', ...fieldPropTypes]
748
748
  this.app.dobo.checkAggregateParams(params)
@@ -758,9 +758,9 @@ async function adapterFactory () {
758
758
 
759
759
  let result
760
760
  try {
761
- await this._attachHook('beforeCreateAggregate', model, filter, params, options)
762
- result = await this.createAggregate(model, filter, params, options)
763
- await this._attachHook('afterCreateAggregate', model, filter, params, result, options)
761
+ await this._attachHook('beforeAggregate', model, filter, params, options)
762
+ result = await this.aggregate(model, filter, params, options)
763
+ await this._attachHook('afterAggregate', model, filter, params, result, options)
764
764
  } catch (err) {
765
765
  if (err.message !== '_emptyColumnQuery') throw err
766
766
  result = { data: [] }
@@ -774,7 +774,7 @@ async function adapterFactory () {
774
774
  }
775
775
 
776
776
  /**
777
- * Wrapper for the {@link DoboAdapter#createHistogram} method, called internally by `model` to make sure
777
+ * Wrapper for the {@link DoboAdapter#histogram} method, called internally by `model` to make sure
778
778
  * all adapter hooks are executed accordingly, and all inputs and outputs are sanitized.
779
779
  * @internal
780
780
  * @async
@@ -785,7 +785,7 @@ async function adapterFactory () {
785
785
  * @param {object} options
786
786
  * @returns {Promise<object>}
787
787
  */
788
- async _createHistogram (model, filter = {}, params, options = {}) {
788
+ async _histogram (model, filter = {}, params, options = {}) {
789
789
  // const fieldPropTypes = ['integer', 'smallint', 'float', 'double']
790
790
  const groupPropTypes = ['datetime', 'date']
791
791
  this.app.dobo.checkHistogramParams(params)
@@ -800,9 +800,9 @@ async function adapterFactory () {
800
800
 
801
801
  let result
802
802
  try {
803
- await this._attachHook('beforeCreateHistogram', model, filter, params, options)
804
- result = await this.createHistogram(model, filter, params, options)
805
- await this._attachHook('afterCreateHistogram', model, filter, params, result, options)
803
+ await this._attachHook('beforeHistogram', model, filter, params, options)
804
+ result = await this.histogram(model, filter, params, options)
805
+ await this._attachHook('afterHistogram', model, filter, params, result, options)
806
806
  } catch (err) {
807
807
  if (err.message !== '_emptyColumnQuery') throw err
808
808
  result = { data: [] }
@@ -997,8 +997,8 @@ async function adapterFactory () {
997
997
  * @param {object} options - Additional options that may affect aggregate creation
998
998
  * @returns {Promise<object>} - The result of the aggregate creation
999
999
  */
1000
- async createAggregate (model, filter = {}, params = {}, options = {}) {
1001
- throw this.plugin.error('notSupportedAdapter%s%s%s', this.app.t('method'), 'createAggregate', this.name)
1000
+ async aggregate (model, filter = {}, params = {}, options = {}) {
1001
+ throw this.plugin.error('notSupportedAdapter%s%s%s', this.app.t('method'), 'aggregate', this.name)
1002
1002
  }
1003
1003
 
1004
1004
  /**
@@ -1013,8 +1013,8 @@ async function adapterFactory () {
1013
1013
  * @param {object} options - Additional options that may affect histogram creation
1014
1014
  * @returns {Promise<object>} - The result of the histogram creation
1015
1015
  */
1016
- async createHistogram (model, filter = {}, params = {}, options = {}) {
1017
- throw this.plugin.error('notSupportedAdapter%s%s%s', this.app.t('method'), 'createHistogram', this.name)
1016
+ async histogram (model, filter = {}, params = {}, options = {}) {
1017
+ throw this.plugin.error('notSupportedAdapter%s%s%s', this.app.t('method'), 'histogram', this.name)
1018
1018
  }
1019
1019
 
1020
1020
  /**
@@ -0,0 +1,23 @@
1
+ import { getFilterAndOptions, execHook, execModelHook, execDynHook } from './helper.js'
2
+ const action = 'aggregate'
3
+
4
+ async function aggregate (...args) {
5
+ if (args.length === 0) return this.action(action, ...args)
6
+ const [_filter = {}, params = {}, opts = {}] = args
7
+ opts.dataOnly = opts.dataOnly ?? true
8
+ const { dataOnly } = opts
9
+ const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
10
+ const { getDefaultValues } = this.app.dobo
11
+ await execHook.call(this, 'beforeAggregate', filter, params, options)
12
+ await execModelHook.call(this, 'beforeAggregate', filter, params, options)
13
+ await execDynHook.call(this, 'beforeAggregate', filter, params, options)
14
+ const result = (await this.adapter._aggregate(this, filter, params, options)) ?? {}
15
+ const { warnings } = getDefaultValues(options)
16
+ if (!warnings) delete result.warnings
17
+ await execDynHook.call(this, 'afterAggregate', filter, params, result, options)
18
+ await execModelHook.call(this, 'afterAggregate', filter, params, result, options)
19
+ await execHook.call(this, 'afterAggregate', filter, params, result, options)
20
+ return dataOnly ? result.data : result
21
+ }
22
+
23
+ export default aggregate
@@ -0,0 +1,23 @@
1
+ import { getFilterAndOptions, execHook, execModelHook, execDynHook } from './helper.js'
2
+ const action = 'histogram'
3
+
4
+ async function histogram (...args) {
5
+ if (args.length === 0) return this.action(action, ...args)
6
+ const [_filter = {}, params = {}, opts = {}] = args
7
+ opts.dataOnly = opts.dataOnly ?? true
8
+ const { dataOnly } = opts
9
+ const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
10
+ const { getDefaultValues } = this.app.dobo
11
+ await execHook.call(this, 'beforeHistogram', filter, params, options)
12
+ await execModelHook.call(this, 'beforeHistogram', filter, params, options)
13
+ await execDynHook.call(this, 'beforeHistogram', filter, params, options)
14
+ const result = (await this.adapter._histogram(this, filter, params, options)) ?? {}
15
+ const { warnings } = getDefaultValues(options)
16
+ if (!warnings) delete result.warnings
17
+ await execDynHook.call(this, 'afterHistogram', filter, params, result, options)
18
+ await execModelHook.call(this, 'afterHistogram', filter, params, result, options)
19
+ await execHook.call(this, 'afterHistogram', filter, params, result, options)
20
+ return dataOnly ? result.data : result
21
+ }
22
+
23
+ export default histogram
@@ -7,8 +7,8 @@ import findAllRecord from './model/find-all-record.js'
7
7
  import findOneRecord from './model/find-one-record.js'
8
8
  import findRecord from './model/find-record.js'
9
9
  import getRecord from './model/get-record.js'
10
- import createHistogram from './model/create-histogram.js'
11
- import createAggregate from './model/create-aggregate.js'
10
+ import histogram from './model/histogram.js'
11
+ import aggregate from './model/aggregate.js'
12
12
  import exists from './model/exists.js'
13
13
  import build from './model/build.js'
14
14
  import loadFixtures from './model/load-fixtures.js'
@@ -271,8 +271,8 @@ async function modelFactory () {
271
271
  transaction,
272
272
  bulkCreateRecord,
273
273
 
274
- createAggregate,
275
- createHistogram,
274
+ aggregate,
275
+ histogram,
276
276
  countRecord,
277
277
 
278
278
  createAttachment,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dobo",
3
- "version": "2.37.1",
3
+ "version": "2.38.0",
4
4
  "description": "DBMS for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "homepage": "https://github.com/ardhi/dobo#readme",
34
34
  "dependencies": {
35
- "@tryghost/nql": "^0.12.7",
35
+ "@tryghost/nql": "^0.13.2",
36
36
  "joi": "^18.0.2",
37
37
  "mingo": "^6.5.1",
38
38
  "ulid": "^3.0.2",
package/wiki/CHANGES.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-08-18
4
+
5
+ - [2.38.0] Change `createAggregate()` to `aggregate()`
6
+ - [2.38.0] Change `createHistogram()` to `histogram()`
7
+
3
8
  ## 2026-08-13
4
9
 
5
10
  - [2.37.1] Bug fix in `adapter.js` to pass options when calling `getRecord()`
6
11
  - [2.37.1] Bug fix in `model._simpleLookup()` to return `null` if query string is not right
7
12
  - [2.37.1] Bug fix in `model.sanitizeFixture()` to not sanitize value that is `null` or `undefined`
13
+ - [2.37.2] Bug fix in `reviveRegexInJson()` when handling with regex
8
14
 
9
15
  ## 2026-08-06
10
16
 
@@ -1,23 +0,0 @@
1
- import { getFilterAndOptions, execHook, execModelHook, execDynHook } from './helper.js'
2
- const action = 'createAggregate'
3
-
4
- async function createAggregate (...args) {
5
- if (args.length === 0) return this.action(action, ...args)
6
- const [_filter = {}, params = {}, opts = {}] = args
7
- opts.dataOnly = opts.dataOnly ?? true
8
- const { dataOnly } = opts
9
- const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
10
- const { getDefaultValues } = this.app.dobo
11
- await execHook.call(this, 'beforeCreateAggregate', filter, params, options)
12
- await execModelHook.call(this, 'beforeCreateAggregate', filter, params, options)
13
- await execDynHook.call(this, 'beforeCreateAggregate', filter, params, options)
14
- const result = (await this.adapter._createAggregate(this, filter, params, options)) ?? {}
15
- const { warnings } = getDefaultValues(options)
16
- if (!warnings) delete result.warnings
17
- await execDynHook.call(this, 'afterCreateAggregate', filter, params, result, options)
18
- await execModelHook.call(this, 'afterCreateAggregate', filter, params, result, options)
19
- await execHook.call(this, 'afterCreateAggregate', filter, params, result, options)
20
- return dataOnly ? result.data : result
21
- }
22
-
23
- export default createAggregate
@@ -1,23 +0,0 @@
1
- import { getFilterAndOptions, execHook, execModelHook, execDynHook } from './helper.js'
2
- const action = 'createHistogram'
3
-
4
- async function createHistogram (...args) {
5
- if (args.length === 0) return this.action(action, ...args)
6
- const [_filter = {}, params = {}, opts = {}] = args
7
- opts.dataOnly = opts.dataOnly ?? true
8
- const { dataOnly } = opts
9
- const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
10
- const { getDefaultValues } = this.app.dobo
11
- await execHook.call(this, 'beforeCreateHistogram', filter, params, options)
12
- await execModelHook.call(this, 'beforeCreateHistogram', filter, params, options)
13
- await execDynHook.call(this, 'beforeCreateHistogram', filter, params, options)
14
- const result = (await this.adapter._createHistogram(this, filter, params, options)) ?? {}
15
- const { warnings } = getDefaultValues(options)
16
- if (!warnings) delete result.warnings
17
- await execDynHook.call(this, 'afterCreateHistogram', filter, params, result, options)
18
- await execModelHook.call(this, 'afterCreateHistogram', filter, params, result, options)
19
- await execHook.call(this, 'afterCreateHistogram', filter, params, result, options)
20
- return dataOnly ? result.data : result
21
- }
22
-
23
- export default createHistogram