waibu-db 2.27.0 → 2.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.
- package/.jsdoc.conf.json +1 -1
- package/docs/WaibuDb.html +1 -1
- package/docs/data/search.json +1 -1
- package/docs/external-DoboModel.html +3 -0
- package/docs/external-TFilter.html +3 -0
- package/docs/external-TOptions.html +3 -0
- package/docs/global.html +1 -1
- package/docs/index.html +1 -1
- package/docs/index.js.html +109 -85
- package/docs/lib_config.js.html +48 -0
- package/docs/lib_crud_add-handler.js.html +82 -0
- package/docs/lib_crud_all-handler.js.html +81 -0
- package/docs/lib_crud_delete-handler.js.html +67 -0
- package/docs/lib_crud_details-handler.js.html +55 -0
- package/docs/lib_crud_edit-handler.js.html +90 -0
- package/docs/lib_crud_export-handler.js.html +72 -0
- package/docs/lib_crud_helper.js.html +118 -0
- package/docs/lib_crud_list-handler.js.html +61 -0
- package/docs/lib_util.js.html +161 -0
- package/docs/module-CRUDHandler.html +24 -0
- package/docs/module-CRUDHandler_Helper.html +3 -0
- package/docs/module-Helper.html +3 -0
- package/docs/module-Helper_CRUDHandler.html +6 -0
- package/extend/waibuBootstrap/theme/component/widget/btn-export.js +2 -1
- package/index.js +80 -30
- package/lib/config.js +45 -0
- package/lib/crud/add-handler.js +31 -4
- package/lib/crud/all-handler.js +47 -1
- package/lib/crud/delete-handler.js +28 -6
- package/lib/crud/details-handler.js +29 -4
- package/lib/crud/edit-handler.js +34 -6
- package/lib/crud/export-handler.js +45 -4
- package/lib/crud/helper.js +59 -10
- package/lib/crud/list-handler.js +30 -3
- package/lib/util.js +98 -20
- package/package.json +1 -1
- package/wiki/CHANGES.md +9 -0
package/lib/util.js
CHANGED
|
@@ -1,16 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Helper
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @external DoboModel
|
|
7
|
+
* @see {@link https://ardhi.github.io/dobo/DoboModel.html|DoboModel}
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @external TFilter
|
|
12
|
+
* @see {@link https://ardhi.github.io/dobo/DoboModel.html#.TFilter|TFilter}
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @external TOptions
|
|
17
|
+
* @see {@link https://ardhi.github.io/dobo/DoboModel.html#.TOptions|TOptions}
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Type of actions that can be performed on records in the database.
|
|
22
|
+
* @typedef TActions
|
|
23
|
+
* @type {Object}
|
|
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
|
|
27
|
+
* @property {number} 3='createRecord' - Create a new record
|
|
28
|
+
* @property {number} 4='findAllRecord' - Find all records
|
|
29
|
+
* @property {number} 5='findOneRecord' - Find one record
|
|
30
|
+
* @property {number} 6='findRecord' - Find records
|
|
31
|
+
* @property {number} 7='getRecord' - Get a record
|
|
32
|
+
* @property {number} 8='removeRecord' - Remove a record
|
|
33
|
+
* @property {number} 9='updateRecord' - Update a record
|
|
34
|
+
*/
|
|
1
35
|
export const actions = ['countRecord', 'createAggregate', 'createHistogram', 'createRecord', 'findAllRecord', 'findOneRecord', 'findRecord', 'getRecord', 'removeRecord', 'updateRecord']
|
|
2
36
|
|
|
3
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Prepare CRUD operation parameters.
|
|
39
|
+
* @async
|
|
40
|
+
* @param {Object} [options={}] - Options for preparing CRUD operation
|
|
41
|
+
* @param {string|external:DoboModel} options.model - The model to operate on
|
|
42
|
+
* @param {string|number} [options.id] - The record ID
|
|
43
|
+
* @param {Object} [options.req] - The request object
|
|
44
|
+
* @param {Object} [options.reply] - The reply object
|
|
45
|
+
* @param {Object} [options.transaction] - The transaction object
|
|
46
|
+
* @param {Object} [options.options] - Additional options
|
|
47
|
+
* @param {Array} [options.args] - Additional arguments
|
|
48
|
+
* @returns {Object} Prepared CRUD parameters
|
|
49
|
+
*/
|
|
50
|
+
export async function prepCrud (options = {}) {
|
|
51
|
+
let { model, id, req, reply, transaction, options: _options = {}, args } = options
|
|
4
52
|
const { isSet } = this.app.lib.aneka
|
|
5
53
|
const { importModule } = this.app.bajo
|
|
6
54
|
const { parseFilter } = this.app.waibu
|
|
7
55
|
const { pascalCase } = this.app.lib.aneka
|
|
8
56
|
const { cloneDeep, has, isString, omit } = this.app.lib._
|
|
9
57
|
const { parseObject } = this.app.lib
|
|
10
|
-
const { buildFilterQuery, buildFilterSearch } = await importModule('dobo:/lib/factory/model/
|
|
58
|
+
const { buildFilterQuery, buildFilterSearch } = await importModule('dobo:/lib/factory/model/helper.js', { asDefaultImport: false })
|
|
11
59
|
|
|
12
60
|
const cfgWeb = this.app.waibu.getConfig()
|
|
13
|
-
const opts = cloneDeep(omit(
|
|
61
|
+
const opts = cloneDeep(omit(_options, ['trx']))
|
|
14
62
|
opts.throwNotFound = true
|
|
15
63
|
if (opts.suppressError === true) opts.suppressError = actions
|
|
16
64
|
else if (isString(opts.suppressError)) opts.suppressError = [opts.suppressError]
|
|
@@ -19,11 +67,11 @@ export async function prepCrud ({ model, id, req, reply, transaction, options =
|
|
|
19
67
|
for (const k of ['count', 'fields']) {
|
|
20
68
|
opts[k] = opts[k] ?? params[k]
|
|
21
69
|
}
|
|
22
|
-
if (has(
|
|
70
|
+
if (has(_options, 'count')) opts.count = _options.count
|
|
23
71
|
opts.dataOnly = opts.dataOnly ?? false
|
|
24
72
|
opts.req = req
|
|
25
73
|
opts.reply = reply
|
|
26
|
-
opts.trx = opts.trx ??
|
|
74
|
+
opts.trx = opts.trx ?? _options.trx ?? transaction ?? true
|
|
27
75
|
|
|
28
76
|
let { attachment, stats, mimeType } = opts
|
|
29
77
|
attachment = attachment ?? req.query.attachment
|
|
@@ -32,10 +80,10 @@ export async function prepCrud ({ model, id, req, reply, transaction, options =
|
|
|
32
80
|
|
|
33
81
|
let refs = []
|
|
34
82
|
const headers = parseObject(req.headers, { parseValue: true })
|
|
35
|
-
if (isSet(headers['x-count']))
|
|
83
|
+
if (isSet(headers['x-count'])) _options.count = headers['x-count']
|
|
36
84
|
if (isSet(headers['x-refs'])) refs = headers['x-refs']
|
|
37
85
|
if (typeof refs === 'string' && !['*', 'all'].includes(refs)) refs = [refs]
|
|
38
|
-
if (refs.length > 0)
|
|
86
|
+
if (refs.length > 0) _options.refs = refs
|
|
39
87
|
|
|
40
88
|
const recId = id ?? params.id ?? req.query.id
|
|
41
89
|
let mdl = model
|
|
@@ -48,16 +96,26 @@ export async function prepCrud ({ model, id, req, reply, transaction, options =
|
|
|
48
96
|
const filter = parseFilter(req)
|
|
49
97
|
filter.query = buildFilterQuery.call(mdl, filter)
|
|
50
98
|
filter.search = buildFilterSearch.call(mdl, filter)
|
|
51
|
-
if (
|
|
52
|
-
if (
|
|
53
|
-
if (
|
|
54
|
-
if (
|
|
55
|
-
if (
|
|
99
|
+
if (_options.query) filter.query = cloneDeep(_options.query)
|
|
100
|
+
if (_options.search) filter.search = cloneDeep(_options.search)
|
|
101
|
+
if (_options.limit) filter.limit = _options.limit
|
|
102
|
+
if (_options.sort) filter.sort = _options.sort
|
|
103
|
+
if (_options.page) filter.page = _options.page
|
|
56
104
|
if (opts.fields && opts.fields.length > 0 && mdl.hasProperty('_immutable')) opts.fields.push('_immutable')
|
|
57
|
-
|
|
105
|
+
const input = cloneDeep(req.body) ?? {}
|
|
106
|
+
return { model: mdl, input, recId, opts, filter, attachment, stats, mimeType }
|
|
58
107
|
}
|
|
59
108
|
|
|
60
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Get a single record from the database based on the provided model, ID, filter, and options.
|
|
111
|
+
* @async
|
|
112
|
+
* @param {external:DoboModel} model - The model to query
|
|
113
|
+
* @param {string|number} id - The ID of the record to retrieve
|
|
114
|
+
* @param {external:TFilter} [filter={}] - The filter criteria for the query
|
|
115
|
+
* @param {external:TOptions} [options={}] - Additional options for the query
|
|
116
|
+
* @returns {Promise<Object>} The retrieved record
|
|
117
|
+
*/
|
|
118
|
+
export async function getOneRecord (model, id, filter = {}, options = {}) {
|
|
61
119
|
const { cloneDeep, pick, isEmpty } = this.app.lib._
|
|
62
120
|
let query = cloneDeep(filter.query || {})
|
|
63
121
|
query = { $and: [query, { id }] }
|
|
@@ -68,17 +126,37 @@ export async function getOneRecord (model, id, filter, options) {
|
|
|
68
126
|
return data
|
|
69
127
|
}
|
|
70
128
|
|
|
71
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Process a database operation with error suppression and transaction handling.
|
|
131
|
+
* @async
|
|
132
|
+
* @param {Object} [opts={}] - Options for processing the handler
|
|
133
|
+
* @param {string} opts.action - The action to perform (e.g., 'createRecord', 'updateRecord')
|
|
134
|
+
* @param {external:DoboModel} opts.model - The model to operate on
|
|
135
|
+
* @param {Function} opts.handler - The handler function to execute
|
|
136
|
+
* @param {external:TOptions} [opts.options] - Additional options for the handler
|
|
137
|
+
*/
|
|
138
|
+
export async function processHandler (opts = {}) {
|
|
139
|
+
const { action, model, handler, options } = opts
|
|
140
|
+
const { req, reply } = options
|
|
141
|
+
|
|
142
|
+
const handleExport = async () => {
|
|
143
|
+
if (!(req.method === 'POST' && req.body._action === 'export' && options.allowExport)) return
|
|
144
|
+
const { importModule } = this.app.bajo
|
|
145
|
+
const exportHandler = await importModule('waibuDb:/lib/crud/export-handler.js')
|
|
146
|
+
await exportHandler.call(this, { model: model.name, req, reply })
|
|
147
|
+
}
|
|
148
|
+
|
|
72
149
|
function suppressedReturn (err) {
|
|
73
150
|
this.log.error(err)
|
|
74
|
-
if (action === 'countRecord') return options.dataOnly ? 0 : { data: 0, warnings: [
|
|
75
|
-
if (['createRecord', 'getRecord'].includes(action)) return options.dataOnly ? {} : { data: {}, warnings: [
|
|
76
|
-
if (action === 'removeRecord') return options.dataOnly ? {} : { oldData: {}, warnings: [
|
|
77
|
-
if (action === 'updateRecord') return options.dataOnly ? {} : { data: {}, oldData: {}, warnings: [
|
|
78
|
-
return options.dataOnly ? [] : { data: [], count: 0, page: 1, warnings: [
|
|
151
|
+
if (action === 'countRecord') return options.dataOnly ? 0 : { data: 0, warnings: [req.t('supppressedError')] }
|
|
152
|
+
if (['createRecord', 'getRecord'].includes(action)) return options.dataOnly ? {} : { data: {}, warnings: [req.t('supppressedError')] }
|
|
153
|
+
if (action === 'removeRecord') return options.dataOnly ? {} : { oldData: {}, warnings: [req.t('supppressedError')] }
|
|
154
|
+
if (action === 'updateRecord') return options.dataOnly ? {} : { data: {}, oldData: {}, warnings: [req.t('supppressedError')] }
|
|
155
|
+
return options.dataOnly ? [] : { data: [], count: 0, page: 1, warnings: [req.t('supppressedError')] }
|
|
79
156
|
}
|
|
80
157
|
|
|
81
158
|
try {
|
|
159
|
+
await handleExport()
|
|
82
160
|
if (options.trx === true && ['createRecord', 'updateRecord', 'upsertRecord', 'removeRecord'].includes(action)) {
|
|
83
161
|
return await model.transaction(handler, action, options)
|
|
84
162
|
}
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-07-13
|
|
4
|
+
|
|
5
|
+
- [2.28.0] Update documentations
|
|
6
|
+
- [2.28.0] Add feature to allow export only if `options.allowExport` is set to true
|
|
7
|
+
|
|
8
|
+
## 2026-07-12
|
|
9
|
+
|
|
10
|
+
- [2.27.1] Bug fix in `util.js`
|
|
11
|
+
|
|
3
12
|
## 2026-06-29
|
|
4
13
|
|
|
5
14
|
- [2.27.0] Add ```isActionAllowed()``` in ```wdb-base```
|