dobo 2.29.1 → 2.30.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/extend/dobo/driver/memory.js +1 -2
- package/index.js +14 -3
- package/lib/factory/driver.js +1 -1
- package/lib/factory/model/_util.js +2 -4
- package/lib/factory/model/find-attachment.js +1 -2
- package/lib/factory/model/list-attachment.js +2 -2
- package/lib/factory/model/load-fixtures.js +1 -2
- package/lib/factory/model/sanitize-body.js +5 -11
- package/package.json +1 -1
- package/wiki/CHANGES.md +8 -0
|
@@ -27,9 +27,8 @@ async function memoryDriverFactory () {
|
|
|
27
27
|
|
|
28
28
|
async connect (connection, noRebuild) {
|
|
29
29
|
const conn = this.plugin.getConnection('memory')
|
|
30
|
-
const { getPluginDataDir } = this.app.bajo
|
|
31
30
|
const { fs } = this.app.lib
|
|
32
|
-
const dir = `${getPluginDataDir(this.plugin.ns)}/memDb/data` // persistence dir
|
|
31
|
+
const dir = `${this.app.getPluginDataDir(this.plugin.ns)}/memDb/data` // persistence dir
|
|
33
32
|
fs.ensureDirSync(dir)
|
|
34
33
|
conn.persistences = conn.persistences ?? []
|
|
35
34
|
|
package/index.js
CHANGED
|
@@ -233,13 +233,12 @@ async function factory (pkgName) {
|
|
|
233
233
|
* @async
|
|
234
234
|
*/
|
|
235
235
|
init = async () => {
|
|
236
|
-
const { getPluginDataDir } = this.app.bajo
|
|
237
236
|
const { fs } = this.app.lib
|
|
238
237
|
await collectDrivers.call(this)
|
|
239
238
|
await collectConnections.call(this)
|
|
240
239
|
await collectFeatures.call(this)
|
|
241
240
|
await collectModels.call(this)
|
|
242
|
-
const attDir = `${getPluginDataDir('dobo')}/attachment`
|
|
241
|
+
const attDir = `${this.app.getPluginDataDir('dobo')}/attachment`
|
|
243
242
|
fs.ensureDirSync(attDir)
|
|
244
243
|
}
|
|
245
244
|
|
|
@@ -369,7 +368,6 @@ async function factory (pkgName) {
|
|
|
369
368
|
sanitizeDate = (value, { inputFormat, outputFormat, silent = true } = {}) => {
|
|
370
369
|
const { dayjs } = this.app.lib
|
|
371
370
|
if (value === 0) return null
|
|
372
|
-
if (!outputFormat) outputFormat = inputFormat
|
|
373
371
|
const dt = dayjs(value, inputFormat)
|
|
374
372
|
if (!dt.isValid()) {
|
|
375
373
|
if (silent) return null
|
|
@@ -428,6 +426,19 @@ async function factory (pkgName) {
|
|
|
428
426
|
return value + ''
|
|
429
427
|
}
|
|
430
428
|
|
|
429
|
+
sanitizeByType = (value, type, opts = {}) => {
|
|
430
|
+
const { isNaN } = this.app.lib._
|
|
431
|
+
let result = value
|
|
432
|
+
if (['object', 'array'].includes(type)) result = this.sanitizeObject(value, opts)
|
|
433
|
+
else if (type === 'boolean') result = this.sanitizeBoolean(value)
|
|
434
|
+
else if (['float', 'double'].includes(type)) result = this.sanitizeFloat(value, opts)
|
|
435
|
+
else if (['integer', 'smallint'].includes(type)) result = this.sanitizeInt(value, opts)
|
|
436
|
+
else if (['string', 'text'].includes(type)) result = this.sanitizeString(result, opts)
|
|
437
|
+
else if (['datetime'].includes(type)) result = this.sanitizeDate(result, opts)
|
|
438
|
+
if (!opts.strict && isNaN(result)) result = null
|
|
439
|
+
return result
|
|
440
|
+
}
|
|
441
|
+
|
|
431
442
|
_calcStats = (items, field, aggregates) => {
|
|
432
443
|
const { generateId, isSet } = this.app.lib.aneka
|
|
433
444
|
const result = { id: generateId, count: 0, avg: null, min: null, max: null }
|
package/lib/factory/driver.js
CHANGED
|
@@ -378,7 +378,7 @@ async function driverFactory () {
|
|
|
378
378
|
result = await this.findRecord(model, filter, options)
|
|
379
379
|
await this._attachHook('afterFindRecord', model, filter, result, options)
|
|
380
380
|
} catch (err) {
|
|
381
|
-
if (err.message
|
|
381
|
+
if (!['_emptyColumnQuery', '_abortAction'].includes(err.message)) throw err
|
|
382
382
|
result = {
|
|
383
383
|
data: [],
|
|
384
384
|
count: 0
|
|
@@ -125,9 +125,8 @@ export async function mergeAttachmentInfo (rec, source, options = {}) {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
export async function getAttachmentPath (id, field, file, options = {}) {
|
|
128
|
-
const { getPluginDataDir } = this.app.bajo
|
|
129
128
|
const { fs } = this.app.lib
|
|
130
|
-
const dir = `${getPluginDataDir(this.app.dobo.ns)}/attachment/${this.name}/${id}`
|
|
129
|
+
const dir = `${this.app.getPluginDataDir(this.app.dobo.ns)}/attachment/${this.name}/${id}`
|
|
131
130
|
if (options.dirOnly) return dir
|
|
132
131
|
const path = field ? `${dir}/${field}/${file}` : `${dir}/${file}`
|
|
133
132
|
if (!fs.existsSync(path)) throw this.app.dobo.error('notFound')
|
|
@@ -160,11 +159,10 @@ export async function copyAttachment (id, options = {}) {
|
|
|
160
159
|
|
|
161
160
|
export async function handleAttachmentUpload (id, trigger, options = {}) {
|
|
162
161
|
if (!this.options.attachment) return
|
|
163
|
-
const { getPluginDataDir } = this.app.bajo
|
|
164
162
|
const { fs } = this.app.lib
|
|
165
163
|
const { req, mimeType, stats, setFile, setField } = options
|
|
166
164
|
if (trigger === 'removed') {
|
|
167
|
-
const dir = `${getPluginDataDir(this.app.dobo.ns)}/attachment/${this.name}/${id}`
|
|
165
|
+
const dir = `${this.app.getPluginDataDir(this.app.dobo.ns)}/attachment/${this.name}/${id}`
|
|
168
166
|
await fs.remove(dir)
|
|
169
167
|
return
|
|
170
168
|
}
|
|
@@ -6,8 +6,7 @@ async function findAttachment (...args) {
|
|
|
6
6
|
if (args.length === 0) return this.action(action, ...args)
|
|
7
7
|
const [id, opts = {}] = args
|
|
8
8
|
const { fastGlob, fs } = this.app.lib
|
|
9
|
-
const
|
|
10
|
-
const dir = `${getPluginDataDir(this.plugin.ns)}/attachment/${this.name}/${id}`
|
|
9
|
+
const dir = `${this.app.getPluginDataDir(this.plugin.ns)}/attachment/${this.name}/${id}`
|
|
11
10
|
if (!fs.existsSync(dir)) return []
|
|
12
11
|
const files = await fastGlob(`${dir}/**/*`)
|
|
13
12
|
const { fullPath, stats, mimeType } = opts
|
|
@@ -6,13 +6,13 @@ async function listAttachment (...args) {
|
|
|
6
6
|
if (args.length === 0) return this.action(action, ...args)
|
|
7
7
|
const [params = {}, opts = {}] = args
|
|
8
8
|
const { map, kebabCase } = this.app.lib._
|
|
9
|
-
const { importPkg
|
|
9
|
+
const { importPkg } = this.app.bajo
|
|
10
10
|
const mime = await importPkg('waibu:mime')
|
|
11
11
|
const { fastGlob } = this.app.lib
|
|
12
12
|
|
|
13
13
|
const { id = '*', field = '*', file = '*', type } = params
|
|
14
14
|
const { uriEncoded = true } = opts
|
|
15
|
-
const root = `${getPluginDataDir('dobo')}/attachment`
|
|
15
|
+
const root = `${this.app.getPluginDataDir('dobo')}/attachment`
|
|
16
16
|
let pattern = `${root}/${this.name}/${id}/${field}/${file}`
|
|
17
17
|
if (type === 'image') pattern += '.{jpg,jpeg,gif,png,webp,avif,svg}'
|
|
18
18
|
else if (type === 'video') pattern += '.{mp4,m4v,webm,mov,qt,mkv,ogg,ogv}'
|
|
@@ -2,7 +2,6 @@ import path from 'path'
|
|
|
2
2
|
|
|
3
3
|
async function exec ({ body, spinner, options, result, bodies } = {}) {
|
|
4
4
|
const { isArray, isString } = this.app.lib._
|
|
5
|
-
const { getPluginDataDir } = this.app.bajo
|
|
6
5
|
const { fs } = this.app.lib
|
|
7
6
|
|
|
8
7
|
await this.transaction(async (trx) => {
|
|
@@ -12,7 +11,7 @@ async function exec ({ body, spinner, options, result, bodies } = {}) {
|
|
|
12
11
|
if (isString(att)) att = { field: 'file', file: att }
|
|
13
12
|
const fname = path.basename(att.file)
|
|
14
13
|
if (fs.existsSync(att.file)) {
|
|
15
|
-
const dest = `${getPluginDataDir(this.plugin.ns)}/${resp.id}/${att.field}/${fname}`
|
|
14
|
+
const dest = `${this.app.getPluginDataDir(this.plugin.ns)}/${resp.id}/${att.field}/${fname}`
|
|
16
15
|
try {
|
|
17
16
|
fs.copySync(att.file, dest)
|
|
18
17
|
} catch (err) {}
|
|
@@ -15,25 +15,19 @@
|
|
|
15
15
|
async function sanitizeBody ({ body = {}, partial, strict, extFields = [], noDefault, truncateString, onlyTypes = [], action } = {}) {
|
|
16
16
|
const { isSet } = this.app.lib.aneka
|
|
17
17
|
const { callHandler } = this.app.bajo
|
|
18
|
-
const {
|
|
19
|
-
const {
|
|
18
|
+
const { sanitizeByType } = this.app.dobo
|
|
19
|
+
const { omit, has, isString } = this.app.lib._
|
|
20
20
|
const result = {}
|
|
21
21
|
|
|
22
22
|
const sanitize = (name, type) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
else if (type === 'boolean') result[name] = sanitizeBoolean(result[name])
|
|
26
|
-
else if (['float', 'double'].includes(type)) result[name] = sanitizeFloat(result[name], { strict })
|
|
27
|
-
else if (['integer', 'smallint'].includes(type)) result[name] = sanitizeInt(result[name], { strict })
|
|
28
|
-
else if (['string', 'text'].includes(type)) result[name] = sanitizeString(result[name], { strict })
|
|
29
|
-
else if (['datetime'].includes(type)) result[name] = sanitizeDate(result[name], { input: 'native' })
|
|
30
|
-
if (!strict && isNaN(result[name])) result[name] = null
|
|
23
|
+
const opts = { strict, action, model: this.name, inputFormat: 'native' }
|
|
24
|
+
result[name] = sanitizeByType(result[name], type, opts)
|
|
31
25
|
if (['updateRecord', 'upsertRecord'].includes(action) && type === 'string' && result[name] === '') result[name] = null
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
const omitted = []
|
|
35
29
|
const details = []
|
|
36
|
-
const properties = [...this.
|
|
30
|
+
const properties = [...this.getProperties(), ...extFields]
|
|
37
31
|
for (const prop of properties) {
|
|
38
32
|
try {
|
|
39
33
|
if (partial && !has(body, prop.name)) {
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-06-12
|
|
4
|
+
|
|
5
|
+
- [2.30.0] Necessary updates to ```bajo@2.18.0``` specs
|
|
6
|
+
- [2.30.0] Add ```sanitizeByType()```
|
|
7
|
+
- [2.30.0] Add ```error._abortAction``` to abort an action in driver level
|
|
8
|
+
- [2.30.0] Refactor ```model.sanitizeBody()``` to use shared sanitizing function
|
|
9
|
+
|
|
3
10
|
## 2026-06-11
|
|
4
11
|
|
|
5
12
|
- [2.29.1] Bug fix in ```model.sanitizeBody()```
|
|
13
|
+
- [2.29.2] Bug fix in ```model.sanitizeBody()```
|
|
6
14
|
|
|
7
15
|
## 2026-06-10
|
|
8
16
|
|