dobo 2.38.0 → 2.39.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.
- package/.bootorder +0 -0
- package/.github/FUNDING.yml +0 -0
- package/.github/workflows/repo-lockdown.yml +0 -0
- package/.jsdoc.conf.json +0 -0
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/docs/Dobo.html +0 -0
- package/docs/DoboAction.html +0 -0
- package/docs/DoboAdapter.html +0 -0
- package/docs/DoboConnection.html +0 -0
- package/docs/DoboFeature.html +0 -0
- package/docs/DoboModel.html +0 -0
- package/docs/data/search.json +0 -0
- package/docs/extend_bajo_hook-docs.js.html +0 -0
- package/docs/external-Tools.html +0 -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 +0 -0
- package/docs/index.html +0 -0
- package/docs/index.js.html +0 -0
- package/docs/lib_factory_action.js.html +0 -0
- package/docs/lib_factory_adapter.js.html +0 -0
- package/docs/lib_factory_connection.js.html +0 -0
- package/docs/lib_factory_feature.js.html +0 -0
- package/docs/lib_factory_model.js.html +0 -0
- package/docs/lib_factory_model_build.js.html +0 -0
- package/docs/lib_factory_model_clear-record.js.html +0 -0
- package/docs/lib_factory_model_count-record.js.html +0 -0
- package/docs/lib_factory_model_create-record.js.html +0 -0
- package/docs/lib_factory_model_drop.js.html +0 -0
- package/docs/lib_factory_model_exists.js.html +0 -0
- package/docs/lib_factory_model_find-all-record.js.html +0 -0
- package/docs/lib_factory_model_find-one-record.js.html +0 -0
- package/docs/lib_factory_model_find-record.js.html +0 -0
- package/docs/lib_factory_model_get-record.js.html +0 -0
- package/docs/lib_factory_model_helper.js.html +0 -0
- package/docs/lib_factory_model_remove-record.js.html +0 -0
- package/docs/lib_factory_model_sanitize-body.js.html +0 -0
- package/docs/lib_factory_model_sanitize-fixture.js.html +0 -0
- package/docs/lib_factory_model_sanitize-record.js.html +0 -0
- package/docs/lib_factory_model_update-record.js.html +0 -0
- package/docs/lib_factory_model_upsert-record.js.html +0 -0
- package/docs/lib_factory_model_validate.js.html +0 -0
- package/docs/lib_helper.js.html +0 -0
- package/docs/module-Helper.html +0 -0
- package/docs/module-Helper_Model.html +0 -0
- package/docs/module-Hook.html +0 -0
- package/docs/scripts/core.js +0 -0
- package/docs/scripts/core.min.js +0 -0
- package/docs/scripts/resize.js +0 -0
- package/docs/scripts/search.js +0 -0
- package/docs/scripts/search.min.js +5 -5
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -0
- package/docs/scripts/third-party/fuse.js +0 -0
- package/docs/scripts/third-party/hljs-line-num-original.js +0 -0
- package/docs/scripts/third-party/hljs-line-num.js +0 -0
- package/docs/scripts/third-party/hljs-original.js +0 -0
- package/docs/scripts/third-party/hljs.js +0 -0
- package/docs/scripts/third-party/popper.js +0 -0
- package/docs/scripts/third-party/tippy.js +0 -0
- package/docs/scripts/third-party/tocbot.js +0 -0
- package/docs/scripts/third-party/tocbot.min.js +0 -0
- package/docs/static/bitcoin.jpeg +0 -0
- package/docs/static/home.md +0 -0
- package/docs/static/logo-ecosystem.png +0 -0
- package/docs/static/logo.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +0 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -0
- package/docs/styles/clean-jsdoc-theme-light.css +0 -0
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -0
- package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -0
- package/docs/styles/clean-jsdoc-theme.min.css +0 -0
- package/extend/bajo/hook.js +236 -236
- package/extend/bajo/intl/en-US.json +0 -0
- package/extend/bajo/intl/id.json +0 -0
- package/extend/bajoCli/applet/aggregate.js +0 -0
- package/extend/bajoCli/applet/clear-record.js +0 -0
- package/extend/bajoCli/applet/connection.js +0 -0
- package/extend/bajoCli/applet/count-record.js +0 -0
- package/extend/bajoCli/applet/create-record.js +0 -0
- package/extend/bajoCli/applet/find-record.js +0 -0
- package/extend/bajoCli/applet/get-record.js +0 -0
- package/extend/bajoCli/applet/histogram.js +0 -0
- package/extend/bajoCli/applet/lib/post-process.js +0 -0
- package/extend/bajoCli/applet/model.js +0 -0
- package/extend/bajoCli/applet/rebuild-model.js +0 -0
- package/extend/bajoCli/applet/remove-record.js +0 -0
- package/extend/bajoCli/applet/update-record.js +0 -0
- package/extend/bajoCli/applet.js +0 -0
- package/extend/dobo/adapter/memory.js +175 -175
- package/extend/dobo/feature/created-at.js +0 -0
- package/extend/dobo/feature/dt.js +0 -0
- package/extend/dobo/feature/image.js +0 -0
- package/extend/dobo/feature/immutable.js +0 -0
- package/extend/dobo/feature/removed-at.js +0 -0
- package/extend/dobo/feature/unique.js +0 -0
- package/extend/dobo/feature/updated-at.js +0 -0
- package/extend/waibuMpa/route/attachment/@model/@id/@field/@file.js +0 -0
- package/extend/waibuStatic/virtual.json +0 -0
- package/index.js +0 -0
- package/lib/factory/action.js +287 -287
- package/lib/factory/adapter.js +1055 -1055
- package/lib/factory/connection.js +109 -109
- package/lib/factory/feature.js +52 -52
- package/lib/factory/model/aggregate.js +23 -23
- package/lib/factory/model/build.js +25 -25
- package/lib/factory/model/bulk-create-record.js +36 -36
- package/lib/factory/model/clear-record.js +30 -30
- package/lib/factory/model/count-record.js +42 -42
- package/lib/factory/model/create-attachment.js +36 -36
- package/lib/factory/model/create-record.js +49 -49
- package/lib/factory/model/drop.js +26 -26
- package/lib/factory/model/exists.js +26 -26
- package/lib/factory/model/find-all-record.js +112 -112
- package/lib/factory/model/find-attachment.js +28 -28
- package/lib/factory/model/find-one-record.js +38 -38
- package/lib/factory/model/find-record.js +82 -82
- package/lib/factory/model/get-attachment.js +15 -15
- package/lib/factory/model/get-record.js +52 -52
- package/lib/factory/model/helper.js +575 -576
- package/lib/factory/model/histogram.js +23 -23
- package/lib/factory/model/list-attachment.js +40 -40
- package/lib/factory/model/load-fixtures.js +63 -63
- package/lib/factory/model/remove-attachment.js +24 -24
- package/lib/factory/model/remove-record.js +44 -44
- package/lib/factory/model/sanitize-body.js +57 -57
- package/lib/factory/model/sanitize-fixture.js +56 -56
- package/lib/factory/model/sanitize-record.js +80 -80
- package/lib/factory/model/transaction.js +15 -15
- package/lib/factory/model/update-attachment.js +9 -9
- package/lib/factory/model/update-record.js +58 -58
- package/lib/factory/model/upsert-record.js +71 -71
- package/lib/factory/model/validate.js +0 -0
- package/lib/factory/model.js +503 -503
- package/lib/helper.js +463 -463
- package/package.json +1 -1
- package/test/e2e/_run.js +12 -12
- package/test/e2e/e2e-factory-process.test.js +25 -25
- package/test/e2e/e2e-model-adapter-process.test.js +52 -52
- package/test/integration/aspect-01-start-connections.test.js +33 -33
- package/test/integration/aspect-02-query-regex.test.js +34 -34
- package/test/integration/aspect-03-model-adapter-flow.test.js +88 -88
- package/test/unit/_stub.js +244 -244
- package/test/unit/dobo-action.test.js +58 -58
- package/test/unit/dobo-connection.test.js +37 -37
- package/test/unit/dobo-core.test.js +136 -136
- package/test/unit/dobo-feature.test.js +25 -25
- package/test/unit/dobo-model.test.js +115 -115
- package/test/unit/helper-sanitize-all.test.js +40 -40
- package/test/unit/helper-sanitize-ref.test.js +64 -64
- package/wiki/APPLETS.md +0 -0
- package/wiki/CHANGES.md +477 -469
- package/wiki/CONFIG.md +0 -0
- package/wiki/CONTRIBUTING.md +0 -0
- package/wiki/DEV-GUIDE.md +0 -0
- package/wiki/ECOSYSTEM.md +0 -0
- package/wiki/GETTING-STARTED.md +0 -0
- package/wiki/QUERY-LANGUAGE.md +0 -0
- package/wiki/USER-GUIDE.md +0 -0
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { mergeAttachmentInfo, getAttachmentPath } from './helper.js'
|
|
2
|
-
const action = 'createAttachment'
|
|
3
|
-
|
|
4
|
-
async function createAttachment (...args) {
|
|
5
|
-
const { createThumbnail } = this.app.bajoExtra
|
|
6
|
-
const { thumbSizes: size } = this.app.dobo.config.default.attachment
|
|
7
|
-
if (!this.options.attachment) return
|
|
8
|
-
if (args.length === 0) return this.action(action, ...args)
|
|
9
|
-
const [id, opts = {}] = args
|
|
10
|
-
const { fs } = this.app.lib
|
|
11
|
-
const { isEmpty, last } = this.app.lib._
|
|
12
|
-
const { source, field = 'file', file, fullPath, stats, mimeType, req } = opts
|
|
13
|
-
if (isEmpty(file)) return
|
|
14
|
-
if (!source) throw this.plugin.error('isMissing%s', this.plugin.t('field.source'))
|
|
15
|
-
const [, filename] = last(source.split('/')).split('@')
|
|
16
|
-
if (isEmpty(filename)) return
|
|
17
|
-
const baseDir = await getAttachmentPath.call(this, id, field, file, { dirOnly: true })
|
|
18
|
-
let dir = `${baseDir}/${field}`
|
|
19
|
-
if ((field || '').endsWith('[]')) dir = `${baseDir}/${field.replace('[]', '')}`
|
|
20
|
-
const dest = `${dir}/${file}`.replaceAll('//', '/')
|
|
21
|
-
await fs.ensureDir(dir)
|
|
22
|
-
await fs.copy(source, dest)
|
|
23
|
-
try {
|
|
24
|
-
if (createThumbnail) await createThumbnail(dest, { dir: `${dir}/_tn`, size, format: ['.png'] })
|
|
25
|
-
} catch (err) {}
|
|
26
|
-
const rec = {
|
|
27
|
-
field: field === '' ? undefined : field,
|
|
28
|
-
dir,
|
|
29
|
-
file
|
|
30
|
-
}
|
|
31
|
-
await mergeAttachmentInfo.call(this, rec, dest, { mimeType, fullPath, stats })
|
|
32
|
-
if (!opts.noFlash && req && req.flash) req.flash('notify', req.t('attachmentUploaded'))
|
|
33
|
-
return rec
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default createAttachment
|
|
1
|
+
import { mergeAttachmentInfo, getAttachmentPath } from './helper.js'
|
|
2
|
+
const action = 'createAttachment'
|
|
3
|
+
|
|
4
|
+
async function createAttachment (...args) {
|
|
5
|
+
const { createThumbnail } = this.app.bajoExtra
|
|
6
|
+
const { thumbSizes: size } = this.app.dobo.config.default.attachment
|
|
7
|
+
if (!this.options.attachment) return
|
|
8
|
+
if (args.length === 0) return this.action(action, ...args)
|
|
9
|
+
const [id, opts = {}] = args
|
|
10
|
+
const { fs } = this.app.lib
|
|
11
|
+
const { isEmpty, last } = this.app.lib._
|
|
12
|
+
const { source, field = 'file', file, fullPath, stats, mimeType, req } = opts
|
|
13
|
+
if (isEmpty(file)) return
|
|
14
|
+
if (!source) throw this.plugin.error('isMissing%s', this.plugin.t('field.source'))
|
|
15
|
+
const [, filename] = last(source.split('/')).split('@')
|
|
16
|
+
if (isEmpty(filename)) return
|
|
17
|
+
const baseDir = await getAttachmentPath.call(this, id, field, file, { dirOnly: true })
|
|
18
|
+
let dir = `${baseDir}/${field}`
|
|
19
|
+
if ((field || '').endsWith('[]')) dir = `${baseDir}/${field.replace('[]', '')}`
|
|
20
|
+
const dest = `${dir}/${file}`.replaceAll('//', '/')
|
|
21
|
+
await fs.ensureDir(dir)
|
|
22
|
+
await fs.copy(source, dest)
|
|
23
|
+
try {
|
|
24
|
+
if (createThumbnail) await createThumbnail(dest, { dir: `${dir}/_tn`, size, format: ['.png'] })
|
|
25
|
+
} catch (err) {}
|
|
26
|
+
const rec = {
|
|
27
|
+
field: field === '' ? undefined : field,
|
|
28
|
+
dir,
|
|
29
|
+
file
|
|
30
|
+
}
|
|
31
|
+
await mergeAttachmentInfo.call(this, rec, dest, { mimeType, fullPath, stats })
|
|
32
|
+
if (!opts.noFlash && req && req.flash) req.flash('notify', req.t('attachmentUploaded'))
|
|
33
|
+
return rec
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default createAttachment
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { getFilterAndOptions, execHook, execValidation, execModelHook, execDynHook, getRefs, handleReq } from './helper.js'
|
|
2
|
-
|
|
3
|
-
export const onlyTypes = ['datetime', 'date', 'time', 'timestamp', 'array', 'object']
|
|
4
|
-
const action = 'createRecord'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Creates a new record in the model's underlying data store with the provided data.
|
|
8
|
-
*
|
|
9
|
-
* If no arguments are provided, it automatically turns into a chainable {@link DoboAction} object.
|
|
10
|
-
* @async
|
|
11
|
-
* @memberof DoboModel
|
|
12
|
-
* @method
|
|
13
|
-
* @param {object} body - The data for the new record to be created
|
|
14
|
-
* @param {DoboModel.TOptions} [opts] - Options object
|
|
15
|
-
* @returns {DoboAction|DoboModel.TResultCreateRecord|DoboModel.TRecord}
|
|
16
|
-
* @see {@link module:Hook.beforeCreateRecord}
|
|
17
|
-
* @see {@link module:Hook.afterCreateRecord}
|
|
18
|
-
*/
|
|
19
|
-
async function createRecord (...args) {
|
|
20
|
-
if (args.length === 0) return this.action(action, ...args)
|
|
21
|
-
const [body = {}, opts = {}] = args
|
|
22
|
-
const { getDefaultValues } = this.app.dobo
|
|
23
|
-
const { isSet } = this.app.lib.aneka
|
|
24
|
-
const { cloneDeep, get } = this.app.lib._
|
|
25
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
26
|
-
const { dataOnly } = opts
|
|
27
|
-
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
28
|
-
const { truncateString, noResult, noBodySanitizer, noResultSanitizer, noValidation } = options
|
|
29
|
-
const extFields = get(options, 'validation.extFields', [])
|
|
30
|
-
const input = noBodySanitizer ? cloneDeep(body) : await this.sanitizeBody({ body, extFields, strict: true, truncateString, onlyTypes, action })
|
|
31
|
-
await execHook.call(this, 'beforeCreateRecord', input, options)
|
|
32
|
-
await execModelHook.call(this, 'beforeCreateRecord', input, options)
|
|
33
|
-
await execDynHook.call(this, 'beforeCreateRecord', input, options)
|
|
34
|
-
if (!noValidation) await execValidation.call(this, input, options)
|
|
35
|
-
let result = options.record ?? (await this.adapter._createRecord(this, input, options)) ?? {}
|
|
36
|
-
if (noResult) return
|
|
37
|
-
await handleReq.call(this, result.data.id, 'created', options)
|
|
38
|
-
result = result ?? {}
|
|
39
|
-
const { warnings } = getDefaultValues(options)
|
|
40
|
-
if (!warnings) delete result.warnings
|
|
41
|
-
if (isSet(options.refs)) await getRefs.call(this, [result.data], options)
|
|
42
|
-
if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
|
|
43
|
-
await execDynHook.call(this, 'afterCreateRecord', input, result, options)
|
|
44
|
-
await execModelHook.call(this, 'afterCreateRecord', input, result, options)
|
|
45
|
-
await execHook.call(this, 'afterCreateRecord', input, result, options)
|
|
46
|
-
return dataOnly ? result.data : result
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default createRecord
|
|
1
|
+
import { getFilterAndOptions, execHook, execValidation, execModelHook, execDynHook, getRefs, handleReq } from './helper.js'
|
|
2
|
+
|
|
3
|
+
export const onlyTypes = ['datetime', 'date', 'time', 'timestamp', 'array', 'object']
|
|
4
|
+
const action = 'createRecord'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new record in the model's underlying data store with the provided data.
|
|
8
|
+
*
|
|
9
|
+
* If no arguments are provided, it automatically turns into a chainable {@link DoboAction} object.
|
|
10
|
+
* @async
|
|
11
|
+
* @memberof DoboModel
|
|
12
|
+
* @method
|
|
13
|
+
* @param {object} body - The data for the new record to be created
|
|
14
|
+
* @param {DoboModel.TOptions} [opts] - Options object
|
|
15
|
+
* @returns {DoboAction|DoboModel.TResultCreateRecord|DoboModel.TRecord}
|
|
16
|
+
* @see {@link module:Hook.beforeCreateRecord}
|
|
17
|
+
* @see {@link module:Hook.afterCreateRecord}
|
|
18
|
+
*/
|
|
19
|
+
async function createRecord (...args) {
|
|
20
|
+
if (args.length === 0) return this.action(action, ...args)
|
|
21
|
+
const [body = {}, opts = {}] = args
|
|
22
|
+
const { getDefaultValues } = this.app.dobo
|
|
23
|
+
const { isSet } = this.app.lib.aneka
|
|
24
|
+
const { cloneDeep, get } = this.app.lib._
|
|
25
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
26
|
+
const { dataOnly } = opts
|
|
27
|
+
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
28
|
+
const { truncateString, noResult, noBodySanitizer, noResultSanitizer, noValidation } = options
|
|
29
|
+
const extFields = get(options, 'validation.extFields', [])
|
|
30
|
+
const input = noBodySanitizer ? cloneDeep(body) : await this.sanitizeBody({ body, extFields, strict: true, truncateString, onlyTypes, action })
|
|
31
|
+
await execHook.call(this, 'beforeCreateRecord', input, options)
|
|
32
|
+
await execModelHook.call(this, 'beforeCreateRecord', input, options)
|
|
33
|
+
await execDynHook.call(this, 'beforeCreateRecord', input, options)
|
|
34
|
+
if (!noValidation) await execValidation.call(this, input, options)
|
|
35
|
+
let result = options.record ?? (await this.adapter._createRecord(this, input, options)) ?? {}
|
|
36
|
+
if (noResult) return
|
|
37
|
+
await handleReq.call(this, result.data.id, 'created', options)
|
|
38
|
+
result = result ?? {}
|
|
39
|
+
const { warnings } = getDefaultValues(options)
|
|
40
|
+
if (!warnings) delete result.warnings
|
|
41
|
+
if (isSet(options.refs)) await getRefs.call(this, [result.data], options)
|
|
42
|
+
if (!noResultSanitizer) result.data = await this.sanitizeRecord(result.data, options)
|
|
43
|
+
await execDynHook.call(this, 'afterCreateRecord', input, result, options)
|
|
44
|
+
await execModelHook.call(this, 'afterCreateRecord', input, result, options)
|
|
45
|
+
await execHook.call(this, 'afterCreateRecord', input, result, options)
|
|
46
|
+
return dataOnly ? result.data : result
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default createRecord
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { getFilterAndOptions, execHook, execModelHook } from './helper.js'
|
|
2
|
-
const action = 'drop'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Drops the model from the underlying data store.
|
|
6
|
-
* @async
|
|
7
|
-
* @memberof DoboModel
|
|
8
|
-
* @method
|
|
9
|
-
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
10
|
-
* @returns {DoboAction|DoboModel.TResult|boolean}
|
|
11
|
-
* @see {@link module:Hook.beforeDropModel}
|
|
12
|
-
* @see {@link module:Hook.afterDropModel}
|
|
13
|
-
*/
|
|
14
|
-
async function drop (opts = {}) {
|
|
15
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
16
|
-
const { dataOnly } = opts
|
|
17
|
-
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
18
|
-
await execHook.call(this, 'beforeDropModel', options)
|
|
19
|
-
await execModelHook.call(this, 'beforeDropModel', options)
|
|
20
|
-
const result = (await this.adapter._dropModel(this, options)) ?? {}
|
|
21
|
-
await execModelHook.call(this, 'afterDropModel', result, options)
|
|
22
|
-
await execHook.call(this, 'afterModelDrop', result, options)
|
|
23
|
-
return dataOnly ? result.data : result
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default drop
|
|
1
|
+
import { getFilterAndOptions, execHook, execModelHook } from './helper.js'
|
|
2
|
+
const action = 'drop'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Drops the model from the underlying data store.
|
|
6
|
+
* @async
|
|
7
|
+
* @memberof DoboModel
|
|
8
|
+
* @method
|
|
9
|
+
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
10
|
+
* @returns {DoboAction|DoboModel.TResult|boolean}
|
|
11
|
+
* @see {@link module:Hook.beforeDropModel}
|
|
12
|
+
* @see {@link module:Hook.afterDropModel}
|
|
13
|
+
*/
|
|
14
|
+
async function drop (opts = {}) {
|
|
15
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
16
|
+
const { dataOnly } = opts
|
|
17
|
+
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
18
|
+
await execHook.call(this, 'beforeDropModel', options)
|
|
19
|
+
await execModelHook.call(this, 'beforeDropModel', options)
|
|
20
|
+
const result = (await this.adapter._dropModel(this, options)) ?? {}
|
|
21
|
+
await execModelHook.call(this, 'afterDropModel', result, options)
|
|
22
|
+
await execHook.call(this, 'afterModelDrop', result, options)
|
|
23
|
+
return dataOnly ? result.data : result
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default drop
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { getFilterAndOptions, execHook, execModelHook } from './helper.js'
|
|
2
|
-
const action = 'modelExists'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Checks if the model exists in the underlying data store.
|
|
6
|
-
* @async
|
|
7
|
-
* @memberof DoboModel
|
|
8
|
-
* @method
|
|
9
|
-
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
10
|
-
* @returns {DoboAction|DoboModel.TResult|boolean}
|
|
11
|
-
* @see {@link module:Hook.beforeModelExists}
|
|
12
|
-
* @see {@link module:Hook.afterModelExists}
|
|
13
|
-
*/
|
|
14
|
-
async function exists (opts = {}) {
|
|
15
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
16
|
-
const { dataOnly } = opts
|
|
17
|
-
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
18
|
-
await execHook.call(this, 'beforeModelExists', options)
|
|
19
|
-
await execModelHook.call(this, 'beforeModelExists', options)
|
|
20
|
-
const result = (await this.adapter._modelExists(this, options)) ?? {}
|
|
21
|
-
await execModelHook.call(this, 'afterModelExists', result, options)
|
|
22
|
-
await execHook.call(this, 'afterModelExists', result, options)
|
|
23
|
-
return dataOnly ? result.data : result
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default exists
|
|
1
|
+
import { getFilterAndOptions, execHook, execModelHook } from './helper.js'
|
|
2
|
+
const action = 'modelExists'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Checks if the model exists in the underlying data store.
|
|
6
|
+
* @async
|
|
7
|
+
* @memberof DoboModel
|
|
8
|
+
* @method
|
|
9
|
+
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
10
|
+
* @returns {DoboAction|DoboModel.TResult|boolean}
|
|
11
|
+
* @see {@link module:Hook.beforeModelExists}
|
|
12
|
+
* @see {@link module:Hook.afterModelExists}
|
|
13
|
+
*/
|
|
14
|
+
async function exists (opts = {}) {
|
|
15
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
16
|
+
const { dataOnly } = opts
|
|
17
|
+
const { options } = await getFilterAndOptions.call(this, null, opts, action)
|
|
18
|
+
await execHook.call(this, 'beforeModelExists', options)
|
|
19
|
+
await execModelHook.call(this, 'beforeModelExists', options)
|
|
20
|
+
const result = (await this.adapter._modelExists(this, options)) ?? {}
|
|
21
|
+
await execModelHook.call(this, 'afterModelExists', result, options)
|
|
22
|
+
await execHook.call(this, 'afterModelExists', result, options)
|
|
23
|
+
return dataOnly ? result.data : result
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default exists
|
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
import { getRefs, execHook, execModelHook, execDynHook, getFilterAndOptions, cloneOptions, sanitizeQuery } from './helper.js'
|
|
2
|
-
const action = 'findAllRecord'
|
|
3
|
-
|
|
4
|
-
async function native (...args) {
|
|
5
|
-
const { isSet } = this.app.lib.aneka
|
|
6
|
-
const { getDefaultValues, t } = this.app.dobo
|
|
7
|
-
const { pick, omit, cloneDeep } = this.app.lib._
|
|
8
|
-
const [params = {}, opts = {}] = args
|
|
9
|
-
const { get, set } = this.app.bajoCache ?? {}
|
|
10
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
11
|
-
const { dataOnly } = opts
|
|
12
|
-
const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
|
|
13
|
-
delete filter.limit
|
|
14
|
-
delete filter.page
|
|
15
|
-
delete filter.skip
|
|
16
|
-
const { hardCap, warnings } = getDefaultValues(options)
|
|
17
|
-
if (dataOnly) options.count = false
|
|
18
|
-
const { noResultSanitizer } = options
|
|
19
|
-
await execHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
20
|
-
await execModelHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
21
|
-
await execDynHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
22
|
-
filter.query = sanitizeQuery.call(this, filter.query)
|
|
23
|
-
const cFilter = cloneDeep(filter)
|
|
24
|
-
if (get) {
|
|
25
|
-
const resp = await get({ model: this, action, filter: cFilter, options })
|
|
26
|
-
if (resp) {
|
|
27
|
-
resp.cached = true
|
|
28
|
-
return dataOnly ? resp.data : resp
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
let result = options.record ?? (await this.adapter._findAllRecord(this, filter, options)) ?? {}
|
|
32
|
-
result.limit = filter.limit
|
|
33
|
-
result.filter = pick(filter, ['query', 'match', 'sort'])
|
|
34
|
-
result.warnings = result.warnings ?? []
|
|
35
|
-
if (!options.count) result = omit(result, ['count', 'pages'])
|
|
36
|
-
else if (options.count && result.count > hardCap) {
|
|
37
|
-
result.warnings.push(t('hardCapWarning%s%s', result.count, hardCap))
|
|
38
|
-
result.count = hardCap
|
|
39
|
-
result.hardCapped = true
|
|
40
|
-
}
|
|
41
|
-
result.pages = options.count ? Math.ceil(result.count / filter.limit) : undefined
|
|
42
|
-
if (!warnings) delete result.warnings
|
|
43
|
-
|
|
44
|
-
if (isSet(options.refs)) await getRefs.call(this, result.data, options)
|
|
45
|
-
if (!noResultSanitizer) {
|
|
46
|
-
for (const idx in result.data) {
|
|
47
|
-
result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
await execDynHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
51
|
-
await execModelHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
52
|
-
await execHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
53
|
-
if (set) await set({ model: this, action, filter: cFilter, options, result })
|
|
54
|
-
return dataOnly ? result.data : result
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function loop (...args) {
|
|
58
|
-
const { cloneDeep } = this.app.lib._
|
|
59
|
-
const { getDefaultValues } = this.app.dobo
|
|
60
|
-
const [params = {}, opts = {}] = args
|
|
61
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
62
|
-
const { dataOnly } = opts
|
|
63
|
-
const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
|
|
64
|
-
const { maxLimit, hardCap, warnings: showWarnings } = getDefaultValues(options)
|
|
65
|
-
const nFilter = cloneDeep(filter || {})
|
|
66
|
-
const nOptions = cloneOptions.call(this, options)
|
|
67
|
-
nOptions.count = false
|
|
68
|
-
nOptions.dataOnly = false
|
|
69
|
-
nFilter.limit = maxLimit
|
|
70
|
-
nFilter.page = 1
|
|
71
|
-
let count = 0
|
|
72
|
-
const warnings = options.warnings ?? []
|
|
73
|
-
const data = []
|
|
74
|
-
for (;;) {
|
|
75
|
-
const result = await this.findRecord(nFilter, nOptions)
|
|
76
|
-
if (result.data.length === 0) break
|
|
77
|
-
if (count + result.data.length > hardCap) {
|
|
78
|
-
const sliced = result.data.slice(0, hardCap - count)
|
|
79
|
-
warnings.push(options.req ? options.req.t('hardCapWarning%s%s', result.data.length, hardCap) : this.plugin.t('hardCapWarning%s%s', result.data.length, hardCap))
|
|
80
|
-
data.push(...sliced)
|
|
81
|
-
break
|
|
82
|
-
}
|
|
83
|
-
data.push(...result.data)
|
|
84
|
-
count = count + result.data.length
|
|
85
|
-
nFilter.page++
|
|
86
|
-
}
|
|
87
|
-
const result = { data, count, warnings }
|
|
88
|
-
if (!showWarnings) delete result.warnings
|
|
89
|
-
return dataOnly ? data : result
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Finds all records from the model's underlying data store based on the provided filter.
|
|
94
|
-
* @async
|
|
95
|
-
* @memberof DoboModel
|
|
96
|
-
* @method
|
|
97
|
-
* @param {DoboModel.TFilter} filter - The filter parameters for finding the records.
|
|
98
|
-
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
99
|
-
* @returns {DoboAction|DoboModel.TResultFindRecord|Array<DoboModel.TRecord>}
|
|
100
|
-
* @see {@link module:Hook.beforeFindAllRecord}
|
|
101
|
-
* @see {@link module:Hook.afterFindAllRecord}
|
|
102
|
-
*/
|
|
103
|
-
async function findAllRecord (...args) {
|
|
104
|
-
// can't use action here, because people tends to use is without arguments
|
|
105
|
-
// if (args.length === 0) return this.action(action, ...args)
|
|
106
|
-
if (this.adapter.findAllRecord) {
|
|
107
|
-
return await native.call(this, ...args)
|
|
108
|
-
}
|
|
109
|
-
return await loop.call(this, ...args)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export default findAllRecord
|
|
1
|
+
import { getRefs, execHook, execModelHook, execDynHook, getFilterAndOptions, cloneOptions, sanitizeQuery } from './helper.js'
|
|
2
|
+
const action = 'findAllRecord'
|
|
3
|
+
|
|
4
|
+
async function native (...args) {
|
|
5
|
+
const { isSet } = this.app.lib.aneka
|
|
6
|
+
const { getDefaultValues, t } = this.app.dobo
|
|
7
|
+
const { pick, omit, cloneDeep } = this.app.lib._
|
|
8
|
+
const [params = {}, opts = {}] = args
|
|
9
|
+
const { get, set } = this.app.bajoCache ?? {}
|
|
10
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
11
|
+
const { dataOnly } = opts
|
|
12
|
+
const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
|
|
13
|
+
delete filter.limit
|
|
14
|
+
delete filter.page
|
|
15
|
+
delete filter.skip
|
|
16
|
+
const { hardCap, warnings } = getDefaultValues(options)
|
|
17
|
+
if (dataOnly) options.count = false
|
|
18
|
+
const { noResultSanitizer } = options
|
|
19
|
+
await execHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
20
|
+
await execModelHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
21
|
+
await execDynHook.call(this, 'beforeFindAllRecord', filter, options)
|
|
22
|
+
filter.query = sanitizeQuery.call(this, filter.query)
|
|
23
|
+
const cFilter = cloneDeep(filter)
|
|
24
|
+
if (get) {
|
|
25
|
+
const resp = await get({ model: this, action, filter: cFilter, options })
|
|
26
|
+
if (resp) {
|
|
27
|
+
resp.cached = true
|
|
28
|
+
return dataOnly ? resp.data : resp
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let result = options.record ?? (await this.adapter._findAllRecord(this, filter, options)) ?? {}
|
|
32
|
+
result.limit = filter.limit
|
|
33
|
+
result.filter = pick(filter, ['query', 'match', 'sort'])
|
|
34
|
+
result.warnings = result.warnings ?? []
|
|
35
|
+
if (!options.count) result = omit(result, ['count', 'pages'])
|
|
36
|
+
else if (options.count && result.count > hardCap) {
|
|
37
|
+
result.warnings.push(t('hardCapWarning%s%s', result.count, hardCap))
|
|
38
|
+
result.count = hardCap
|
|
39
|
+
result.hardCapped = true
|
|
40
|
+
}
|
|
41
|
+
result.pages = options.count ? Math.ceil(result.count / filter.limit) : undefined
|
|
42
|
+
if (!warnings) delete result.warnings
|
|
43
|
+
|
|
44
|
+
if (isSet(options.refs)) await getRefs.call(this, result.data, options)
|
|
45
|
+
if (!noResultSanitizer) {
|
|
46
|
+
for (const idx in result.data) {
|
|
47
|
+
result.data[idx] = await this.sanitizeRecord(result.data[idx], options)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
await execDynHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
51
|
+
await execModelHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
52
|
+
await execHook.call(this, 'afterFindAllRecord', filter, result, options)
|
|
53
|
+
if (set) await set({ model: this, action, filter: cFilter, options, result })
|
|
54
|
+
return dataOnly ? result.data : result
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function loop (...args) {
|
|
58
|
+
const { cloneDeep } = this.app.lib._
|
|
59
|
+
const { getDefaultValues } = this.app.dobo
|
|
60
|
+
const [params = {}, opts = {}] = args
|
|
61
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
62
|
+
const { dataOnly } = opts
|
|
63
|
+
const { filter, options } = await getFilterAndOptions.call(this, params, opts, action)
|
|
64
|
+
const { maxLimit, hardCap, warnings: showWarnings } = getDefaultValues(options)
|
|
65
|
+
const nFilter = cloneDeep(filter || {})
|
|
66
|
+
const nOptions = cloneOptions.call(this, options)
|
|
67
|
+
nOptions.count = false
|
|
68
|
+
nOptions.dataOnly = false
|
|
69
|
+
nFilter.limit = maxLimit
|
|
70
|
+
nFilter.page = 1
|
|
71
|
+
let count = 0
|
|
72
|
+
const warnings = options.warnings ?? []
|
|
73
|
+
const data = []
|
|
74
|
+
for (;;) {
|
|
75
|
+
const result = await this.findRecord(nFilter, nOptions)
|
|
76
|
+
if (result.data.length === 0) break
|
|
77
|
+
if (count + result.data.length > hardCap) {
|
|
78
|
+
const sliced = result.data.slice(0, hardCap - count)
|
|
79
|
+
warnings.push(options.req ? options.req.t('hardCapWarning%s%s', result.data.length, hardCap) : this.plugin.t('hardCapWarning%s%s', result.data.length, hardCap))
|
|
80
|
+
data.push(...sliced)
|
|
81
|
+
break
|
|
82
|
+
}
|
|
83
|
+
data.push(...result.data)
|
|
84
|
+
count = count + result.data.length
|
|
85
|
+
nFilter.page++
|
|
86
|
+
}
|
|
87
|
+
const result = { data, count, warnings }
|
|
88
|
+
if (!showWarnings) delete result.warnings
|
|
89
|
+
return dataOnly ? data : result
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Finds all records from the model's underlying data store based on the provided filter.
|
|
94
|
+
* @async
|
|
95
|
+
* @memberof DoboModel
|
|
96
|
+
* @method
|
|
97
|
+
* @param {DoboModel.TFilter} filter - The filter parameters for finding the records.
|
|
98
|
+
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
99
|
+
* @returns {DoboAction|DoboModel.TResultFindRecord|Array<DoboModel.TRecord>}
|
|
100
|
+
* @see {@link module:Hook.beforeFindAllRecord}
|
|
101
|
+
* @see {@link module:Hook.afterFindAllRecord}
|
|
102
|
+
*/
|
|
103
|
+
async function findAllRecord (...args) {
|
|
104
|
+
// can't use action here, because people tends to use is without arguments
|
|
105
|
+
// if (args.length === 0) return this.action(action, ...args)
|
|
106
|
+
if (this.adapter.findAllRecord) {
|
|
107
|
+
return await native.call(this, ...args)
|
|
108
|
+
}
|
|
109
|
+
return await loop.call(this, ...args)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export default findAllRecord
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { mergeAttachmentInfo } from './helper.js'
|
|
2
|
-
const action = 'findAttachment'
|
|
3
|
-
|
|
4
|
-
async function findAttachment (...args) {
|
|
5
|
-
if (!this.options.attachment) return
|
|
6
|
-
if (args.length === 0) return this.action(action, ...args)
|
|
7
|
-
const [id, opts = {}] = args
|
|
8
|
-
const { fastGlob, fs } = this.app.lib
|
|
9
|
-
const dir = `${this.app.getPluginDataDir(this.plugin.ns)}/attachment/${this.name}/${id}`
|
|
10
|
-
if (!fs.existsSync(dir)) return []
|
|
11
|
-
const files = await fastGlob(`${dir}/**/*`)
|
|
12
|
-
const { fullPath, stats, mimeType } = opts
|
|
13
|
-
const recs = []
|
|
14
|
-
for (const f of files) {
|
|
15
|
-
const item = f.replace(dir, '')
|
|
16
|
-
let [, field, file] = item.split('/')
|
|
17
|
-
if (!file) {
|
|
18
|
-
file = field
|
|
19
|
-
field = null
|
|
20
|
-
}
|
|
21
|
-
const rec = { field, file }
|
|
22
|
-
await mergeAttachmentInfo.call(this, rec, f, { mimeType, fullPath, stats })
|
|
23
|
-
recs.push(rec)
|
|
24
|
-
}
|
|
25
|
-
return recs
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default findAttachment
|
|
1
|
+
import { mergeAttachmentInfo } from './helper.js'
|
|
2
|
+
const action = 'findAttachment'
|
|
3
|
+
|
|
4
|
+
async function findAttachment (...args) {
|
|
5
|
+
if (!this.options.attachment) return
|
|
6
|
+
if (args.length === 0) return this.action(action, ...args)
|
|
7
|
+
const [id, opts = {}] = args
|
|
8
|
+
const { fastGlob, fs } = this.app.lib
|
|
9
|
+
const dir = `${this.app.getPluginDataDir(this.plugin.ns)}/attachment/${this.name}/${id}`
|
|
10
|
+
if (!fs.existsSync(dir)) return []
|
|
11
|
+
const files = await fastGlob(`${dir}/**/*`)
|
|
12
|
+
const { fullPath, stats, mimeType } = opts
|
|
13
|
+
const recs = []
|
|
14
|
+
for (const f of files) {
|
|
15
|
+
const item = f.replace(dir, '')
|
|
16
|
+
let [, field, file] = item.split('/')
|
|
17
|
+
if (!file) {
|
|
18
|
+
file = field
|
|
19
|
+
field = null
|
|
20
|
+
}
|
|
21
|
+
const rec = { field, file }
|
|
22
|
+
await mergeAttachmentInfo.call(this, rec, f, { mimeType, fullPath, stats })
|
|
23
|
+
recs.push(rec)
|
|
24
|
+
}
|
|
25
|
+
return recs
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default findAttachment
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { cloneOptions } from './helper.js'
|
|
2
|
-
|
|
3
|
-
const action = 'findOneRecord'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Finds a single record from the model's underlying data store based on the provided filter.
|
|
7
|
-
*
|
|
8
|
-
* If no arguments are provided, it automatically turns into a chainable {@link DoboAction} object.
|
|
9
|
-
* @async
|
|
10
|
-
* @memberof DoboModel
|
|
11
|
-
* @method
|
|
12
|
-
* @param {DoboModel.TFilter} filter - The filter parameters for finding the record.
|
|
13
|
-
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
14
|
-
* @returns {DoboAction|DoboModel.TResultFindRecord|Array<DoboModel.TRecord>}
|
|
15
|
-
* @see {@link module:Hook.beforeFindRecord}
|
|
16
|
-
*/
|
|
17
|
-
async function findOneRecord (...args) {
|
|
18
|
-
if (args.length === 0) return this.action(action, ...args)
|
|
19
|
-
const { getDefaultValues } = this.app.dobo
|
|
20
|
-
const [params = {}, opts = {}] = args
|
|
21
|
-
const { cloneDeep } = this.app.lib._
|
|
22
|
-
opts.dataOnly = opts.dataOnly ?? true
|
|
23
|
-
const { dataOnly } = opts
|
|
24
|
-
if (dataOnly) opts.count = false
|
|
25
|
-
const nFilter = cloneDeep(params || {})
|
|
26
|
-
const nOptions = cloneOptions.call(this, opts)
|
|
27
|
-
nOptions.count = false
|
|
28
|
-
nOptions.dataOnly = false
|
|
29
|
-
nFilter.limit = 1
|
|
30
|
-
const { warnings } = getDefaultValues(nOptions)
|
|
31
|
-
const resp = await this.findRecord(nFilter, nOptions)
|
|
32
|
-
const data = resp.data[0]
|
|
33
|
-
const result = { data, warnings: resp.warnings }
|
|
34
|
-
if (!warnings) delete result.warnings
|
|
35
|
-
return dataOnly ? data : result
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export default findOneRecord
|
|
1
|
+
import { cloneOptions } from './helper.js'
|
|
2
|
+
|
|
3
|
+
const action = 'findOneRecord'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Finds a single record from the model's underlying data store based on the provided filter.
|
|
7
|
+
*
|
|
8
|
+
* If no arguments are provided, it automatically turns into a chainable {@link DoboAction} object.
|
|
9
|
+
* @async
|
|
10
|
+
* @memberof DoboModel
|
|
11
|
+
* @method
|
|
12
|
+
* @param {DoboModel.TFilter} filter - The filter parameters for finding the record.
|
|
13
|
+
* @param {DoboModel.TOptions} [opts] - Options object.
|
|
14
|
+
* @returns {DoboAction|DoboModel.TResultFindRecord|Array<DoboModel.TRecord>}
|
|
15
|
+
* @see {@link module:Hook.beforeFindRecord}
|
|
16
|
+
*/
|
|
17
|
+
async function findOneRecord (...args) {
|
|
18
|
+
if (args.length === 0) return this.action(action, ...args)
|
|
19
|
+
const { getDefaultValues } = this.app.dobo
|
|
20
|
+
const [params = {}, opts = {}] = args
|
|
21
|
+
const { cloneDeep } = this.app.lib._
|
|
22
|
+
opts.dataOnly = opts.dataOnly ?? true
|
|
23
|
+
const { dataOnly } = opts
|
|
24
|
+
if (dataOnly) opts.count = false
|
|
25
|
+
const nFilter = cloneDeep(params || {})
|
|
26
|
+
const nOptions = cloneOptions.call(this, opts)
|
|
27
|
+
nOptions.count = false
|
|
28
|
+
nOptions.dataOnly = false
|
|
29
|
+
nFilter.limit = 1
|
|
30
|
+
const { warnings } = getDefaultValues(nOptions)
|
|
31
|
+
const resp = await this.findRecord(nFilter, nOptions)
|
|
32
|
+
const data = resp.data[0]
|
|
33
|
+
const result = { data, warnings: resp.warnings }
|
|
34
|
+
if (!warnings) delete result.warnings
|
|
35
|
+
return dataOnly ? data : result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default findOneRecord
|