waibu-db 2.32.2 → 2.33.1

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.
@@ -101,7 +101,7 @@ async function btnExport () {
101
101
  if (_.isEmpty(selector)) {
102
102
  await wbs.notify('Cant get data selector', { type: 'danger' })
103
103
  } else {
104
- const item = handler === 'list' ? this.extractTable(selector) : this.extractForm(selector)
104
+ const item = ['list', ''].includes(handler) ? this.extractTable(selector) : this.extractForm(selector)
105
105
  await wbs.copyToClipboard(item)
106
106
  }
107
107
  instance.hide()
@@ -4,12 +4,141 @@ async function query () {
4
4
  const WdbBase = await wdbBase.call(this)
5
5
 
6
6
  return class WdbQuery extends WdbBase {
7
+ modal = ({ container, models, columns, fields, id }) => {
8
+ const { jsonStringify } = this.app.waibuMpa
9
+ const { upperFirst } = this.app.lib._
10
+ const qsKey = this.app.waibu.config.qsKey
11
+ const icon = this.params.attr.mini ? 'search' : (this.params.attr.icon ?? 'dotsThree')
12
+ const applyBtn = !this.params.attr.mini ? '<c:btn color="primary" t:content="apply" margin="start-2" @click="submit()" />' : ''
13
+ let parse = 'parse () {},'
14
+ if (!this.params.attr.mini) {
15
+ parse = `parse () {
16
+ this.builder = document.getElementById('${id}').value
17
+ if (!this.builder.includes(':')) this.builder = ''
18
+ if (_.isEmpty(this.builder)) return
19
+ const tokens = _.merge({}, this.ops, {
20
+ in: ':[',
21
+ between: ':{',
22
+ contains: ':~',
23
+ starts: ':~^',
24
+ ends: ':~$$',
25
+ '!in': ':-[',
26
+ '!between': ':-{',
27
+ '!contains': ':-~',
28
+ '!starts': ':-~^',
29
+ '!ends': ':-~$$'
30
+ })
31
+ for (const part of this.builder.split('+')) {
32
+ let [f, ...opv] = part.split(':')
33
+ opv = ':' + opv.join(':')
34
+ this.selected.push(f)
35
+ let op
36
+ let val
37
+ _.each(tokens, (v, k) => {
38
+ if (opv.slice(0, v.length) === v) {
39
+ op = k
40
+ val = opv.slice(v.length).replaceAll('[', '').replaceAll('{', '').replaceAll(']', '').replaceAll('}', '').replaceAll('\\'', '')
41
+ }
42
+ })
43
+ if (_.isEmpty(op)) continue
44
+ this[f + 'Op'] = op
45
+ if (op === 'between') {
46
+ const vals = val.split(',')
47
+ this[f + 'Val'] = vals[0]
48
+ this[f + 'Val2'] = vals[1]
49
+ } else {
50
+ this[f + 'Val'] = val
51
+ }
52
+ }
53
+ },
54
+ `
55
+ }
56
+ return `
57
+ <c:${container} trigger-color="secondary-outline" trigger-icon="${icon}" trigger-on-end t:title="queryBuilder" x-ref="query" x-data="{
58
+ fields: ${jsonStringify(fields, true)},
59
+ builder: '',
60
+ selected: [],
61
+ ${models.join(',\n')},
62
+ ops: { eq: ':', neq: ':-', gt: ':>', gte: ':>=', lt: ':<', lte: ':<=' },
63
+ opsIn (v, neg) { return ':' + (neg ? '-' : '') + '[' + this.expandArray(v) + ']' },
64
+ opsBetween (v, v2, neg) { return ':' + (neg ? '-' : '') + '{' + this.expandArray(v) + ',' + this.expandArray(v2) + '}' },
65
+ opsExt (v, neg, ext) {
66
+ let prefix = (neg ? '-' : '') + '~'
67
+ if (ext) prefix += ext
68
+ return ':' + prefix + '\\'' + v + '\\''
69
+ },
70
+ ${parse}
71
+ expandArray (val = '') {
72
+ return _.map(val.split(','), item => {
73
+ item = _.trim(item)
74
+ if (Number(item)) return item
75
+ return '\\'' + item + '\\''
76
+ })
77
+ },
78
+ rebuild () {
79
+ const items = []
80
+ for (const sel of this.selected) {
81
+ const key = this[sel + 'Op']
82
+ let val = this[sel + 'Val']
83
+ let val2 = this[sel + 'Val2']
84
+ if (_.isEmpty(val)) continue
85
+ if (key === 'between' && _.isEmpty(val2)) continue
86
+ let item
87
+ if (key === 'in') item = this.opsIn(val)
88
+ else if (key === '!in') item = this.opsIn(val, true)
89
+ else if (key === 'between') item = this.opsBetween(val, val2, false)
90
+ else if (key === '!between') item = this.opsBetween(val, val2, true)
91
+ else if (key === 'contains') item = this.opsExt(val)
92
+ else if (key === '!contains') item = this.opsExt(val, true)
93
+ else if (key === 'starts') item = this.opsExt(val, false, '^')
94
+ else if (key === '!starts') item = this.opsExt(val, true, '^')
95
+ else if (key === 'ends') item = this.opsExt(val, false, '$$')
96
+ else if (key === '!ends') item = this.opsExt(val, true, '$$')
97
+ else if (val.includes(' ')) item = this.ops[key] + '\\'' + val + '\\''
98
+ else item = this.ops[key] + val
99
+ items.push(sel + item)
100
+ }
101
+ this.builder = items.join('+')
102
+ },
103
+ submit (run) {
104
+ if (run) {
105
+ const url = new URL(window.location.href)
106
+ const params = new URLSearchParams(url.search)
107
+ params.set('${qsKey.page}', 1)
108
+ params.set('${qsKey.query}', this.builder ?? '')
109
+ window.location.href = '?' + params.toString()
110
+ } else $dispatch('on-query', this.builder)
111
+ const instance = wbs.getInstance('${upperFirst(container)}', $refs.query)
112
+ instance.hide()
113
+ }
114
+ }" x-init="
115
+ parse()
116
+ const ops = _.map(fields, f => (f + 'Op'))
117
+ const vals = _.map(fields, f => (f + 'Val'))
118
+ const vals2 = _.map(fields, f => (f + 'Val2'))
119
+ const watcher = ['selected', ...ops, ...vals, ...vals2].join(',')
120
+ $watch(watcher, v => rebuild())
121
+ " ${this.params.attr.modal ? '' : 'style="width:600px;"'}>
122
+ <c:grid-row gutter="2">
123
+ <c:grid-col col="12">
124
+ <c:form-textarea x-model="builder" readonly rows="4"/>
125
+ </c:grid-col>
126
+ ${columns.join('\n')}
127
+ </c:grid-row>
128
+ <c:div flex="justify-content:end" margin="top-3">
129
+ <c:btn color="secondary" t:content="close" dismiss="${container}" />
130
+ ${applyBtn}
131
+ <c:btn color="primary" t:content="submitQuery" margin="start-2" @click="submit(true)" />
132
+ </c:div>
133
+ </c:${container}>
134
+ `
135
+ }
136
+
7
137
  build = async () => {
8
138
  const { req } = this.component
9
139
  const { generateId } = this.app.lib.aneka
10
140
  const { join } = this.app.bajo
11
- const { jsonStringify } = this.app.waibuMpa
12
- const { find, get, without, isEmpty, filter, upperFirst } = this.app.lib._
141
+ const { find, get, without, isEmpty, filter } = this.app.lib._
13
142
  const qsKey = this.app.waibu.config.qsKey
14
143
  const schema = get(this, 'component.locals.schema', {})
15
144
  if (schema.view.disabled.includes('find')) {
@@ -62,144 +191,36 @@ async function query () {
62
191
  this.params.noTag = true
63
192
  const container = this.params.attr.modal ? 'modal' : 'drawer'
64
193
  const scanables = (this.schema.scanables ?? []).map(item => req.t(`field.${item}`))
65
- let placeholder = this.params.attr.placeholder
66
- if (!placeholder) placeholder = scanables.length > 0 ? req.t('queryHint%s', join(scanables, { separator: ', ', lastSeparator: 'or' })) : req.t('query')
67
- this.params.html = await this.component.buildSentence(`
68
- <c:form-input type="search" placeholder="${placeholder}" id="${id}" x-data="{ query: '' }" x-init="
69
- const url = new URL(window.location.href)
70
- query = url.searchParams.get('${qsKey.query}') ?? ''
71
- " x-model="query" @on-query.window="query = $event.detail ?? ''" @keyup.enter="$dispatch('on-submit')">
72
- <c:form-input-addon>
73
- <c:${container} trigger-icon="${this.params.attr.icon ?? 'dotsThree'}" trigger-on-end t:title="queryBuilder" x-ref="query" x-data="{
74
- fields: ${jsonStringify(fields, true)},
75
- builder: '',
76
- selected: [],
77
- ${models.join(',\n')},
78
- ops: { eq: ':', neq: ':-', gt: ':>', gte: ':>=', lt: ':<', lte: ':<=' },
79
- opsIn (v, neg) { return ':' + (neg ? '-' : '') + '[' + this.expandArray(v) + ']' },
80
- opsBetween (v, v2, neg) { return ':' + (neg ? '-' : '') + '{' + this.expandArray(v) + ',' + this.expandArray(v2) + '}' },
81
- opsExt (v, neg, ext) {
82
- let prefix = (neg ? '-' : '') + '~'
83
- if (ext) prefix += ext
84
- return ':' + prefix + '\\'' + v + '\\''
85
- },
86
- parse () {
87
- this.builder = document.getElementById('${id}').value
88
- if (!this.builder.includes(':')) this.builder = ''
89
- if (_.isEmpty(this.builder)) return
90
- const tokens = _.merge({}, this.ops, {
91
- in: ':[',
92
- between: ':{',
93
- contains: ':~',
94
- starts: ':~^',
95
- ends: ':~$$',
96
- '!in': ':-[',
97
- '!between': ':-{',
98
- '!contains': ':-~',
99
- '!starts': ':-~^',
100
- '!ends': ':-~$$'
101
- })
102
- for (const part of this.builder.split('+')) {
103
- let [f, ...opv] = part.split(':')
104
- opv = ':' + opv.join(':')
105
- this.selected.push(f)
106
- let op
107
- let val
108
- _.each(tokens, (v, k) => {
109
- if (opv.slice(0, v.length) === v) {
110
- op = k
111
- val = opv.slice(v.length).replaceAll('[', '').replaceAll('{', '').replaceAll(']', '').replaceAll('}', '').replaceAll('\\'', '')
112
- }
113
- })
114
- if (_.isEmpty(op)) continue
115
- this[f + 'Op'] = op
116
- if (op === 'between') {
117
- const vals = val.split(',')
118
- this[f + 'Val'] = vals[0]
119
- this[f + 'Val2'] = vals[1]
120
- } else {
121
- this[f + 'Val'] = val
122
- }
123
- }
124
- },
125
- expandArray (val = '') {
126
- return _.map(val.split(','), item => {
127
- item = _.trim(item)
128
- if (Number(item)) return item
129
- return '\\'' + item + '\\''
130
- })
131
- },
132
- rebuild () {
133
- const items = []
134
- for (const sel of this.selected) {
135
- const key = this[sel + 'Op']
136
- let val = this[sel + 'Val']
137
- let val2 = this[sel + 'Val2']
138
- if (_.isEmpty(val)) continue
139
- if (key === 'between' && _.isEmpty(val2)) continue
140
- let item
141
- if (key === 'in') item = this.opsIn(val)
142
- else if (key === '!in') item = this.opsIn(val, true)
143
- else if (key === 'between') item = this.opsBetween(val, val2, false)
144
- else if (key === '!between') item = this.opsBetween(val, val2, true)
145
- else if (key === 'contains') item = this.opsExt(val)
146
- else if (key === '!contains') item = this.opsExt(val, true)
147
- else if (key === 'starts') item = this.opsExt(val, false, '^')
148
- else if (key === '!starts') item = this.opsExt(val, true, '^')
149
- else if (key === 'ends') item = this.opsExt(val, false, '$$')
150
- else if (key === '!ends') item = this.opsExt(val, true, '$$')
151
- else if (val.includes(' ')) item = this.ops[key] + '\\'' + val + '\\''
152
- else item = this.ops[key] + val
153
- items.push(sel + item)
154
- }
155
- this.builder = items.join('+')
156
- },
157
- submit (run) {
158
- if (run) {
194
+ if (this.params.attr.mini) {
195
+ this.params.html = await this.component.buildSentence(`
196
+ ${this.modal({ container, models, columns, fields, id })}
197
+ `)
198
+ } else {
199
+ let placeholder = this.params.attr.placeholder
200
+ if (!placeholder) placeholder = scanables.length > 0 ? req.t('queryHint%s', join(scanables, { separator: ', ', lastSeparator: 'or' })) : req.t('query')
201
+ this.params.html = await this.component.buildSentence(`
202
+ <c:form-input type="search" placeholder="${placeholder}" id="${id}" x-data="{ query: '' }" x-init="
203
+ const url = new URL(window.location.href)
204
+ query = url.searchParams.get('${qsKey.query}') ?? ''
205
+ " x-model="query" @on-query.window="query = $event.detail ?? ''" @keyup.enter="$dispatch('on-submit')">
206
+ <c:form-input-addon>
207
+ ${this.modal({ container, models, columns, fields, id })}
208
+ </c:form-input-addon>
209
+ <c:form-input-addon>
210
+ <c:btn t:content="submit" x-data="{
211
+ submit () {
212
+ const val = document.getElementById('${id}').value ?? ''
159
213
  const url = new URL(window.location.href)
160
214
  const params = new URLSearchParams(url.search)
161
215
  params.set('${qsKey.page}', 1)
162
- params.set('${qsKey.query}', this.builder ?? '')
216
+ params.set('${qsKey.query}', val)
163
217
  window.location.href = '?' + params.toString()
164
- } else $dispatch('on-query', this.builder)
165
- const instance = wbs.getInstance('${upperFirst(container)}', $refs.query)
166
- instance.hide()
167
- }
168
- }" x-init="
169
- parse()
170
- const ops = _.map(fields, f => (f + 'Op'))
171
- const vals = _.map(fields, f => (f + 'Val'))
172
- const vals2 = _.map(fields, f => (f + 'Val2'))
173
- const watcher = ['selected', ...ops, ...vals, ...vals2].join(',')
174
- $watch(watcher, v => rebuild())
175
- " ${this.params.attr.modal ? '' : 'style="width:600px;"'}>
176
- <c:grid-row gutter="2">
177
- <c:grid-col col="12">
178
- <c:form-textarea x-model="builder" readonly rows="4"/>
179
- </c:grid-col>
180
- ${columns.join('\n')}
181
- </c:grid-row>
182
- <c:div flex="justify-content:end" margin="top-3">
183
- <c:btn color="secondary" t:content="close" dismiss="${container}" />
184
- <c:btn color="primary" t:content="apply" margin="start-2" @click="submit()" />
185
- <c:btn color="primary" t:content="submitQuery" margin="start-2" @click="submit(true)" />
186
- </c:div>
187
- </c:${container}>
188
- </c:form-input-addon>
189
- <c:form-input-addon>
190
- <c:btn t:content="submit" x-data="{
191
- submit () {
192
- const val = document.getElementById('${id}').value ?? ''
193
- const url = new URL(window.location.href)
194
- const params = new URLSearchParams(url.search)
195
- params.set('${qsKey.page}', 1)
196
- params.set('${qsKey.query}', val)
197
- window.location.href = '?' + params.toString()
198
- }
199
- }" @click="submit" @on-submit.window="submit()" />
200
- </c:form-input-addon>
201
- </c:form-input>
202
- `)
218
+ }
219
+ }" @click="submit" @on-submit.window="submit()" />
220
+ </c:form-input-addon>
221
+ </c:form-input>
222
+ `)
223
+ }
203
224
  }
204
225
  }
205
226
  }
@@ -23,9 +23,9 @@ async function recsInfo () {
23
23
  this.params.html = ''
24
24
  return
25
25
  }
26
- page = page ?? get(this, 'component.locals.list.page', 1)
27
- limit = limit ?? get(this, 'component.locals.list.limit', 25)
28
- pages = pages ?? get(this, 'component.locals.list.pages', 0)
26
+ page = get(this, 'component.locals.list.page', page ?? 1)
27
+ limit = get(this, 'component.locals.list.limit', limit ?? 25)
28
+ pages = get(this, 'component.locals.list.pages', pages ?? 0)
29
29
 
30
30
  this.params.tag = 'div'
31
31
  this.params.attr.flex = 'justify-center:start align-items:center'
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import countRecord from './lib/method/count-record.js'
2
- import createAggregate from './lib/method/create-aggregate.js'
3
- import createHistogram from './lib/method/create-histogram.js'
2
+ import aggregate from './lib/method/aggregate.js'
3
+ import histogram from './lib/method/histogram.js'
4
4
  import createRecord from './lib/method/create-record.js'
5
5
  import findOneRecord from './lib/method/find-one-record.js'
6
6
  import findRecord from './lib/method/find-record.js'
@@ -59,8 +59,8 @@ async function factory (pkgName) {
59
59
 
60
60
  this.bindThis(
61
61
  countRecord,
62
- createAggregate,
63
- createHistogram,
62
+ aggregate,
63
+ histogram,
64
64
  createRecord,
65
65
  findOneRecord,
66
66
  findRecord,
@@ -36,7 +36,7 @@ async function exportHandler (opts = {}) {
36
36
  const mdl = this.app.dobo.getModel(model)
37
37
  const { schema } = await getSchemaExt(model, 'add', merge({ args: [{ req, model: mdl }] }, { params }, options))
38
38
  if (schema.disabled.includes('find')) return await reply.view(templateDisabled, { action: 'list' })
39
- const crud = await prepCrud.call(this.app.getPlugin('waibuDb'), { model, req, reply, args: ['model'] })
39
+ const crud = await prepCrud.call(this.app.getPlugin('waibuDb'), { model, req, reply, args: ['model'], options })
40
40
  const data = {
41
41
  name: model,
42
42
  filter: crud.filter,
@@ -22,7 +22,7 @@ export async function addOnsHandler (opts = {}) {
22
22
  const { req, reply, schema } = opts
23
23
  const { escape } = this.app.waibu
24
24
  const { base64JsonEncode } = this.app.waibu
25
- const { createAggregate } = this.app.waibuDb
25
+ const { aggregate } = this.app.waibuDb
26
26
  const { get, map, pick, pullAt } = this.app.lib._
27
27
  const _opts = map(get(schema, 'view.stat.aggregate', []), item => {
28
28
  const dbOpts = pick(item, ['fields', 'group', 'aggregate'])
@@ -34,7 +34,7 @@ export async function addOnsHandler (opts = {}) {
34
34
  for (const idx in _opts) {
35
35
  const o = _opts[idx]
36
36
  try {
37
- const resp = await createAggregate({ model: schema.name, req, reply, options: o.dbOpts })
37
+ const resp = await aggregate({ model: schema.name, req, reply, options: o.dbOpts })
38
38
  const data = []
39
39
  for (const d of resp.data) {
40
40
  const key = o.dbOpts.fields[0]
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function createAggregate ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function aggregate ({ model, req, reply, options = {}, noAutoFilter, transaction } = {}) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
  const params = {}
6
6
  for (const item of ['group', 'field', 'aggregates']) {
7
7
  params[item] = options[item] ?? req.params[item] ?? req.query[item]
@@ -10,10 +10,10 @@ async function createAggregate ({ model, req, reply, options = {}, transaction }
10
10
 
11
11
  async function handler (trx) {
12
12
  if (opts.trx === true) opts.trx = trx
13
- return await mdl.createAggregate(filter, params, opts)
13
+ return await mdl.aggregate(filter, params, opts)
14
14
  }
15
15
 
16
- return await processHandler.call(this, { action: 'createAggregate', model: mdl, handler, options: opts })
16
+ return await processHandler.call(this, { action: 'aggregate', model: mdl, handler, options: opts })
17
17
  }
18
18
 
19
- export default createAggregate
19
+ export default aggregate
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function countRecord ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function countRecord ({ model, req, reply, options = {}, noAutoFilter, transaction } = {}) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
 
6
6
  async function handler (trx) {
7
7
  if (opts.trx === true) opts.trx = trx
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function findAllRecord ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function findAllRecord ({ model, req, reply, options = {}, noAutoFilter, transaction } = {}) {
4
+ const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
 
6
6
  async function handler (trx) {
7
7
  if (opts.trx === true) opts.trx = trx
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function findOneRecord ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function findOneRecord ({ model, req, reply, options = {}, noAutoFilter, transaction } = {}) {
4
+ const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
 
6
6
  async function handler (trx) {
7
7
  if (opts.trx === true) opts.trx = trx
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function findRecord ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function findRecord ({ model, req, reply, noAutoFilter, options = {}, transaction } = {}) {
4
+ const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
 
6
6
  async function handler (trx) {
7
7
  if (opts.trx === true) opts.trx = trx
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, getOneRecord, processHandler } from '../util.js'
2
2
 
3
- async function getRecord ({ model, req, reply, id, options = {}, transaction } = {}) {
4
- const { model: mdl, recId, filter, attachment, stats, mimeType, opts } = await prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'], transaction })
3
+ async function getRecord ({ model, req, reply, id, options = {}, transaction, noAutoFilter } = {}) {
4
+ const { model: mdl, recId, filter, attachment, stats, mimeType, opts } = await prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'], transaction, noAutoFilter })
5
5
  const me = this
6
6
 
7
7
  async function handler (trx) {
@@ -1,7 +1,7 @@
1
1
  import { prepCrud, processHandler } from '../util.js'
2
2
 
3
- async function createHistogram ({ model, req, reply, options = {}, transaction } = {}) {
4
- const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], transaction })
3
+ async function histogram ({ model, req, reply, options = {}, noAutoFilter, transaction } = {}) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'], noAutoFilter, transaction })
5
5
  const params = {}
6
6
  for (const item of ['type', 'group', 'field', 'aggregates']) {
7
7
  params[item] = options[item] ?? req.params[item] ?? req.query[item]
@@ -10,10 +10,10 @@ async function createHistogram ({ model, req, reply, options = {}, transaction }
10
10
 
11
11
  async function handler (trx) {
12
12
  if (opts.trx === true) opts.trx = trx
13
- return await mdl.createHistogram(filter, params, opts)
13
+ return await mdl.histogram(filter, params, opts)
14
14
  }
15
15
 
16
- return await processHandler.call(this, { action: 'createHistogram', model: mdl, handler, options: opts })
16
+ return await processHandler.call(this, { action: 'histogram', model: mdl, handler, options: opts })
17
17
  }
18
18
 
19
- export default createHistogram
19
+ export default histogram
package/lib/util.js CHANGED
@@ -22,8 +22,8 @@
22
22
  * @typedef TActions
23
23
  * @type {Object}
24
24
  * @property {number} 0='countRecord' - Count the number of records
25
- * @property {number} 1='createAggregate' - Create an aggregate record
26
- * @property {number} 2='createHistogram' - Create a histogram record
25
+ * @property {number} 1='aggregate' - Create an aggregate record
26
+ * @property {number} 2='histogram' - Create a histogram record
27
27
  * @property {number} 3='createRecord' - Create a new record
28
28
  * @property {number} 4='findAllRecord' - Find all records
29
29
  * @property {number} 5='findOneRecord' - Find one record
@@ -32,7 +32,7 @@
32
32
  * @property {number} 8='removeRecord' - Remove a record
33
33
  * @property {number} 9='updateRecord' - Update a record
34
34
  */
35
- export const actions = ['countRecord', 'createAggregate', 'createHistogram', 'createRecord', 'findAllRecord', 'findOneRecord', 'findRecord', 'getRecord', 'removeRecord', 'updateRecord']
35
+ export const actions = ['countRecord', 'aggregate', 'histogram', 'createRecord', 'findAllRecord', 'findOneRecord', 'findRecord', 'getRecord', 'removeRecord', 'updateRecord']
36
36
 
37
37
  /**
38
38
  * Prepare CRUD operation parameters.
@@ -43,12 +43,13 @@ export const actions = ['countRecord', 'createAggregate', 'createHistogram', 'cr
43
43
  * @param {Object} [options.req] - The request object
44
44
  * @param {Object} [options.reply] - The reply object
45
45
  * @param {Object} [options.transaction] - The transaction object
46
+ * @param {boolean} [options.noAutoFilter] - Disable automatic filter parsing from `req.query`
46
47
  * @param {Object} [options.options] - Additional options
47
48
  * @param {Array} [options.args] - Additional arguments
48
49
  * @returns {Object} Prepared CRUD parameters
49
50
  */
50
51
  export async function prepCrud (options = {}) {
51
- let { model, id, req, reply, transaction, options: _options = {}, args } = options
52
+ let { model, id, req, reply, transaction, options: _options = {}, args, noAutoFilter } = options
52
53
  const { isSet } = this.app.lib.aneka
53
54
  const { importModule } = this.app.bajo
54
55
  const { parseFilter } = this.app.waibu
@@ -93,9 +94,12 @@ export async function prepCrud (options = {}) {
93
94
  }
94
95
  opts.bboxLatField = req.query[cfgWeb.qsKey.bboxLatField]
95
96
  opts.bboxLngField = req.query[cfgWeb.qsKey.bboxLngField]
96
- const filter = parseFilter(req)
97
- filter.query = buildFilterQuery.call(mdl, filter)
98
- filter.search = buildFilterSearch.call(mdl, filter)
97
+ let filter = { query: {}, search: {} }
98
+ if (!noAutoFilter) {
99
+ filter = parseFilter(req)
100
+ filter.query = buildFilterQuery.call(mdl, filter)
101
+ filter.search = buildFilterSearch.call(mdl, filter)
102
+ }
99
103
  if (_options.query) filter.query = cloneDeep(_options.query)
100
104
  if (_options.search) filter.search = cloneDeep(_options.search)
101
105
  if (_options.limit) filter.limit = _options.limit
@@ -143,7 +147,7 @@ export async function processHandler (opts = {}) {
143
147
  if (!(req.method === 'POST' && req.body._action === 'export' && options.allowExport)) return
144
148
  const { importModule } = this.app.bajo
145
149
  const exportHandler = await importModule('waibuDb:/lib/crud/export-handler.js')
146
- await exportHandler.call(this, { model: model.name, req, reply })
150
+ await exportHandler.call(this, { model: model.name, req, reply, options })
147
151
  }
148
152
 
149
153
  function suppressedReturn (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "2.32.2",
3
+ "version": "2.33.1",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-08-19
4
+
5
+ - [2.33.1] Bug fix in `wdb-btn-export` widget
6
+ - [2.33.1] Bug fix in `export-handler.js`
7
+ - [2.33.1] Bug fix in `util.js`
8
+
9
+ ## 2026-08-18
10
+
11
+ - [2.33.0] Update things to match `dobo@2.38.0`
12
+
3
13
  ## 2026-07-29
4
14
 
5
15
  - [2.32.2] Bug fix in `export-handler.js`