dobo 2.0.0 → 2.2.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/.github/FUNDING.yml +13 -0
- package/.github/workflows/repo-lockdown.yml +24 -0
- package/.jsdoc.conf.json +45 -0
- package/LICENSE +1 -1
- package/README.md +38 -19
- package/docs/Dobo.html +26 -0
- package/docs/data/search.json +1 -0
- package/docs/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/global.html +7 -0
- package/docs/index.html +3 -0
- package/docs/index.js.html +578 -0
- package/docs/lib_collect-connections.js.html +39 -0
- package/docs/lib_collect-drivers.js.html +52 -0
- package/docs/lib_collect-features.js.html +36 -0
- package/docs/lib_collect-schemas.js.html +94 -0
- package/docs/lib_index.js.html +6 -0
- package/docs/method_model_create.js.html +35 -0
- package/docs/method_model_drop.js.html +34 -0
- package/docs/method_model_exists.js.html +40 -0
- package/docs/method_record_count.js.html +69 -0
- package/docs/method_record_create.js.html +114 -0
- package/docs/method_record_find-all.js.html +44 -0
- package/docs/method_record_find-one.js.html +73 -0
- package/docs/method_record_find.js.html +118 -0
- package/docs/method_record_get.js.html +92 -0
- package/docs/method_record_remove.js.html +75 -0
- package/docs/method_record_update.js.html +107 -0
- package/docs/method_record_upsert.js.html +54 -0
- package/docs/method_sanitize_body.js.html +88 -0
- package/docs/method_sanitize_date.js.html +30 -0
- package/docs/method_sanitize_id.js.html +20 -0
- package/docs/method_validate.js.html +249 -0
- package/docs/module-Lib.html +3 -0
- package/docs/scripts/core.js +725 -0
- package/docs/scripts/core.min.js +23 -0
- package/docs/scripts/resize.js +90 -0
- package/docs/scripts/search.js +265 -0
- package/docs/scripts/search.min.js +6 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/scripts/third-party/fuse.js +9 -0
- package/docs/scripts/third-party/hljs-line-num-original.js +366 -0
- package/docs/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/scripts/third-party/hljs-original.js +5164 -0
- package/docs/scripts/third-party/hljs.js +1 -0
- package/docs/scripts/third-party/popper.js +5 -0
- package/docs/scripts/third-party/tippy.js +1 -0
- package/docs/scripts/third-party/tocbot.js +671 -0
- package/docs/scripts/third-party/tocbot.min.js +1 -0
- package/docs/static/bitcoin.jpeg +0 -0
- package/docs/static/home.md +25 -0
- package/docs/static/logo-ecosystem.png +0 -0
- package/docs/static/logo.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/styles/clean-jsdoc-theme.min.css +1 -0
- package/extend/bajo/intl/en-US.json +69 -30
- package/extend/bajo/intl/id.json +58 -29
- package/extend/bajoCli/applet/clear-record.js +22 -0
- package/extend/bajoCli/applet/connection.js +5 -5
- package/extend/bajoCli/applet/count-record.js +27 -0
- package/extend/bajoCli/applet/create-aggregate.js +33 -0
- package/extend/bajoCli/applet/create-histogram.js +33 -0
- package/extend/bajoCli/applet/create-record.js +39 -0
- package/extend/bajoCli/applet/find-record.js +27 -0
- package/extend/bajoCli/applet/get-record.js +27 -0
- package/extend/bajoCli/applet/lib/post-process.js +25 -26
- package/extend/bajoCli/applet/model.js +22 -0
- package/extend/bajoCli/applet/rebuild-model.js +91 -0
- package/extend/bajoCli/applet/remove-record.js +27 -0
- package/extend/bajoCli/applet/update-record.js +44 -0
- package/extend/bajoCli/applet.js +0 -0
- package/extend/dobo/driver/memory.js +170 -0
- package/extend/dobo/feature/created-at.js +10 -8
- package/extend/dobo/feature/dt.js +0 -0
- package/extend/dobo/feature/immutable.js +30 -0
- package/extend/dobo/feature/int-id.js +0 -0
- package/extend/dobo/feature/removed-at.js +35 -57
- package/extend/dobo/feature/updated-at.js +14 -12
- package/extend/waibuMpa/route/attachment/@model/@id/@field/@file.js +5 -9
- package/extend/waibuStatic/virtual.json +0 -0
- package/index.js +420 -337
- package/lib/collect-connections.js +60 -21
- package/lib/collect-drivers.js +29 -35
- package/lib/collect-features.js +40 -0
- package/lib/collect-models.js +319 -0
- package/lib/factory/action.js +161 -0
- package/lib/factory/connection.js +62 -0
- package/lib/factory/driver.js +358 -0
- package/lib/factory/feature.js +33 -0
- package/lib/factory/model/_util.js +402 -0
- package/lib/factory/model/build.js +15 -0
- package/lib/factory/model/clear-record.js +17 -0
- package/lib/factory/model/count-record.js +17 -0
- package/lib/factory/model/create-aggregate.js +17 -0
- package/lib/factory/model/create-attachment.js +29 -0
- package/lib/factory/model/create-histogram.js +17 -0
- package/lib/factory/model/create-record.js +35 -0
- package/lib/factory/model/drop.js +15 -0
- package/lib/factory/model/exists.js +21 -0
- package/lib/factory/model/find-all-record.js +71 -0
- package/lib/factory/model/find-attachment.js +29 -0
- package/lib/factory/model/find-one-record.js +19 -0
- package/lib/factory/model/find-record.js +103 -0
- package/lib/factory/model/get-attachment.js +15 -0
- package/lib/factory/model/get-record.js +79 -0
- package/lib/factory/model/list-attachment.js +37 -0
- package/lib/{add-fixtures.js → factory/model/load-fixtures.js} +69 -67
- package/lib/factory/model/remove-attachment.js +15 -0
- package/lib/factory/model/remove-record.js +59 -0
- package/lib/factory/model/sanitize-body.js +62 -0
- package/lib/factory/model/sanitize-id.js +7 -0
- package/lib/factory/model/sanitize-record.js +26 -0
- package/lib/factory/model/update-attachment.js +9 -0
- package/lib/factory/model/update-record.js +81 -0
- package/lib/factory/model/upsert-record.js +95 -0
- package/lib/factory/model/validate.js +232 -0
- package/lib/factory/model.js +150 -0
- package/lib/index.js +3 -0
- package/package.json +45 -36
- package/wiki/APPLETS.md +57 -0
- package/wiki/CHANGES.md +46 -0
- package/wiki/CONFIG.md +25 -0
- package/wiki/CONTRIBUTING.md +5 -0
- package/wiki/DEV-GUIDE.md +1 -0
- package/wiki/ECOSYSTEM.md +20 -0
- package/wiki/GETTING-STARTED.md +166 -0
- package/{docs/query-language.md → wiki/QUERY-LANGUAGE.md} +0 -0
- package/wiki/USER-GUIDE.md +1 -0
- package/extend/bajoCli/applet/model-clear.js +0 -11
- package/extend/bajoCli/applet/model-rebuild.js +0 -101
- package/extend/bajoCli/applet/record-create.js +0 -41
- package/extend/bajoCli/applet/record-find.js +0 -27
- package/extend/bajoCli/applet/record-get.js +0 -24
- package/extend/bajoCli/applet/record-remove.js +0 -24
- package/extend/bajoCli/applet/record-update.js +0 -47
- package/extend/bajoCli/applet/schema.js +0 -22
- package/extend/bajoCli/applet/stat-count.js +0 -24
- package/lib/build-bulk-action.js +0 -12
- package/lib/check-unique.js +0 -39
- package/lib/collect-feature.js +0 -25
- package/lib/collect-schemas.js +0 -83
- package/lib/exec-feature-hook.js +0 -13
- package/lib/exec-validation.js +0 -21
- package/lib/generic-prop-sanitizer.js +0 -31
- package/lib/handle-attachment-upload.js +0 -16
- package/lib/mem-db/conn-sanitizer.js +0 -8
- package/lib/mem-db/instantiate.js +0 -41
- package/lib/mem-db/method/model/clear.js +0 -6
- package/lib/mem-db/method/model/create.js +0 -5
- package/lib/mem-db/method/model/drop.js +0 -5
- package/lib/mem-db/method/model/exists.js +0 -5
- package/lib/mem-db/method/record/create.js +0 -12
- package/lib/mem-db/method/record/find.js +0 -20
- package/lib/mem-db/method/record/get.js +0 -9
- package/lib/mem-db/method/record/remove.js +0 -13
- package/lib/mem-db/method/record/update.js +0 -15
- package/lib/mem-db/method/stat/count.js +0 -11
- package/lib/mem-db/start.js +0 -25
- package/lib/merge-attachment-info.js +0 -16
- package/lib/multi-rel-rows.js +0 -42
- package/lib/resolve-method.js +0 -16
- package/lib/sanitize-schema.js +0 -197
- package/lib/single-rel-rows.js +0 -38
- package/method/attachment/copy-uploaded.js +0 -34
- package/method/attachment/create.js +0 -29
- package/method/attachment/find.js +0 -27
- package/method/attachment/get-path.js +0 -12
- package/method/attachment/get.js +0 -12
- package/method/attachment/pre-check.js +0 -9
- package/method/attachment/remove.js +0 -11
- package/method/attachment/update.js +0 -7
- package/method/bulk/create.js +0 -46
- package/method/model/clear.js +0 -22
- package/method/model/create.js +0 -19
- package/method/model/drop.js +0 -19
- package/method/model/exists.js +0 -24
- package/method/record/clear.js +0 -24
- package/method/record/count.js +0 -44
- package/method/record/create.js +0 -71
- package/method/record/find-all.js +0 -25
- package/method/record/find-one.js +0 -56
- package/method/record/find.js +0 -52
- package/method/record/get.js +0 -47
- package/method/record/remove.js +0 -41
- package/method/record/update.js +0 -63
- package/method/record/upsert.js +0 -35
- package/method/sanitize/body.js +0 -70
- package/method/sanitize/date.js +0 -14
- package/method/sanitize/id.js +0 -7
- package/method/stat/aggregate.js +0 -23
- package/method/stat/histogram.js +0 -26
- package/method/validate.js +0 -157
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
async function findAll (name, filter = {}, options = {}) {
|
|
2
|
-
const { maxLimit, hardLimit } = this.config.default.filter
|
|
3
|
-
filter.page = 1
|
|
4
|
-
filter.limit = maxLimit
|
|
5
|
-
options.dataOnly = true
|
|
6
|
-
const match = filter.match
|
|
7
|
-
const all = []
|
|
8
|
-
let count = 0
|
|
9
|
-
for (;;) {
|
|
10
|
-
filter.match = match
|
|
11
|
-
const results = await this.recordFind(name, filter, options)
|
|
12
|
-
if (results.length === 0) break
|
|
13
|
-
if (count + results.length > hardLimit) {
|
|
14
|
-
const sliced = results.slice(0, hardLimit - count)
|
|
15
|
-
all.push(...sliced)
|
|
16
|
-
break
|
|
17
|
-
}
|
|
18
|
-
all.push(...results)
|
|
19
|
-
count = count + results.length
|
|
20
|
-
filter.page++
|
|
21
|
-
}
|
|
22
|
-
return all
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default findAll
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
import singleRelRows from '../../lib/single-rel-rows.js'
|
|
3
|
-
import execFeatureHook from '../../lib/exec-feature-hook.js'
|
|
4
|
-
|
|
5
|
-
async function findOne (name, filter = {}, opts = {}) {
|
|
6
|
-
const { isSet } = this.lib.aneka
|
|
7
|
-
const { runHook } = this.app.bajo
|
|
8
|
-
const { get, set } = this.cache ?? {}
|
|
9
|
-
const { cloneDeep, camelCase, omit, pick } = this.lib._
|
|
10
|
-
delete opts.record
|
|
11
|
-
const options = cloneDeep(omit(opts, ['req', 'reply']))
|
|
12
|
-
options.req = opts.req
|
|
13
|
-
options.reply = opts.reply
|
|
14
|
-
options.dataOnly = options.dataOnly ?? true
|
|
15
|
-
let { fields, dataOnly, noHook, noCache, noFeatureHook, hidden, forceNoHidden } = options
|
|
16
|
-
options.count = false
|
|
17
|
-
options.dataOnly = false
|
|
18
|
-
await this.modelExists(name, true)
|
|
19
|
-
filter.limit = 1
|
|
20
|
-
filter.page = 1
|
|
21
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-find', options)
|
|
22
|
-
if (!schema.cacheable) noCache = true
|
|
23
|
-
filter.query = this.buildQuery({ filter, schema, options }) ?? {}
|
|
24
|
-
if (options.queryHandler) filter.query = await options.queryHandler.call(opts.req ? this.app[opts.req.ns] : this, filter.query, opts.req)
|
|
25
|
-
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
26
|
-
if (!noHook) {
|
|
27
|
-
await runHook(`${this.name}:beforeRecordFindOne`, name, filter, options)
|
|
28
|
-
await runHook(`${this.name}.${camelCase(name)}:beforeRecordFindOne`, filter, options)
|
|
29
|
-
}
|
|
30
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeFindOne', { schema, filter, options })
|
|
31
|
-
if (get && !noCache && !options.record) {
|
|
32
|
-
const cachedResult = await get({ model: name, filter, options })
|
|
33
|
-
if (cachedResult) {
|
|
34
|
-
cachedResult.cached = true
|
|
35
|
-
return dataOnly ? cachedResult.data : cachedResult
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
filter.limit = 1
|
|
39
|
-
filter.page = 1
|
|
40
|
-
let record = options.record ?? (await handler.call(this.app[driver.ns], { schema, filter, options }))
|
|
41
|
-
delete options.record
|
|
42
|
-
record.data = record.data[0]
|
|
43
|
-
|
|
44
|
-
if (isSet(options.rels)) await singleRelRows.call(this, { schema, record: record.data, options })
|
|
45
|
-
record.data = await this.pickRecord({ record: record.data, fields, schema, hidden, forceNoHidden })
|
|
46
|
-
record = pick(record, ['data'])
|
|
47
|
-
if (!noHook) {
|
|
48
|
-
await runHook(`${this.name}.${camelCase(name)}:afterRecordFindOne`, filter, options, record)
|
|
49
|
-
await runHook(`${this.name}:afterRecordFindOne`, name, filter, options, record)
|
|
50
|
-
}
|
|
51
|
-
if (set && !noCache) await set({ model: name, filter, options, record })
|
|
52
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterFindOne', { schema, filter, options, record })
|
|
53
|
-
return dataOnly ? record.data : record
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default findOne
|
package/method/record/find.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
import multiRelRows from '../../lib/multi-rel-rows.js'
|
|
3
|
-
import execFeatureHook from '../../lib/exec-feature-hook.js'
|
|
4
|
-
|
|
5
|
-
async function find (name, filter = {}, opts = {}) {
|
|
6
|
-
const { isSet } = this.lib.aneka
|
|
7
|
-
const { runHook } = this.app.bajo
|
|
8
|
-
const { get, set } = this.cache ?? {}
|
|
9
|
-
const { cloneDeep, camelCase, omit } = this.lib._
|
|
10
|
-
delete opts.records
|
|
11
|
-
const options = cloneDeep(omit(opts, ['req', 'reply']))
|
|
12
|
-
options.req = opts.req
|
|
13
|
-
options.reply = opts.reply
|
|
14
|
-
options.dataOnly = options.dataOnly ?? true
|
|
15
|
-
let { fields, dataOnly, noHook, noCache, noFeatureHook, hidden, forceNoHidden } = options
|
|
16
|
-
options.count = options.count ?? false
|
|
17
|
-
options.dataOnly = false
|
|
18
|
-
await this.modelExists(name, true)
|
|
19
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-find', options)
|
|
20
|
-
if (!schema.cacheable) noCache = true
|
|
21
|
-
filter.query = this.buildQuery({ filter, schema, options }) ?? {}
|
|
22
|
-
if (options.queryHandler) filter.query = await options.queryHandler.call(opts.req ? this.app[opts.req.ns] : this, filter.query, opts.req)
|
|
23
|
-
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
24
|
-
if (!noHook) {
|
|
25
|
-
await runHook(`${this.name}:beforeRecordFind`, name, filter, options)
|
|
26
|
-
await runHook(`${this.name}.${camelCase(name)}:beforeRecordFind`, filter, options)
|
|
27
|
-
}
|
|
28
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeFind', { schema, filter, options })
|
|
29
|
-
if (get && !noCache && !options.records) {
|
|
30
|
-
const cachedResult = await get({ model: name, filter, options })
|
|
31
|
-
if (cachedResult) {
|
|
32
|
-
cachedResult.cached = true
|
|
33
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterFind', { schema, filter, options, records: cachedResult })
|
|
34
|
-
return dataOnly ? cachedResult.data : cachedResult
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
const records = options.records ?? (await handler.call(this.app[driver.ns], { schema, filter, options }))
|
|
38
|
-
delete options.records
|
|
39
|
-
if (isSet(options.rels)) await multiRelRows.call(this, { schema, records: records.data, options })
|
|
40
|
-
for (const idx in records.data) {
|
|
41
|
-
records.data[idx] = await this.pickRecord({ record: records.data[idx], fields, schema, hidden, forceNoHidden })
|
|
42
|
-
}
|
|
43
|
-
if (!noHook) {
|
|
44
|
-
await runHook(`${this.name}.${camelCase(name)}:afterRecordFind`, filter, options, records)
|
|
45
|
-
await runHook(`${this.name}:afterRecordFind`, name, filter, options, records)
|
|
46
|
-
}
|
|
47
|
-
if (set && !noCache) await set({ model: name, filter, options, records })
|
|
48
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterFind', { schema, filter, options, records })
|
|
49
|
-
return dataOnly ? records.data : records
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export default find
|
package/method/record/get.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
import singleRelRows from '../../lib/single-rel-rows.js'
|
|
3
|
-
import execFeatureHook from '../../lib/exec-feature-hook.js'
|
|
4
|
-
|
|
5
|
-
async function get (name, id, opts = {}) {
|
|
6
|
-
const { isSet } = this.lib.aneka
|
|
7
|
-
const { runHook } = this.app.bajo
|
|
8
|
-
const { get, set } = this.cache ?? {}
|
|
9
|
-
const { cloneDeep, camelCase, omit } = this.lib._
|
|
10
|
-
delete opts.record
|
|
11
|
-
const options = cloneDeep(omit(opts, ['req', 'reply']))
|
|
12
|
-
options.req = opts.req
|
|
13
|
-
options.reply = opts.reply
|
|
14
|
-
options.dataOnly = options.dataOnly ?? true
|
|
15
|
-
let { fields, dataOnly, noHook, noCache, noFeatureHook, hidden = [], forceNoHidden } = options
|
|
16
|
-
await this.modelExists(name, true)
|
|
17
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-get', options)
|
|
18
|
-
if (!schema.cacheable) noCache = true
|
|
19
|
-
id = this.sanitizeId(id, schema)
|
|
20
|
-
options.dataOnly = false
|
|
21
|
-
if (!noHook) {
|
|
22
|
-
await runHook(`${this.name}:beforeRecordGet`, name, id, options)
|
|
23
|
-
await runHook(`${this.name}.${camelCase(name)}:beforeRecordGet`, id, options)
|
|
24
|
-
}
|
|
25
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeGet', { schema, id, options })
|
|
26
|
-
if (get && !noCache && !options.record) {
|
|
27
|
-
const cachedResult = await get({ model: name, id, options })
|
|
28
|
-
if (cachedResult) {
|
|
29
|
-
cachedResult.cached = true
|
|
30
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterGet', { schema, id, options, record: cachedResult })
|
|
31
|
-
return dataOnly ? cachedResult.data : cachedResult
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const record = options.record ?? (await handler.call(this.app[driver.ns], { schema, id, options }))
|
|
35
|
-
delete options.record
|
|
36
|
-
if (isSet(options.rels)) await singleRelRows.call(this, { schema, record: record.data, options })
|
|
37
|
-
record.data = await this.pickRecord({ record: record.data, fields, schema, hidden, forceNoHidden })
|
|
38
|
-
if (!noHook) {
|
|
39
|
-
await runHook(`${this.name}.${camelCase(name)}:afterRecordGet`, id, options, record)
|
|
40
|
-
await runHook(`${this.name}:afterRecordGet`, name, id, options, record)
|
|
41
|
-
}
|
|
42
|
-
if (set && !noCache) await set({ model: name, id, options, record })
|
|
43
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterGet', { schema, id, options, record })
|
|
44
|
-
return dataOnly ? record.data : record
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export default get
|
package/method/record/remove.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
import handleAttachmentUpload from '../../lib/handle-attachment-upload.js'
|
|
3
|
-
import execFeatureHook from '../../lib/exec-feature-hook.js'
|
|
4
|
-
|
|
5
|
-
async function remove (name, id, opts = {}) {
|
|
6
|
-
const { runHook } = this.app.bajo
|
|
7
|
-
const { clearModel } = this.cache ?? {}
|
|
8
|
-
const { cloneDeep, camelCase, omit } = this.lib._
|
|
9
|
-
delete opts.record
|
|
10
|
-
const options = cloneDeep(omit(opts, ['req', 'reply']))
|
|
11
|
-
options.req = opts.req
|
|
12
|
-
options.reply = opts.reply
|
|
13
|
-
options.dataOnly = options.dataOnly ?? true
|
|
14
|
-
const { fields, dataOnly, noHook, noResult, noFeatureHook, hidden, forceNoHidden } = options
|
|
15
|
-
options.dataOnly = false
|
|
16
|
-
await this.modelExists(name, true)
|
|
17
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-remove', options)
|
|
18
|
-
id = this.sanitizeId(id, schema)
|
|
19
|
-
if (!noHook) {
|
|
20
|
-
await runHook(`${this.name}:beforeRecordRemove`, name, id, options)
|
|
21
|
-
await runHook(`${this.name}.${camelCase(name)}:beforeRecordRemove`, id, options)
|
|
22
|
-
}
|
|
23
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeRemove', { schema, id, options })
|
|
24
|
-
const record = options.record ?? (await handler.call(this.app[driver.ns], { schema, id, options }))
|
|
25
|
-
delete options.record
|
|
26
|
-
if (options.req) {
|
|
27
|
-
if (options.req.file) await handleAttachmentUpload.call(this, { name: schema.name, id, options, action: 'remove' })
|
|
28
|
-
if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('recordRemoved'))
|
|
29
|
-
}
|
|
30
|
-
if (clearModel) await clearModel({ model: name, id, options, record })
|
|
31
|
-
if (noResult) return
|
|
32
|
-
record.oldData = options.record ? options.record.oldData : (await this.pickRecord({ record: record.oldData, fields, schema, hidden, forceNoHidden }))
|
|
33
|
-
if (!noHook) {
|
|
34
|
-
await runHook(`${this.name}.${camelCase(name)}:afterRecordRemove`, id, options, record)
|
|
35
|
-
await runHook(`${this.name}:afterRecordRemove`, name, id, options, record)
|
|
36
|
-
}
|
|
37
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterRemove', { schema, id, options, record })
|
|
38
|
-
return dataOnly ? record.oldData : record
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export default remove
|
package/method/record/update.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
import checkUnique from '../../lib/check-unique.js'
|
|
3
|
-
import handleAttachmentUpload from '../../lib/handle-attachment-upload.js'
|
|
4
|
-
import execValidation from '../../lib/exec-validation.js'
|
|
5
|
-
import execFeatureHook from '../../lib/exec-feature-hook.js'
|
|
6
|
-
import singleRelRows from '../../lib/single-rel-rows.js'
|
|
7
|
-
|
|
8
|
-
async function update (name, id, input, opts = {}) {
|
|
9
|
-
const { isSet } = this.lib.aneka
|
|
10
|
-
const { runHook } = this.app.bajo
|
|
11
|
-
const { clearModel } = this.cache ?? {}
|
|
12
|
-
const { forOwn, find, cloneDeep, camelCase, omit, get } = this.lib._
|
|
13
|
-
delete opts.record
|
|
14
|
-
const options = cloneDeep(omit(opts, ['req', 'reply']))
|
|
15
|
-
options.req = opts.req
|
|
16
|
-
options.reply = opts.reply
|
|
17
|
-
options.dataOnly = options.dataOnly ?? true
|
|
18
|
-
input = cloneDeep(input)
|
|
19
|
-
const { fields, dataOnly, noHook, noValidation, noCheckUnique, noFeatureHook, noResult, noSanitize, partial = true, hidden, forceNoHidden } = options
|
|
20
|
-
options.dataOnly = true
|
|
21
|
-
options.truncateString = options.truncateString ?? true
|
|
22
|
-
await this.modelExists(name, true)
|
|
23
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'record-update', options)
|
|
24
|
-
id = this.sanitizeId(id, schema)
|
|
25
|
-
const extFields = get(options, 'validation.extFields', [])
|
|
26
|
-
let body = noSanitize ? input : await this.sanitizeBody({ body: input, schema, partial, strict: true, extFields })
|
|
27
|
-
delete body.id
|
|
28
|
-
if (!noHook) {
|
|
29
|
-
await runHook(`${this.name}:beforeRecordUpdate`, name, id, body, options)
|
|
30
|
-
await runHook(`${this.name}.${camelCase(name)}:beforeRecordUpdate`, id, body, options)
|
|
31
|
-
}
|
|
32
|
-
if (!noValidation) body = await execValidation.call(this, { name, body, options, partial })
|
|
33
|
-
if (!noCheckUnique) await checkUnique.call(this, { schema, body, id })
|
|
34
|
-
const nbody = {}
|
|
35
|
-
forOwn(body, (v, k) => {
|
|
36
|
-
if (v === undefined) return undefined
|
|
37
|
-
const prop = find(schema.properties, { name: k })
|
|
38
|
-
if (!prop) return undefined
|
|
39
|
-
if (options.truncateString && isSet(v) && ['string', 'text'].includes(prop.type)) v = v.slice(0, prop.maxLength)
|
|
40
|
-
nbody[k] = v
|
|
41
|
-
})
|
|
42
|
-
delete nbody.id
|
|
43
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'beforeUpdate', { schema, body: nbody, options })
|
|
44
|
-
const record = options.record ?? (await handler.call(this.app[driver.ns], { schema, id, body: nbody, options }))
|
|
45
|
-
delete options.record
|
|
46
|
-
if (isSet(options.rels)) await singleRelRows.call(this, { schema, record: record.data, options })
|
|
47
|
-
if (options.req) {
|
|
48
|
-
if (options.req.file) await handleAttachmentUpload.call(this, { name: schema.name, id, body, options, action: 'update' })
|
|
49
|
-
if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('recordUpdated'))
|
|
50
|
-
}
|
|
51
|
-
if (clearModel) await clearModel({ model: name, id, body: nbody, options, record })
|
|
52
|
-
if (noResult) return
|
|
53
|
-
record.oldData = await this.pickRecord({ record: record.oldData, fields, schema, hidden, forceNoHidden })
|
|
54
|
-
record.data = await this.pickRecord({ record: record.data, fields, schema, hidden, forceNoHidden })
|
|
55
|
-
if (!noHook) {
|
|
56
|
-
await runHook(`${this.name}.${camelCase(name)}:afterRecordUpdate`, id, nbody, options, record)
|
|
57
|
-
await runHook(`${this.name}:afterRecordUpdate`, name, id, nbody, options, record)
|
|
58
|
-
}
|
|
59
|
-
if (!noFeatureHook) await execFeatureHook.call(this, 'afterUpdate', { schema, body: nbody, record })
|
|
60
|
-
return dataOnly ? record.data : record
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export default update
|
package/method/record/upsert.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
async function upsert (name, input, opts = {}) {
|
|
2
|
-
const { generateId } = this.app.bajo
|
|
3
|
-
const { find } = this.lib._
|
|
4
|
-
const { cloneDeep, omit, merge } = this.lib._
|
|
5
|
-
const { query, omitOnUpdate = [], omitOnCreate = [] } = opts
|
|
6
|
-
const options = cloneDeep(omit(opts, ['req', 'reply', 'query', 'omitOnUpdate', 'omitOnCreate']))
|
|
7
|
-
options.req = opts.req
|
|
8
|
-
options.reply = opts.reply
|
|
9
|
-
options.dataOnly = options.dataOnly ?? true
|
|
10
|
-
await this.modelExists(name, true)
|
|
11
|
-
const { schema } = this.getInfo(name)
|
|
12
|
-
const idField = find(schema.properties, { name: 'id' })
|
|
13
|
-
let id
|
|
14
|
-
if (idField.type === 'string') id = input.id ?? generateId()
|
|
15
|
-
else if (idField.type === 'integer') id = input.id ?? generateId('int')
|
|
16
|
-
id = this.sanitizeId(id, schema)
|
|
17
|
-
let old
|
|
18
|
-
let body
|
|
19
|
-
const o = { dataOnly: true, noHook: true, noCache: true, hidden: options.hidden, forceNoHidden: options.forceNoHidden }
|
|
20
|
-
if (query) {
|
|
21
|
-
old = await this.recordFindOne(name, { query }, o)
|
|
22
|
-
} else {
|
|
23
|
-
o.thrownNotFound = false
|
|
24
|
-
old = await this.recordGet(name, id, o)
|
|
25
|
-
}
|
|
26
|
-
if (old) {
|
|
27
|
-
body = merge(omit(old, ['id', 'createdAt', 'updatedAt', 'removedAt']), omit(input, omitOnUpdate))
|
|
28
|
-
return await this.recordUpdate(name, old.id, body, options)
|
|
29
|
-
}
|
|
30
|
-
if (!query) input.id = id
|
|
31
|
-
body = omit(input, omitOnCreate)
|
|
32
|
-
return await this.recordCreate(name, body, options)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default upsert
|
package/method/sanitize/body.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
async function sanitizeBody ({ body = {}, schema = {}, partial, strict, extFields = [] }) {
|
|
2
|
-
const { isSet } = this.lib.aneka
|
|
3
|
-
const { dayjs } = this.lib
|
|
4
|
-
const { callHandler } = this.app.bajo
|
|
5
|
-
const { has, isString, isNumber, concat, isNaN } = this.lib._
|
|
6
|
-
const result = {}
|
|
7
|
-
for (const p of concat(schema.properties, extFields)) {
|
|
8
|
-
if (partial && !has(body, p.name)) continue
|
|
9
|
-
if (['object', 'array'].includes(p.type)) {
|
|
10
|
-
if (isString(body[p.name])) {
|
|
11
|
-
try {
|
|
12
|
-
result[p.name] = JSON.parse(body[p.name])
|
|
13
|
-
} catch (err) {
|
|
14
|
-
result[p.name] = null
|
|
15
|
-
}
|
|
16
|
-
} else {
|
|
17
|
-
try {
|
|
18
|
-
result[p.name] = JSON.parse(JSON.stringify(body[p.name]))
|
|
19
|
-
} catch (err) {}
|
|
20
|
-
}
|
|
21
|
-
} else result[p.name] = body[p.name]
|
|
22
|
-
if (isSet(body[p.name])) {
|
|
23
|
-
if (p.type === 'boolean') result[p.name] = result[p.name] === null ? null : (['true', true].includes(result[p.name]))
|
|
24
|
-
if (['float', 'double'].includes(p.type)) {
|
|
25
|
-
if (isNumber(body[p.name])) result[p.name] = body[p.name]
|
|
26
|
-
else if (strict) {
|
|
27
|
-
result[p.name] = Number(body[p.name])
|
|
28
|
-
} else {
|
|
29
|
-
result[p.name] = parseFloat(body[p.name]) || null
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (['integer', 'smallint'].includes(p.type)) {
|
|
33
|
-
if (isNumber(body[p.name])) result[p.name] = body[p.name]
|
|
34
|
-
else if (strict) {
|
|
35
|
-
result[p.name] = Number(body[p.name])
|
|
36
|
-
} else {
|
|
37
|
-
result[p.name] = parseInt(body[p.name]) || null
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (p.type === 'timestamp') {
|
|
41
|
-
if (!isNumber(body[p.name])) result[p.name] = -1
|
|
42
|
-
else {
|
|
43
|
-
const dt = dayjs.unix(body[p.name])
|
|
44
|
-
result[p.name] = dt.isValid() ? dt.unix() : -1
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
for (const t of ['datetime', 'date|YYYY-MM-DD', 'time|HH:mm:ss']) {
|
|
48
|
-
const [type, input] = t.split('|')
|
|
49
|
-
if (p.type === type) result[p.name] = this.sanitizeDate(body[p.name], { input })
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (['string', 'text'].includes(p.type)) result[p.name] = body[p.name] + ''
|
|
53
|
-
} else {
|
|
54
|
-
if (isSet(p.default)) {
|
|
55
|
-
result[p.name] = p.default
|
|
56
|
-
if (isString(p.default) && p.default.startsWith('handler:')) {
|
|
57
|
-
const [, ...args] = p.default.split(':')
|
|
58
|
-
if (args.length > 0) result[p.name] = await callHandler(args.join(':'))
|
|
59
|
-
} else {
|
|
60
|
-
if (['float', 'double'].includes(p.type)) result[p.name] = parseFloat(result[p.name])
|
|
61
|
-
if (['integer', 'smallint'].includes(p.type)) result[p.name] = parseInt(result[p.name])
|
|
62
|
-
if (isNaN(result[p.name])) result[p.name] = null
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return result
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export default sanitizeBody
|
package/method/sanitize/date.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
function sanitizeDate (value, { input, output, silent = true } = {}) {
|
|
2
|
-
const { dayjs } = this.lib
|
|
3
|
-
if (value === 0) return null
|
|
4
|
-
if (!output) output = input
|
|
5
|
-
const dt = dayjs(value, input)
|
|
6
|
-
if (!dt.isValid()) {
|
|
7
|
-
if (silent) return -1
|
|
8
|
-
throw this.error('invalidDate')
|
|
9
|
-
}
|
|
10
|
-
if (output === 'native' || !output) return dt.toDate()
|
|
11
|
-
return dt.format(output)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default sanitizeDate
|
package/method/sanitize/id.js
DELETED
package/method/stat/aggregate.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
|
|
3
|
-
async function aggregate (name, filter = {}, options = {}) {
|
|
4
|
-
const { runHook } = this.app.bajo
|
|
5
|
-
const { dataOnly = true, noHook, aggregate } = options
|
|
6
|
-
options.dataOnly = false
|
|
7
|
-
await this.modelExists(name, true)
|
|
8
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-aggregate', options)
|
|
9
|
-
if (!noHook) {
|
|
10
|
-
await runHook(`${this.name}:beforeStatAggregate`, name, aggregate, filter, options)
|
|
11
|
-
await runHook(`${this.name}.${name}:beforeStatAggregate`, aggregate, filter, options)
|
|
12
|
-
}
|
|
13
|
-
filter.query = this.buildQuery({ filter, schema, options }) ?? {}
|
|
14
|
-
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
15
|
-
const rec = await handler.call(this.app[driver.ns], { schema, filter, options })
|
|
16
|
-
if (!noHook) {
|
|
17
|
-
await runHook(`${this.name}.${name}:afterStatAggregate`, aggregate, filter, options, rec)
|
|
18
|
-
await runHook(`${this.name}:afterStatAggregate`, name, aggregate, filter, options, rec)
|
|
19
|
-
}
|
|
20
|
-
return dataOnly ? rec.data : rec
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default aggregate
|
package/method/stat/histogram.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import resolveMethod from '../../lib/resolve-method.js'
|
|
2
|
-
|
|
3
|
-
const types = ['daily', 'monthly', 'yearly']
|
|
4
|
-
|
|
5
|
-
async function histogram (name, filter = {}, options = {}) {
|
|
6
|
-
const { runHook, join } = this.app.bajo
|
|
7
|
-
const { dataOnly = true, noHook, type } = options
|
|
8
|
-
options.dataOnly = false
|
|
9
|
-
if (!types.includes(type)) throw this.error('histogramTypeMusBe%s', join(types))
|
|
10
|
-
await this.modelExists(name, true)
|
|
11
|
-
const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-histogram', options)
|
|
12
|
-
filter.query = this.buildQuery({ filter, schema, options }) ?? {}
|
|
13
|
-
filter.match = this.buildMatch({ input: filter.match, schema, options }) ?? {}
|
|
14
|
-
if (!noHook) {
|
|
15
|
-
await runHook(`${this.name}:beforeStatHistogram`, name, type, filter, options)
|
|
16
|
-
await runHook(`${this.name}.${name}:beforeStatHistogram`, type, filter, options)
|
|
17
|
-
}
|
|
18
|
-
const rec = await handler.call(this.app[driver.ns], { schema, type, filter, options })
|
|
19
|
-
if (!noHook) {
|
|
20
|
-
await runHook(`${this.name}.${name}:afterStatHistogram`, type, filter, options, rec)
|
|
21
|
-
await runHook(`${this.name}:afterStatHistogram`, name, type, filter, options, rec)
|
|
22
|
-
}
|
|
23
|
-
return dataOnly ? rec.data : rec
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default histogram
|
package/method/validate.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import joi from 'joi'
|
|
2
|
-
|
|
3
|
-
const excludedTypes = ['object', 'array']
|
|
4
|
-
const excludedNames = []
|
|
5
|
-
|
|
6
|
-
const validator = {
|
|
7
|
-
string: ['alphanum', 'base64', 'case', 'creditCard', 'dataUri', 'domain', 'email', 'guid',
|
|
8
|
-
'uuid', 'hex', 'hostname', 'insensitive', 'ip', 'isoDate', 'isoDuration', 'length', 'lowercase',
|
|
9
|
-
'max', 'min', 'normalize', 'pattern', 'regex', 'replace', 'token', 'trim', 'truncate',
|
|
10
|
-
'uppercase', 'uri'],
|
|
11
|
-
number: ['great', 'less', 'max', 'min', 'multiple', 'negative', 'port', 'positive',
|
|
12
|
-
'sign', 'unsafe'],
|
|
13
|
-
boolean: ['falsy', 'sensitive', 'truthy'],
|
|
14
|
-
date: ['greater', 'iso', 'less', 'max', 'min'],
|
|
15
|
-
timestamp: ['timestamp']
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function buildFromDbSchema (schema, { fields = [], rule = {}, extFields = [] } = {}) {
|
|
19
|
-
// if (schema.validation) return schema.validation
|
|
20
|
-
const {
|
|
21
|
-
isPlainObject, get, each, isEmpty, isString, forOwn, keys,
|
|
22
|
-
find, isArray, has, cloneDeep, concat, without
|
|
23
|
-
} = this.lib._
|
|
24
|
-
const obj = {}
|
|
25
|
-
const me = this
|
|
26
|
-
const refs = []
|
|
27
|
-
|
|
28
|
-
function getRuleKv (kvRule) {
|
|
29
|
-
let key
|
|
30
|
-
let value
|
|
31
|
-
let columns
|
|
32
|
-
if (isPlainObject(kvRule)) {
|
|
33
|
-
key = kvRule.rule
|
|
34
|
-
value = kvRule.params
|
|
35
|
-
columns = kvRule.fields
|
|
36
|
-
} else if (isString(kvRule)) {
|
|
37
|
-
[key, value, columns] = kvRule.split(':')
|
|
38
|
-
}
|
|
39
|
-
return { key, value, columns }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function applyFieldRules (prop, obj) {
|
|
43
|
-
const minMax = { min: false, max: false }
|
|
44
|
-
const rules = get(rule, prop.name, prop.rules ?? [])
|
|
45
|
-
if (!isArray(rules)) return rules
|
|
46
|
-
each(rules, r => {
|
|
47
|
-
const types = validator[me.propType[prop.type].validator]
|
|
48
|
-
const { key, value } = getRuleKv(r)
|
|
49
|
-
if (keys(minMax).includes(key)) minMax[key] = true
|
|
50
|
-
if (key === 'ref') {
|
|
51
|
-
refs.push(prop.name)
|
|
52
|
-
obj = joi.ref(value)
|
|
53
|
-
return undefined
|
|
54
|
-
}
|
|
55
|
-
if (!key || !types.includes(key)) return undefined
|
|
56
|
-
obj = obj[key](value)
|
|
57
|
-
})
|
|
58
|
-
if (refs.includes(prop.name)) return obj
|
|
59
|
-
if (['string', 'text'].includes(prop.type)) {
|
|
60
|
-
forOwn(minMax, (v, k) => {
|
|
61
|
-
if (v) return undefined
|
|
62
|
-
if (has(prop, `${k}Length`)) obj = obj[k](prop[`${k}Length`])
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
if (isArray(prop.values)) obj = obj.valid(...prop.values)
|
|
66
|
-
if (!['id'].includes(prop.name) && prop.required) obj = obj.required()
|
|
67
|
-
return obj
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const props = concat(cloneDeep(schema.properties), extFields)
|
|
71
|
-
|
|
72
|
-
for (const p of props) {
|
|
73
|
-
if (excludedTypes.includes(p.type) || excludedNames.includes(p.name)) continue
|
|
74
|
-
if (fields.length > 0 && !fields.includes(p.name)) continue
|
|
75
|
-
let item
|
|
76
|
-
switch (p.type) {
|
|
77
|
-
case 'text':
|
|
78
|
-
case 'string': {
|
|
79
|
-
item = applyFieldRules(p, joi.string())
|
|
80
|
-
break
|
|
81
|
-
}
|
|
82
|
-
case 'smallint':
|
|
83
|
-
case 'integer':
|
|
84
|
-
item = applyFieldRules(p, joi.number().integer())
|
|
85
|
-
break
|
|
86
|
-
case 'float':
|
|
87
|
-
case 'double':
|
|
88
|
-
if (p.precision) item = applyFieldRules(p, joi.number().precision(p.precision))
|
|
89
|
-
else item = applyFieldRules(p, joi.number())
|
|
90
|
-
break
|
|
91
|
-
case 'time':
|
|
92
|
-
case 'date':
|
|
93
|
-
case 'datetime':
|
|
94
|
-
item = applyFieldRules(p, joi.date())
|
|
95
|
-
break
|
|
96
|
-
case 'timestamp':
|
|
97
|
-
item = applyFieldRules(p, joi.number().integer())
|
|
98
|
-
break
|
|
99
|
-
case 'boolean':
|
|
100
|
-
item = applyFieldRules(p, joi.boolean())
|
|
101
|
-
break
|
|
102
|
-
}
|
|
103
|
-
if (item) {
|
|
104
|
-
if (item.$_root) obj[p.name] = item.allow(null)
|
|
105
|
-
else obj[p.name] = item
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (isEmpty(obj)) return false
|
|
109
|
-
each(get(schema, 'globalRules', []), r => {
|
|
110
|
-
each(without(keys(obj), ...refs), k => {
|
|
111
|
-
const prop = find(props, { name: k })
|
|
112
|
-
if (!prop) return undefined
|
|
113
|
-
const types = validator[me.propType[prop.type].validator]
|
|
114
|
-
const { key, value, columns = [] } = getRuleKv(r)
|
|
115
|
-
if (!types.includes(key)) return undefined
|
|
116
|
-
if (columns.length === 0 || columns.includes(k)) obj[k] = obj[k][key](value)
|
|
117
|
-
})
|
|
118
|
-
})
|
|
119
|
-
const result = joi.object(obj)
|
|
120
|
-
if (fields.length === 0) return result
|
|
121
|
-
each(['with', 'xor', 'without'], k => {
|
|
122
|
-
const item = get(schema, `extRule.${k}`)
|
|
123
|
-
if (item) result[k](...item)
|
|
124
|
-
})
|
|
125
|
-
return result
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function validate (value, joiSchema, { ns, fields, extFields, params } = {}) {
|
|
129
|
-
const { defaultsDeep, isSet } = this.lib.aneka
|
|
130
|
-
const { isString, forOwn, find } = this.lib._
|
|
131
|
-
|
|
132
|
-
ns = ns ?? [this.name]
|
|
133
|
-
params = defaultsDeep(params, this.config.validationParams)
|
|
134
|
-
const { rule = {} } = params
|
|
135
|
-
delete params.rule
|
|
136
|
-
if (isString(joiSchema)) {
|
|
137
|
-
const { schema } = this.getInfo(joiSchema)
|
|
138
|
-
forOwn(value, (v, k) => {
|
|
139
|
-
if (!isSet(v)) return undefined
|
|
140
|
-
const p = find(schema.properties, { name: k })
|
|
141
|
-
if (!p) return undefined
|
|
142
|
-
for (const t of ['date|YYYY-MM-DD', 'time|HH:mm:ss']) {
|
|
143
|
-
const [type, input] = t.split('|')
|
|
144
|
-
if (p.type === type) value[k] = this.sanitizeDate(value[k], { input, output: 'native' })
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
joiSchema = buildFromDbSchema.call(this, schema, { fields, rule, extFields })
|
|
148
|
-
}
|
|
149
|
-
if (!joiSchema) return value
|
|
150
|
-
try {
|
|
151
|
-
return await joiSchema.validateAsync(value, params)
|
|
152
|
-
} catch (err) {
|
|
153
|
-
throw this.error('validationError', { details: err.details, values: err.values, ns, statusCode: 422, code: 'DB_VALIDATION' })
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export default validate
|