dobo 2.19.0 → 2.20.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.
@@ -238,7 +238,7 @@ async function createSchema (item) {
238
238
  const { readConfig } = this.app.bajo
239
239
  const { fastGlob } = this.app.lib
240
240
  const { find, isPlainObject, orderBy, get, cloneDeep } = this.app.lib._
241
- const { mergeObjectsByKey, defaultsDeep } = this.app.lib.aneka
241
+ const { mergeObjectsByKey, defaultsDeep, parseObject } = this.app.lib.aneka
242
242
  if (item.file && !item.base) item.base = path.basename(item.file, path.extname(item.file))
243
243
  item.attachment = item.attachment ?? true
244
244
  const feats = item.features ?? []
@@ -269,7 +269,7 @@ async function createSchema (item) {
269
269
  item.cache = item.cache ?? item.connection.options.cache ?? defCache
270
270
  if (item.cache === true) item.cache = get(item, 'connection.options.cache', defCache)
271
271
  else if (item.cache === false) item.cache = { ttlDur: 0 }
272
- item.cache = defaultsDeep(get(this, `app.bajoCache.config.dobo.${item.name}`), item.cache)
272
+ item.cache = parseObject(defaultsDeep(get(this, `app.bajoCache.config.dobo.${item.name}`), item.cache))
273
273
  await findAllProps.call(this, item, props, indexes)
274
274
  await findAllFeats.call(this, item, feats, indexes)
275
275
  await findAllIndexes.call(this, item, indexes)
@@ -65,6 +65,16 @@ export async function getFilterAndOptions (filter = {}, options = {}, action) {
65
65
  const { runModelHook } = this.app.dobo
66
66
  const nFilter = cloneDeep(filter || {})
67
67
  const nOptions = cloneOptions.call(this, options)
68
+ if (options.noMagic) {
69
+ nOptions.noModelHook = true
70
+ nOptions.noHook = true
71
+ nOptions.noDynHook = true
72
+ nOptions.noValidation = true
73
+ nOptions.noCache = true
74
+ nOptions.throwNotFound = false
75
+ delete options.noMagic
76
+ delete nOptions.noMagic
77
+ }
68
78
  nOptions.action = action
69
79
  nOptions.dataOnly = false
70
80
  nOptions.truncateString = nOptions.truncateString ?? false
@@ -420,3 +430,12 @@ export function preparePagination (filter = {}, options = {}) {
420
430
  const sort = buildSort(sortInput, options.allowSortUnindexed)
421
431
  return { limit, page, skip, sort }
422
432
  }
433
+
434
+ export async function clearCache (id) {
435
+ const { clear } = this.app.bajoCache
436
+ if (!clear) return
437
+ await clear({ key: `dobo|${this.name}|getRecord|${id}` })
438
+ await clear({ key: `dobo|${this.name}|findRecord` })
439
+ await clear({ key: `dobo|${this.name}|findAllRecord` })
440
+ await clear({ key: `dobo|${this.name}|findOneRecord` })
441
+ }
@@ -2,7 +2,8 @@ import { getFilterAndOptions, execHook, execModelHook } from './_util.js'
2
2
  const action = 'build'
3
3
 
4
4
  async function build (opts = {}) {
5
- const { dataOnly = true } = opts
5
+ opts.dataOnly = opts.dataOnly ?? true
6
+ const { dataOnly } = opts
6
7
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
7
8
  await execHook.call(this, 'beforeBuildModel', options)
8
9
  await execModelHook.call(this, 'beforeBuildModel', options)
@@ -4,7 +4,8 @@ const action = 'clearRecord'
4
4
  async function clearRecord (...args) {
5
5
  if (args.length === 0) return this.action(action, ...args)
6
6
  const [opts = {}] = args
7
- const { dataOnly = true } = opts
7
+ opts.dataOnly = opts.dataOnly ?? true
8
+ const { dataOnly } = opts
8
9
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
9
10
  await execHook.call(this, 'beforeClearRecord', options)
10
11
  await execModelHook.call(this, 'beforeClearRecord', options)
@@ -5,7 +5,8 @@ async function countRecord (...args) {
5
5
  const { getDefaultValues } = this.app.dobo
6
6
  if (args.length === 0) return this.action(action, ...args)
7
7
  const [params = {}, opts = {}] = args
8
- const { dataOnly = true } = opts
8
+ opts.dataOnly = opts.dataOnly ?? true
9
+ const { dataOnly } = opts
9
10
  const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
10
11
  const { hardCap, t } = getDefaultValues(options)
11
12
  await execHook.call(this, 'beforeCountRecord', options)
@@ -4,7 +4,8 @@ const action = 'createAggregate'
4
4
  async function createAggregate (...args) {
5
5
  if (args.length === 0) return this.action(action, ...args)
6
6
  const [_filter = {}, params = {}, opts = {}] = args
7
- const { dataOnly = true } = opts
7
+ opts.dataOnly = opts.dataOnly ?? true
8
+ const { dataOnly } = opts
8
9
  const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
9
10
  const { getDefaultValues } = this.app.dobo
10
11
  await execHook.call(this, 'beforeCreateAggregate', filter, params, options)
@@ -4,7 +4,8 @@ const action = 'createHistogram'
4
4
  async function createHistogram (...args) {
5
5
  if (args.length === 0) return this.action(action, ...args)
6
6
  const [_filter = {}, params = {}, opts = {}] = args
7
- const { dataOnly = true } = opts
7
+ opts.dataOnly = opts.dataOnly ?? true
8
+ const { dataOnly } = opts
8
9
  const { filter, options } = await getFilterAndOptions.call(this, _filter, opts, action)
9
10
  const { getDefaultValues } = this.app.dobo
10
11
  await execHook.call(this, 'beforeCreateHistogram', filter, params, options)
@@ -8,9 +8,9 @@ async function createRecord (...args) {
8
8
  const [body = {}, opts = {}] = args
9
9
  const { getDefaultValues } = this.app.dobo
10
10
  const { isSet } = this.app.lib.aneka
11
- const { runHook } = this.app.bajo
12
11
  const { cloneDeep, get } = this.app.lib._
13
- const { dataOnly = true } = opts
12
+ opts.dataOnly = opts.dataOnly ?? true
13
+ const { dataOnly } = opts
14
14
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
15
15
  const { truncateString, noResult, noBodySanitizer, noResultSanitizer, noValidation } = options
16
16
  const extFields = get(options, 'validation.extFields', [])
@@ -20,10 +20,7 @@ async function createRecord (...args) {
20
20
  await execDynHook.call(this, 'beforeCreateRecord', input, options)
21
21
  if (!noValidation) await execValidation.call(this, input, options)
22
22
  let result = options.record ?? (await this.driver._createRecord(this, input, options)) ?? {}
23
- if (noResult) {
24
- await runHook('cache:clear', this, 'create', body, null, options)
25
- return
26
- }
23
+ if (noResult) return
27
24
  result = result ?? {}
28
25
  const { warnings } = getDefaultValues(options)
29
26
  if (!warnings) delete result.warnings
@@ -33,7 +30,6 @@ async function createRecord (...args) {
33
30
  await execDynHook.call(this, 'afterCreateRecord', input, result, options)
34
31
  await execModelHook.call(this, 'afterCreateRecord', input, result, options)
35
32
  await execHook.call(this, 'afterCreateRecord', input, result, options)
36
- await runHook('cache:clear', this, 'create', body, result, options)
37
33
  return dataOnly ? result.data : result
38
34
  }
39
35
 
@@ -2,7 +2,8 @@ import { getFilterAndOptions, execHook, execModelHook } from './_util.js'
2
2
  const action = 'drop'
3
3
 
4
4
  async function drop (opts = {}) {
5
- const { dataOnly = true } = opts
5
+ opts.dataOnly = opts.dataOnly ?? true
6
+ const { dataOnly } = opts
6
7
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
7
8
  await execHook.call(this, 'beforeDropModel', options)
8
9
  await execModelHook.call(this, 'beforeDropModel', options)
@@ -8,7 +8,8 @@ const action = 'modelExists'
8
8
  * @returns {Object}
9
9
  */
10
10
  async function isExists (opts = {}) {
11
- const { dataOnly = true } = opts
11
+ opts.dataOnly = opts.dataOnly ?? true
12
+ const { dataOnly } = opts
12
13
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
13
14
  await execHook.call(this, 'beforeModelExists', options)
14
15
  await execModelHook.call(this, 'beforeModelExists', options)
@@ -4,27 +4,24 @@ const action = 'findAllRecord'
4
4
  async function native (...args) {
5
5
  const { isSet } = this.app.lib.aneka
6
6
  const { getDefaultValues, t } = this.app.dobo
7
- const { cloneDeep, pick, omit } = this.app.lib._
7
+ const { pick, omit, cloneDeep } = this.app.lib._
8
8
  const [params = {}, opts = {}] = args
9
- const { dataOnly = true } = opts
10
- const { get: getCache, set: setCache } = this.app.bajoCache ?? {}
9
+ const { get, set } = this.app.bajoCache ?? {}
10
+ opts.dataOnly = opts.dataOnly ?? true
11
+ const { dataOnly } = opts
11
12
  const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
12
13
  const { hardCap, warnings } = getDefaultValues(options)
13
14
  if (dataOnly) options.count = false
14
- let { noResultSanitizer, noCache } = options
15
+ const { noResultSanitizer } = options
15
16
  await execHook.call(this, 'beforeFindRecord', filter, options)
16
17
  await execModelHook.call(this, 'beforeFindRecord', filter, options)
17
18
  await execDynHook.call(this, 'beforeFindRecord', filter, options)
18
- if (this.cache.ttlDur === 0 || options.record) noCache = true
19
- const cacheFilter = cloneDeep(filter)
20
- if (!noCache && getCache) {
21
- const result = await getCache({ model: this, filter: cacheFilter, options })
22
- if (result) {
23
- for (const idx in result.data) {
24
- result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
25
- }
26
- result.cached = true
27
- return dataOnly ? result.data : result
19
+ const cFilter = cloneDeep(filter)
20
+ if (get) {
21
+ const resp = await get({ model: this, action, filter: cFilter, options })
22
+ if (resp) {
23
+ resp.cached = true
24
+ return dataOnly ? resp.data : resp
28
25
  }
29
26
  }
30
27
  let result = options.record ?? (await this.driver._findAllRecord(this, filter, options)) ?? {}
@@ -49,10 +46,7 @@ async function native (...args) {
49
46
  await execDynHook.call(this, 'afterFindRecord', filter, result, options)
50
47
  await execModelHook.call(this, 'afterFindRecord', filter, result, options)
51
48
  await execHook.call(this, 'afterFindRecord', filter, result, options)
52
- if (!noCache && setCache) {
53
- await setCache({ model: this, filter: cacheFilter, result, options })
54
- result.cached = false
55
- }
49
+ if (set) await set({ model: this, action, filter: cFilter, options, result })
56
50
  return dataOnly ? result.data : result
57
51
  }
58
52
 
@@ -60,7 +54,8 @@ async function loop (...args) {
60
54
  const { cloneDeep } = this.app.lib._
61
55
  const { getDefaultValues } = this.app.dobo
62
56
  const [params = {}, opts = {}] = args
63
- const { dataOnly = true } = opts
57
+ opts.dataOnly = opts.dataOnly ?? true
58
+ const { dataOnly } = opts
64
59
  const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
65
60
  const { maxLimit, hardCap, warnings: showWarnings } = getDefaultValues(options)
66
61
  const nFilter = cloneDeep(filter || {})
@@ -7,7 +7,8 @@ async function findOneRecord (...args) {
7
7
  const { getDefaultValues } = this.app.dobo
8
8
  const [params = {}, opts = {}] = args
9
9
  const { cloneDeep } = this.app.lib._
10
- const { dataOnly = true } = opts
10
+ opts.dataOnly = opts.dataOnly ?? true
11
+ const { dataOnly } = opts
11
12
  if (dataOnly) opts.count = false
12
13
  const nFilter = cloneDeep(params || {})
13
14
  const nOptions = cloneOptions.call(this, opts)
@@ -17,7 +18,7 @@ async function findOneRecord (...args) {
17
18
  const { warnings } = getDefaultValues(nOptions)
18
19
  const resp = await this.findRecord(nFilter, nOptions)
19
20
  const data = resp.data[0]
20
- const result = { data, cached: resp.cached, warnings: resp.warnings }
21
+ const result = { data, warnings: resp.warnings }
21
22
  if (!warnings) delete result.warnings
22
23
  return dataOnly ? data : result
23
24
  }
@@ -69,32 +69,29 @@ async function findRecord (...args) {
69
69
  const { getDefaultValues, t } = this.app.dobo
70
70
  const [params = {}, opts = {}] = args
71
71
  const { isSet } = this.app.lib.aneka
72
- const { cloneDeep, pick, omit } = this.app.lib._
73
- const { dataOnly = true } = opts
74
- const { get: getCache, set: setCache } = this.app.bajoCache ?? {}
72
+ const { pick, omit, cloneDeep } = this.app.lib._
73
+ const { get, set } = this.app.bajoCache ?? {}
74
+ opts.dataOnly = opts.dataOnly ?? true
75
+ const { dataOnly } = opts
75
76
  const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
76
77
  const { hardCap, warnings } = getDefaultValues(options)
77
78
  if (dataOnly) options.count = false
78
- let { noResultSanitizer, noCache } = options
79
+ const { noResultSanitizer } = options
79
80
  await execHook.call(this, 'beforeFindRecord', filter, options)
80
81
  await execModelHook.call(this, 'beforeFindRecord', filter, options)
81
82
  await execDynHook.call(this, 'beforeFindRecord', filter, options)
82
- if (this.cache.ttlDur === 0 || options.record) noCache = true
83
- const cacheFilter = cloneDeep(filter)
84
- if (!noCache && getCache) {
85
- const result = await getCache({ model: this, filter: cacheFilter, options })
86
- if (result) {
87
- for (const idx in result.data) {
88
- result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
89
- }
90
- result.cached = true
91
- return dataOnly ? result.data : result
83
+ const cFilter = cloneDeep(filter)
84
+ if (get) {
85
+ const resp = await get({ model: this, action, filter: cFilter, options })
86
+ if (resp) {
87
+ resp.cached = true
88
+ return dataOnly ? resp.data : resp
92
89
  }
93
90
  }
94
91
  let result = options.record ?? (await this.driver._findRecord(this, filter, options)) ?? {}
95
92
  result.page = filter.page
96
93
  result.limit = filter.limit
97
- result.filter = pick(filter, ['query', 'match', 'sort'])
94
+ result.filter = pick(filter, ['query', 'search', 'sort'])
98
95
  result.warnings = result.warnings ?? []
99
96
  if (!options.count) result = omit(result, ['count', 'pages'])
100
97
  else if (options.count && result.count > hardCap) {
@@ -114,10 +111,7 @@ async function findRecord (...args) {
114
111
  await execDynHook.call(this, 'afterFindRecord', filter, result, options)
115
112
  await execModelHook.call(this, 'afterFindRecord', filter, result, options)
116
113
  await execHook.call(this, 'afterFindRecord', filter, result, options)
117
- if (!noCache && setCache) {
118
- await setCache({ model: this, filter: cacheFilter, result, options })
119
- result.cached = false
120
- }
114
+ if (set) await set({ model: this, action, filter: cFilter, options, result })
121
115
  return dataOnly ? result.data : result
122
116
  }
123
117
 
@@ -48,22 +48,20 @@ async function getRecord (...args) {
48
48
  const { getDefaultValues } = this.app.dobo
49
49
  const { isEmpty } = this.app.lib._
50
50
  const { isSet } = this.app.lib.aneka
51
- const { get: getCache, set: setCache } = this.app.bajoCache ?? {}
52
- const { dataOnly = true } = opts
51
+ const { get, set } = this.app.bajoCache ?? {}
52
+ opts.dataOnly = opts.dataOnly ?? true
53
+ const { dataOnly } = opts
53
54
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
54
- let { noResultSanitizer, noCache } = options
55
- if (!this.cacheable || !options.record) noCache = true
55
+ const { noResultSanitizer } = options
56
56
  id = this.sanitizeId(id)
57
57
  await execHook.call(this, 'beforeGetRecord', id, options)
58
58
  await execModelHook.call(this, 'beforeGetRecord', id, options)
59
59
  await execDynHook.call(this, 'beforeGetRecord', id, options)
60
- if (this.cache.ttlDur === 0 || options.record) noCache = true
61
- if (!noCache && getCache) {
62
- const result = await getCache({ model: this, id, options })
63
- if (result) {
64
- result.data = await this.sanitizeRecord(result.data, options)
65
- result.cached = true
66
- return dataOnly ? result.data : result
60
+ if (get) {
61
+ const resp = await get({ model: this, action, id, options })
62
+ if (resp) {
63
+ resp.cached = true
64
+ return dataOnly ? resp.data : resp
67
65
  }
68
66
  }
69
67
  const result = options.record ?? (await this.driver._getRecord(this, id, options)) ?? {}
@@ -75,10 +73,7 @@ async function getRecord (...args) {
75
73
  await execDynHook.call(this, 'afterGetRecord', id, result, options)
76
74
  await execModelHook.call(this, 'afterGetRecord', id, result, options)
77
75
  await execHook.call(this, 'afterGetRecord', id, result, options)
78
- if (!noCache && setCache) {
79
- await setCache({ model: this, id, result, options })
80
- result.cached = false
81
- }
76
+ if (set) await set({ model: this, action, id, options, result })
82
77
  return dataOnly ? result.data : result
83
78
  }
84
79
 
@@ -1,4 +1,4 @@
1
- import { getFilterAndOptions, execHook, execModelHook, execDynHook, getSingleRef, handleReq } from './_util.js'
1
+ import { getFilterAndOptions, execHook, execModelHook, execDynHook, getSingleRef, handleReq, clearCache } from './_util.js'
2
2
  const action = 'removeRecord'
3
3
 
4
4
  /**
@@ -36,8 +36,8 @@ async function removeRecord (...args) {
36
36
  let [id, opts = {}] = args
37
37
  const { getDefaultValues } = this.app.dobo
38
38
  const { isSet } = this.app.lib.aneka
39
- const { runHook } = this.app.bajo
40
- const { dataOnly = true } = opts
39
+ opts.dataOnly = opts.dataOnly ?? true
40
+ const { dataOnly } = opts
41
41
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
42
42
  const { noResult, noResultSanitizer } = options
43
43
  id = this.sanitizeId(id)
@@ -45,10 +45,8 @@ async function removeRecord (...args) {
45
45
  await execModelHook.call(this, 'beforeRemoveRecord', id, options)
46
46
  await execDynHook.call(this, 'beforeRemoveRecord', id, options)
47
47
  const result = options.record ?? (await this.driver._removeRecord(this, id, options)) ?? {}
48
- if (noResult) {
49
- await runHook('cache:clear', this, 'remove', id)
50
- return
51
- }
48
+ await clearCache.call(this, id)
49
+ if (noResult) return
52
50
  const { warnings } = getDefaultValues(options)
53
51
  if (!warnings) delete result.warnings
54
52
  if (!noResultSanitizer) result.oldData = await this.sanitizeRecord(result.oldData, options)
@@ -57,7 +55,6 @@ async function removeRecord (...args) {
57
55
  await execDynHook.call(this, 'afterRemoveRecord', id, result, options)
58
56
  await execModelHook.call(this, 'afterRemoveRecord', id, result, options)
59
57
  await execHook.call(this, 'afterRemoveRecord', id, result, options)
60
- await runHook('cache:clear', this, 'remove', id, result, options)
61
58
  return dataOnly ? result.oldData : result
62
59
  }
63
60
 
@@ -1,4 +1,4 @@
1
- import { getFilterAndOptions, execHook, execValidation, execModelHook, execDynHook, getSingleRef, handleReq } from './_util.js'
1
+ import { getFilterAndOptions, execHook, execValidation, execModelHook, execDynHook, getSingleRef, handleReq, clearCache } from './_util.js'
2
2
  import { onlyTypes } from './create-record.js'
3
3
  const action = 'updateRecord'
4
4
 
@@ -49,9 +49,9 @@ async function updateRecord (...args) {
49
49
  let [id, body = {}, opts = {}] = args
50
50
  const { getDefaultValues } = this.app.dobo
51
51
  const { isSet } = this.app.lib.aneka
52
- const { runHook } = this.app.bajo
53
52
  const { cloneDeep, get, omit } = this.app.lib._
54
- const { dataOnly = true } = opts
53
+ opts.dataOnly = opts.dataOnly ?? true
54
+ const { dataOnly } = opts
55
55
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
56
56
  options.partial = options.partial ?? true
57
57
  const { truncateString, noResult, noBodySanitizer, noResultSanitizer, noValidation, partial } = options
@@ -67,10 +67,8 @@ async function updateRecord (...args) {
67
67
  await execDynHook.call(this, 'beforeUpdateRecord', id, input, options)
68
68
  if (!noValidation) await execValidation.call(this, input, options)
69
69
  const result = options.record ?? (await this.driver._updateRecord(this, id, input, options)) ?? {}
70
- if (noResult) {
71
- await runHook('cache:clear', this, 'update', id, body)
72
- return
73
- }
70
+ await clearCache.call(this, id)
71
+ if (noResult) return
74
72
  const { warnings } = getDefaultValues(options)
75
73
  if (!warnings) delete result.warnings
76
74
  if (!noResultSanitizer) {
@@ -82,7 +80,6 @@ async function updateRecord (...args) {
82
80
  await execDynHook.call(this, 'afterUpdateRecord', id, input, result, options)
83
81
  await execModelHook.call(this, 'afterUpdateRecord', id, input, result, options)
84
82
  await execHook.call(this, 'afterUpdateRecord', id, input, result, options)
85
- await runHook('cache:clear', this, 'update', id, body, result, options)
86
83
  return dataOnly ? result.data : result
87
84
  }
88
85
 
@@ -1,12 +1,12 @@
1
- import { getFilterAndOptions, execHook, execModelHook, execDynHook, execValidation, getSingleRef, handleReq } from './_util.js'
1
+ import { getFilterAndOptions, execHook, execModelHook, execDynHook, execValidation, getSingleRef, handleReq, clearCache } from './_util.js'
2
2
  const action = 'upsertRecord'
3
3
 
4
4
  async function native (body = {}, opts = {}) {
5
5
  const { isSet } = this.app.lib.aneka
6
6
  const { getDefaultValues } = this.app.dobo
7
- const { runHook } = this.app.bajo
8
7
  const { cloneDeep, get } = this.app.lib._
9
- const { dataOnly = true } = opts
8
+ opts.dataOnly = opts.dataOnly ?? true
9
+ const { dataOnly } = opts
10
10
  const { options } = await getFilterAndOptions.call(this, null, opts, action)
11
11
  const { truncateString, noResult, noBodySanitizer, noResultSanitizer, noValidation } = options
12
12
  const extFields = get(options, 'validation.extFields', [])
@@ -16,10 +16,8 @@ async function native (body = {}, opts = {}) {
16
16
  await execModelHook.call(this, 'beforeUpsertRecord', input, options)
17
17
  await execDynHook.call(this, 'beforeUpsertRecord', input, options)
18
18
  const result = options.record ?? (await this.driver._upsertRecord(this, input, options)) ?? {}
19
- if (noResult) {
20
- await runHook('cache:clear', this, 'upsert', body)
21
- return
22
- }
19
+ await clearCache.call(this, body.id)
20
+ if (noResult) return
23
21
  const { warnings } = getDefaultValues(options)
24
22
  if (!warnings) delete result.warnings
25
23
  if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
@@ -28,7 +26,6 @@ async function native (body = {}, opts = {}) {
28
26
  await execDynHook.call(this, 'afterUpsertRecord', input, result, options)
29
27
  await execModelHook.call(this, 'afterUpsertRecord', input, result, options)
30
28
  await execHook.call(this, 'afterUpsertRecord', input, result, options)
31
- await runHook('cache:clear', this, 'upsert', body, result, options)
32
29
  return dataOnly ? result.data : result
33
30
  }
34
31
 
@@ -43,7 +40,7 @@ async function manual (body = {}, options = {}) {
43
40
  } catch (err) {
44
41
  }
45
42
  }
46
- const id = get(old, 'dara.id')
43
+ const id = get(old, 'data.id')
47
44
  if (id) return await this.updateRecord(old.data.id, omit(body, ['id']), options)
48
45
  return await this.createRecord(body, options)
49
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dobo",
3
- "version": "2.19.0",
3
+ "version": "2.20.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-21
4
+
5
+ - [2.19.1] Bug fix in ```collect-models.js```, now values are sanitized with ```parseObject()```
6
+ - [2.19.1] Bug fix in ```options.dataOnly``` on all model methods
7
+ - [2.19.1] Add ```options.noMagic```
8
+ - [2.20.0] Revert back to NOT using hooks for caching
9
+
3
10
  ## 2026-04-19
4
11
 
5
12
  - [2.19.0] Add ```queryAny()``` for query using model's scanables fields