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.
Files changed (160) hide show
  1. package/.bootorder +0 -0
  2. package/.github/FUNDING.yml +0 -0
  3. package/.github/workflows/repo-lockdown.yml +0 -0
  4. package/.jsdoc.conf.json +0 -0
  5. package/LICENSE +0 -0
  6. package/README.md +0 -0
  7. package/docs/Dobo.html +0 -0
  8. package/docs/DoboAction.html +0 -0
  9. package/docs/DoboAdapter.html +0 -0
  10. package/docs/DoboConnection.html +0 -0
  11. package/docs/DoboFeature.html +0 -0
  12. package/docs/DoboModel.html +0 -0
  13. package/docs/data/search.json +0 -0
  14. package/docs/extend_bajo_hook-docs.js.html +0 -0
  15. package/docs/external-Tools.html +0 -0
  16. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  17. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  18. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  19. package/docs/global.html +0 -0
  20. package/docs/index.html +0 -0
  21. package/docs/index.js.html +0 -0
  22. package/docs/lib_factory_action.js.html +0 -0
  23. package/docs/lib_factory_adapter.js.html +0 -0
  24. package/docs/lib_factory_connection.js.html +0 -0
  25. package/docs/lib_factory_feature.js.html +0 -0
  26. package/docs/lib_factory_model.js.html +0 -0
  27. package/docs/lib_factory_model_build.js.html +0 -0
  28. package/docs/lib_factory_model_clear-record.js.html +0 -0
  29. package/docs/lib_factory_model_count-record.js.html +0 -0
  30. package/docs/lib_factory_model_create-record.js.html +0 -0
  31. package/docs/lib_factory_model_drop.js.html +0 -0
  32. package/docs/lib_factory_model_exists.js.html +0 -0
  33. package/docs/lib_factory_model_find-all-record.js.html +0 -0
  34. package/docs/lib_factory_model_find-one-record.js.html +0 -0
  35. package/docs/lib_factory_model_find-record.js.html +0 -0
  36. package/docs/lib_factory_model_get-record.js.html +0 -0
  37. package/docs/lib_factory_model_helper.js.html +0 -0
  38. package/docs/lib_factory_model_remove-record.js.html +0 -0
  39. package/docs/lib_factory_model_sanitize-body.js.html +0 -0
  40. package/docs/lib_factory_model_sanitize-fixture.js.html +0 -0
  41. package/docs/lib_factory_model_sanitize-record.js.html +0 -0
  42. package/docs/lib_factory_model_update-record.js.html +0 -0
  43. package/docs/lib_factory_model_upsert-record.js.html +0 -0
  44. package/docs/lib_factory_model_validate.js.html +0 -0
  45. package/docs/lib_helper.js.html +0 -0
  46. package/docs/module-Helper.html +0 -0
  47. package/docs/module-Helper_Model.html +0 -0
  48. package/docs/module-Hook.html +0 -0
  49. package/docs/scripts/core.js +0 -0
  50. package/docs/scripts/core.min.js +0 -0
  51. package/docs/scripts/resize.js +0 -0
  52. package/docs/scripts/search.js +0 -0
  53. package/docs/scripts/search.min.js +5 -5
  54. package/docs/scripts/third-party/Apache-License-2.0.txt +0 -0
  55. package/docs/scripts/third-party/fuse.js +0 -0
  56. package/docs/scripts/third-party/hljs-line-num-original.js +0 -0
  57. package/docs/scripts/third-party/hljs-line-num.js +0 -0
  58. package/docs/scripts/third-party/hljs-original.js +0 -0
  59. package/docs/scripts/third-party/hljs.js +0 -0
  60. package/docs/scripts/third-party/popper.js +0 -0
  61. package/docs/scripts/third-party/tippy.js +0 -0
  62. package/docs/scripts/third-party/tocbot.js +0 -0
  63. package/docs/scripts/third-party/tocbot.min.js +0 -0
  64. package/docs/static/bitcoin.jpeg +0 -0
  65. package/docs/static/home.md +0 -0
  66. package/docs/static/logo-ecosystem.png +0 -0
  67. package/docs/static/logo.png +0 -0
  68. package/docs/styles/clean-jsdoc-theme-base.css +0 -0
  69. package/docs/styles/clean-jsdoc-theme-dark.css +0 -0
  70. package/docs/styles/clean-jsdoc-theme-light.css +0 -0
  71. package/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -0
  72. package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -0
  73. package/docs/styles/clean-jsdoc-theme.min.css +0 -0
  74. package/extend/bajo/hook.js +236 -236
  75. package/extend/bajo/intl/en-US.json +0 -0
  76. package/extend/bajo/intl/id.json +0 -0
  77. package/extend/bajoCli/applet/aggregate.js +0 -0
  78. package/extend/bajoCli/applet/clear-record.js +0 -0
  79. package/extend/bajoCli/applet/connection.js +0 -0
  80. package/extend/bajoCli/applet/count-record.js +0 -0
  81. package/extend/bajoCli/applet/create-record.js +0 -0
  82. package/extend/bajoCli/applet/find-record.js +0 -0
  83. package/extend/bajoCli/applet/get-record.js +0 -0
  84. package/extend/bajoCli/applet/histogram.js +0 -0
  85. package/extend/bajoCli/applet/lib/post-process.js +0 -0
  86. package/extend/bajoCli/applet/model.js +0 -0
  87. package/extend/bajoCli/applet/rebuild-model.js +0 -0
  88. package/extend/bajoCli/applet/remove-record.js +0 -0
  89. package/extend/bajoCli/applet/update-record.js +0 -0
  90. package/extend/bajoCli/applet.js +0 -0
  91. package/extend/dobo/adapter/memory.js +175 -175
  92. package/extend/dobo/feature/created-at.js +0 -0
  93. package/extend/dobo/feature/dt.js +0 -0
  94. package/extend/dobo/feature/image.js +0 -0
  95. package/extend/dobo/feature/immutable.js +0 -0
  96. package/extend/dobo/feature/removed-at.js +0 -0
  97. package/extend/dobo/feature/unique.js +0 -0
  98. package/extend/dobo/feature/updated-at.js +0 -0
  99. package/extend/waibuMpa/route/attachment/@model/@id/@field/@file.js +0 -0
  100. package/extend/waibuStatic/virtual.json +0 -0
  101. package/index.js +0 -0
  102. package/lib/factory/action.js +287 -287
  103. package/lib/factory/adapter.js +1055 -1055
  104. package/lib/factory/connection.js +109 -109
  105. package/lib/factory/feature.js +52 -52
  106. package/lib/factory/model/aggregate.js +23 -23
  107. package/lib/factory/model/build.js +25 -25
  108. package/lib/factory/model/bulk-create-record.js +36 -36
  109. package/lib/factory/model/clear-record.js +30 -30
  110. package/lib/factory/model/count-record.js +42 -42
  111. package/lib/factory/model/create-attachment.js +36 -36
  112. package/lib/factory/model/create-record.js +49 -49
  113. package/lib/factory/model/drop.js +26 -26
  114. package/lib/factory/model/exists.js +26 -26
  115. package/lib/factory/model/find-all-record.js +112 -112
  116. package/lib/factory/model/find-attachment.js +28 -28
  117. package/lib/factory/model/find-one-record.js +38 -38
  118. package/lib/factory/model/find-record.js +82 -82
  119. package/lib/factory/model/get-attachment.js +15 -15
  120. package/lib/factory/model/get-record.js +52 -52
  121. package/lib/factory/model/helper.js +575 -576
  122. package/lib/factory/model/histogram.js +23 -23
  123. package/lib/factory/model/list-attachment.js +40 -40
  124. package/lib/factory/model/load-fixtures.js +63 -63
  125. package/lib/factory/model/remove-attachment.js +24 -24
  126. package/lib/factory/model/remove-record.js +44 -44
  127. package/lib/factory/model/sanitize-body.js +57 -57
  128. package/lib/factory/model/sanitize-fixture.js +56 -56
  129. package/lib/factory/model/sanitize-record.js +80 -80
  130. package/lib/factory/model/transaction.js +15 -15
  131. package/lib/factory/model/update-attachment.js +9 -9
  132. package/lib/factory/model/update-record.js +58 -58
  133. package/lib/factory/model/upsert-record.js +71 -71
  134. package/lib/factory/model/validate.js +0 -0
  135. package/lib/factory/model.js +503 -503
  136. package/lib/helper.js +463 -463
  137. package/package.json +1 -1
  138. package/test/e2e/_run.js +12 -12
  139. package/test/e2e/e2e-factory-process.test.js +25 -25
  140. package/test/e2e/e2e-model-adapter-process.test.js +52 -52
  141. package/test/integration/aspect-01-start-connections.test.js +33 -33
  142. package/test/integration/aspect-02-query-regex.test.js +34 -34
  143. package/test/integration/aspect-03-model-adapter-flow.test.js +88 -88
  144. package/test/unit/_stub.js +244 -244
  145. package/test/unit/dobo-action.test.js +58 -58
  146. package/test/unit/dobo-connection.test.js +37 -37
  147. package/test/unit/dobo-core.test.js +136 -136
  148. package/test/unit/dobo-feature.test.js +25 -25
  149. package/test/unit/dobo-model.test.js +115 -115
  150. package/test/unit/helper-sanitize-all.test.js +40 -40
  151. package/test/unit/helper-sanitize-ref.test.js +64 -64
  152. package/wiki/APPLETS.md +0 -0
  153. package/wiki/CHANGES.md +477 -469
  154. package/wiki/CONFIG.md +0 -0
  155. package/wiki/CONTRIBUTING.md +0 -0
  156. package/wiki/DEV-GUIDE.md +0 -0
  157. package/wiki/ECOSYSTEM.md +0 -0
  158. package/wiki/GETTING-STARTED.md +0 -0
  159. package/wiki/QUERY-LANGUAGE.md +0 -0
  160. 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