dobo 2.30.7 → 2.32.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.
Files changed (123) hide show
  1. package/.jsdoc.conf.json +1 -1
  2. package/docs/Dobo.html +1 -24
  3. package/docs/DoboAction.html +13 -0
  4. package/docs/DoboAdapter.html +3 -0
  5. package/docs/DoboConnection.html +3 -0
  6. package/docs/DoboFeature.html +3 -0
  7. package/docs/DoboModel.html +51 -0
  8. package/docs/data/search.json +1 -1
  9. package/docs/extend_bajo_hook-docs.js.html +241 -0
  10. package/docs/external-Tools.html +3 -0
  11. package/docs/global.html +1 -5
  12. package/docs/index.html +1 -1
  13. package/docs/index.js.html +434 -380
  14. package/docs/lib_factory_action.js.html +290 -0
  15. package/docs/lib_factory_adapter.js.html +1057 -0
  16. package/docs/lib_factory_connection.js.html +112 -0
  17. package/docs/lib_factory_feature.js.html +55 -0
  18. package/docs/lib_factory_model.js.html +503 -0
  19. package/docs/lib_factory_model_build.js.html +28 -0
  20. package/docs/lib_factory_model_clear-record.js.html +33 -0
  21. package/docs/lib_factory_model_count-record.js.html +45 -0
  22. package/docs/lib_factory_model_create-record.js.html +52 -0
  23. package/docs/lib_factory_model_drop.js.html +29 -0
  24. package/docs/lib_factory_model_exists.js.html +29 -0
  25. package/docs/lib_factory_model_find-all-record.js.html +115 -0
  26. package/docs/lib_factory_model_find-one-record.js.html +41 -0
  27. package/docs/lib_factory_model_find-record.js.html +85 -0
  28. package/docs/lib_factory_model_get-record.js.html +55 -0
  29. package/docs/lib_factory_model_helper.js.html +579 -0
  30. package/docs/lib_factory_model_remove-record.js.html +47 -0
  31. package/docs/lib_factory_model_sanitize-body.js.html +60 -0
  32. package/docs/lib_factory_model_sanitize-fixture.js.html +59 -0
  33. package/docs/lib_factory_model_sanitize-record.js.html +73 -0
  34. package/docs/lib_factory_model_update-record.js.html +61 -0
  35. package/docs/lib_factory_model_upsert-record.js.html +74 -0
  36. package/docs/{method_validate.js.html → lib_factory_model_validate.js.html} +109 -73
  37. package/docs/lib_helper.js.html +466 -0
  38. package/docs/module-Helper.html +3 -0
  39. package/docs/module-Helper_Model.html +3 -0
  40. package/docs/module-Hook.html +15 -0
  41. package/docs/scripts/core.js +477 -476
  42. package/docs/scripts/resize.js +36 -36
  43. package/docs/scripts/search.js +105 -105
  44. package/docs/scripts/third-party/fuse.js +1 -1
  45. package/docs/scripts/third-party/hljs-line-num-original.js +285 -282
  46. package/docs/scripts/third-party/hljs-line-num.js +1 -1
  47. package/docs/scripts/third-party/hljs-original.js +1202 -1195
  48. package/docs/scripts/third-party/hljs.js +1 -1
  49. package/docs/scripts/third-party/popper.js +1 -1
  50. package/docs/scripts/third-party/tippy.js +1 -1
  51. package/docs/scripts/third-party/tocbot.js +509 -508
  52. package/docs/static/home.md +3 -1
  53. package/extend/bajo/hook-docs.js +238 -0
  54. package/extend/bajo/intl/en-US.json +9 -9
  55. package/extend/bajo/intl/id.json +9 -9
  56. package/extend/bajoCli/applet/rebuild-model.js +2 -2
  57. package/extend/dobo/{driver → adapter}/memory.js +6 -6
  58. package/extend/dobo/feature/immutable.js +2 -2
  59. package/extend/dobo/feature/removed-at.js +1 -1
  60. package/index.js +33 -30
  61. package/lib/factory/action.js +145 -18
  62. package/lib/factory/adapter.js +1054 -0
  63. package/lib/factory/connection.js +46 -22
  64. package/lib/factory/feature.js +23 -3
  65. package/lib/factory/model/build.js +11 -2
  66. package/lib/factory/model/bulk-create-record.js +2 -2
  67. package/lib/factory/model/clear-record.js +13 -3
  68. package/lib/factory/model/count-record.js +13 -2
  69. package/lib/factory/model/create-aggregate.js +2 -2
  70. package/lib/factory/model/create-attachment.js +1 -1
  71. package/lib/factory/model/create-histogram.js +2 -2
  72. package/lib/factory/model/create-record.js +15 -2
  73. package/lib/factory/model/drop.js +12 -2
  74. package/lib/factory/model/exists.js +10 -6
  75. package/lib/factory/model/find-all-record.js +14 -3
  76. package/lib/factory/model/find-attachment.js +1 -1
  77. package/lib/factory/model/find-one-record.js +13 -1
  78. package/lib/factory/model/find-record.js +17 -53
  79. package/lib/factory/model/get-record.js +11 -39
  80. package/lib/factory/model/{_util.js → helper.js} +176 -16
  81. package/lib/factory/model/remove-attachment.js +1 -1
  82. package/lib/factory/model/remove-record.js +11 -28
  83. package/lib/factory/model/sanitize-body.js +14 -12
  84. package/lib/factory/model/sanitize-fixture.js +17 -4
  85. package/lib/factory/model/sanitize-record.js +9 -6
  86. package/lib/factory/model/transaction.js +2 -2
  87. package/lib/factory/model/update-record.js +12 -40
  88. package/lib/factory/model/upsert-record.js +13 -42
  89. package/lib/factory/model/validate.js +47 -14
  90. package/lib/factory/model.js +301 -23
  91. package/lib/{collect-models.js → helper.js} +463 -364
  92. package/package.json +1 -1
  93. package/wiki/CHANGES.md +17 -7
  94. package/wiki/ECOSYSTEM.md +7 -7
  95. package/wiki/GETTING-STARTED.md +3 -3
  96. package/wiki/QUERY-LANGUAGE.md +1 -1
  97. package/docs/lib_collect-connections.js.html +0 -39
  98. package/docs/lib_collect-drivers.js.html +0 -52
  99. package/docs/lib_collect-features.js.html +0 -36
  100. package/docs/lib_collect-schemas.js.html +0 -94
  101. package/docs/lib_index.js.html +0 -6
  102. package/docs/method_model_create.js.html +0 -35
  103. package/docs/method_model_drop.js.html +0 -34
  104. package/docs/method_model_exists.js.html +0 -40
  105. package/docs/method_record_count.js.html +0 -69
  106. package/docs/method_record_create.js.html +0 -114
  107. package/docs/method_record_find-all.js.html +0 -44
  108. package/docs/method_record_find-one.js.html +0 -73
  109. package/docs/method_record_find.js.html +0 -118
  110. package/docs/method_record_get.js.html +0 -92
  111. package/docs/method_record_remove.js.html +0 -75
  112. package/docs/method_record_update.js.html +0 -107
  113. package/docs/method_record_upsert.js.html +0 -54
  114. package/docs/method_sanitize_body.js.html +0 -88
  115. package/docs/method_sanitize_date.js.html +0 -30
  116. package/docs/method_sanitize_id.js.html +0 -20
  117. package/docs/module-Lib.html +0 -3
  118. package/lib/collect-connections.js +0 -56
  119. package/lib/collect-drivers.js +0 -35
  120. package/lib/collect-features.js +0 -40
  121. package/lib/factory/driver.js +0 -574
  122. package/lib/factory/model/sanitize-id.js +0 -7
  123. package/lib/index.js +0 -3
@@ -0,0 +1,466 @@
1
+ <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: lib/helper.js</title><!--[if lt IE 9]>
2
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
+ <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="light"><div class="sidebar-container"><div class="sidebar" id="sidebar"><a href="/" class="sidebar-title sidebar-title-anchor">Dobo API</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="Dobo.html">Dobo</a></div><div class="sidebar-section-children"><a href="DoboAction.html">DoboAction</a></div><div class="sidebar-section-children"><a href="DoboAdapter.html">DoboAdapter</a></div><div class="sidebar-section-children"><a href="DoboConnection.html">DoboConnection</a></div><div class="sidebar-section-children"><a href="DoboFeature.html">DoboFeature</a></div><div class="sidebar-section-children"><a href="DoboModel.html">DoboModel</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-Helper.html">Helper</a></div><div class="sidebar-section-children"><a href="module-Helper_Model.html">Helper/Model</a></div><div class="sidebar-section-children"><a href="module-Hook.html">Hook</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="external-Tools.html">Tools</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#actionFactory">actionFactory</a></div><div class="sidebar-section-children"><a href="global.html#adapterFactory">adapterFactory</a></div><div class="sidebar-section-children"><a href="global.html#connectionFactory">connectionFactory</a></div><div class="sidebar-section-children"><a href="global.html#featureFactory">featureFactory</a></div><div class="sidebar-section-children"><a href="global.html#modelFactory">modelFactory</a></div><div class="sidebar-section-children"><a href="global.html#pluginFactory">pluginFactory</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/dobo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/dobo" target="">Github</a></div><div class="navbar-item"><a id="" href="https://dobo.bajo.app/" target="">Dobo</a></div><div class="navbar-item"><a id="" href="https://bajo.app/" target="">Bajo</a></div></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">lib_helper.js</h1></header><article><pre class="prettyprint source lang-js"><code>import path from 'path'
4
+ import adapterFactory from './factory/adapter.js'
5
+ import connectionFactory from './factory/connection.js'
6
+ import featureFactory from './factory/feature.js'
7
+ import modelFactory from './factory/model.js'
8
+ import actionFactory from './factory/action.js'
9
+
10
+ /**
11
+ * @module Helper
12
+ */
13
+
14
+ /**
15
+ * Sanitizes a property definition for a model, ensuring it adheres to the expected structure and types.
16
+ * It handles various property attributes such as type, index, required status, and more.
17
+ *
18
+ * If the property is virtual, it processes it accordingly; otherwise, it adds it to the model's properties
19
+ * and indexes.
20
+ * @param {DoboModel} model
21
+ * @param {DoboModel.TProperty} prop
22
+ * @param {DoboModel.TIndex[]} indexes
23
+ */
24
+ async function sanitizeProp (model, prop, indexes) {
25
+ const { isEmpty, isString, keys, pick, isArray, isPlainObject, omit, isFunction } = this.app.lib._
26
+ const allPropKeys = this.getAllPropertyKeys(model.connection.adapter)
27
+ const propType = this.constructor.propertyType
28
+ if (isString(prop)) {
29
+ let [name, type, maxLength, idx, required] = prop.split(',').map(m => m.trim())
30
+ if (isEmpty(type)) type = 'string'
31
+ maxLength = isEmpty(maxLength) ? propType.string.maxLength : parseInt(maxLength)
32
+ prop = { name, type, maxLength }
33
+ if (!isEmpty(idx)) prop.index = idx
34
+ prop.required = required === 'true'
35
+ }
36
+ prop.type = prop.type ?? 'string'
37
+ if (isArray(prop.values)) {
38
+ prop.values = prop.values.map(item => {
39
+ if (isPlainObject(item)) return pick(item, ['value', 'text'])
40
+ return { value: item, text: item }
41
+ })
42
+ } else if (!(isString(prop.values) || isFunction(prop.values))) delete prop.values
43
+ if (prop.hidden) model.hidden.push(prop.name)
44
+ if (prop.scanable) model.scanables.push(prop.scanable)
45
+ if (prop.virtual) {
46
+ const keys = Object.keys(propType)
47
+ if (!keys.includes(prop.type)) this.fatal('unknownPropType%s%s', `${prop.name}:${prop.type}`, model.name)
48
+ for (const key of ['required', 'rules', 'index', 'validator', 'ref', 'rulesMsg', 'immutable']) {
49
+ delete prop[key]
50
+ }
51
+ model.properties.push(prop)
52
+ } else {
53
+ if (prop.index) {
54
+ if (prop.index === true || prop.index === 'true') prop.index = 'index'
55
+ const [idx, idxName] = prop.index.split(':')
56
+ const index = { name: idxName ?? `${model.collName}_${prop.name}_${idx}`, fields: [prop.name], type: idx }
57
+ indexes.push(index)
58
+ }
59
+ if (keys(propType).includes(prop.type)) model.properties.push(pick(prop, allPropKeys))
60
+ else {
61
+ const feature = this.getFeature(prop.type)
62
+ if (!feature) this.fatal('unknownPropType%s%s', prop.type, model.name)
63
+ const opts = omit(prop, ['name', 'type'])
64
+ opts.field = prop.name
65
+ await applyFeature.call(this, model, feature, opts, indexes)
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Finds and sanitizes all properties for a given model schema, ensuring that the 'id' property is included and
72
+ * that all properties are properly processed.
73
+ * @param {object} schema - The model schema
74
+ * @param {array} inputs - The list of input properties to process
75
+ * @param {array} indexes - The list of indexes to update
76
+ */
77
+ async function findAllProps (schema, inputs = [], indexes = []) {
78
+ const { isPlainObject, cloneDeep } = this.app.lib._
79
+ const isIdProp = inputs.find(p => {
80
+ return isPlainObject(p) ? p.name === 'id' : p.startsWith('id,')
81
+ })
82
+ if (!isIdProp) {
83
+ const idField = cloneDeep(schema.connection.adapter.idField)
84
+ idField.name = 'id'
85
+ inputs.unshift(idField)
86
+ }
87
+ for (const prop of inputs) {
88
+ await sanitizeProp.call(this, schema, prop, indexes)
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Applies a feature to a model schema, adding properties, rules, hooks, and other
94
+ * configurations as defined by the feature.
95
+ * @param {object} schema - The model schema
96
+ * @param {object} feature - The feature to apply
97
+ * @param {object} options - The options for the feature
98
+ * @param {array} indexes - The list of indexes to update
99
+ */
100
+ async function applyFeature (schema, feature, options, indexes) {
101
+ const { isArray, findIndex } = this.app.lib._
102
+ if (feature.name === 'dobo:unique' &amp;&amp; options.field === 'id') {
103
+ const idx = findIndex(schema.properties, { name: 'id' })
104
+ if (idx > -1) schema.properties.pullAt(idx)
105
+ }
106
+ const item = await feature.handler(options)
107
+ if (item.rules) schema.rules.push(...item.rules)
108
+ if (item.scanables) schema.scanables.push(...item.scanables)
109
+ if (!isArray(item.properties)) item.properties = [item.properties]
110
+ for (const prop of item.properties) {
111
+ prop.feature = `${feature.plugin.ns}:${feature.name}`
112
+ await sanitizeProp.call(this, schema, prop, indexes)
113
+ }
114
+ if (item.hooks) {
115
+ item.hooks = item.hooks.map(hook => {
116
+ hook.level = hook.level ?? 999
117
+ return hook
118
+ })
119
+ schema.hooks.push(...item.hooks)
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Finds and applies all features for a given model schema, ensuring that each feature is properly processed
125
+ * @param {object} schema - The model schema
126
+ * @param {array} inputs - The list of features to apply
127
+ * @param {array} indexes - The list of indexes to update
128
+ */
129
+ async function findAllFeats (schema, inputs = [], indexes = []) {
130
+ const { isString, omit } = this.app.lib._
131
+ for (let feat of inputs) {
132
+ if (isString(feat)) feat = { name: feat }
133
+ const featName = feat.name.indexOf(':') === -1 ? `dobo:${feat.name}` : feat.name
134
+ const feature = this.app.dobo.getFeature(featName)
135
+ if (!feature) this.fatal('invalidFeature%s%s', schema.name, featName)
136
+ await applyFeature.call(this, schema, feature, omit(feat, 'name'), indexes)
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Finds and applies all indexes for a given model schema, ensuring that each index is properly processed
142
+ * @param {object} schema - The model schema
143
+ * @param {array} inputs - The list of indexes to apply
144
+ * @param {array} indexes - The list of existing indexes to update
145
+ */
146
+ async function findAllIndexes (schema, inputs = [], indexes = []) {
147
+ const items = []
148
+ for (const index of inputs) {
149
+ index.type = index.type ?? 'index'
150
+ index.fields = index.fields ?? []
151
+ if (!index.name) index.name = `${schema.name}_${index.fields.join('_')}_${index.type}`
152
+ items.push(index)
153
+ }
154
+ schema.indexes = [...items, ...indexes]
155
+ }
156
+
157
+ /**
158
+ * Sanitizes the references in a model schema, ensuring that all references point to valid models and properties.
159
+ * It checks for duplicate reference keys and validates the existence of referenced models and properties.
160
+ * @async
161
+ * @param {object} schema - The model schema to sanitize
162
+ * @param {object[]} schemas - The list of all model schemas
163
+ * @returns {Promise&lt;void>}
164
+ */
165
+ export async function sanitizeRef (schema, schemas) {
166
+ const { find, isString, pullAt } = this.app.lib._
167
+ const _refKeys = []
168
+ for (const prop of schema.properties) {
169
+ const ignored = []
170
+ for (const key in prop.ref ?? {}) {
171
+ _refKeys.push(key)
172
+ let ref = prop.ref[key]
173
+ if (isString(ref)) {
174
+ ref = { field: ref }
175
+ }
176
+ ref.field = ref.field ?? 'id'
177
+ ref.type = ref.type ?? '1:1'
178
+ ref.searchField = ref.searchField ?? ref.field
179
+ ref.labelField = ref.labelField ?? ref.searchField
180
+ const rModel = find(schemas, { name: ref.model })
181
+ if (!rModel) {
182
+ ignored.push(key)
183
+ this.log.warn('notFound%s%s', this.t('model'), ref.model)
184
+ continue
185
+ }
186
+ const rProp = find(rModel.properties, { name: ref.field })
187
+ if (!rProp) {
188
+ ignored.push(key)
189
+ this.log.warn('notFound%s%s', this.t('property'), `${ref.field}@${ref.model}`)
190
+ continue
191
+ }
192
+ ref.fields = ref.fields ?? '*'
193
+ if (['*', 'all'].includes(ref.fields)) ref.fields = rModel.properties.map(p => p.name)
194
+ if (ref.fields.length > 0 &amp;&amp; !ref.fields.includes('id')) ref.fields.unshift('id')
195
+ const removed = []
196
+ for (const idx in ref.fields) {
197
+ const p = find(rModel.properties, { name: ref.fields[idx] })
198
+ if (!p) removed.push(ref.fields[idx])
199
+ }
200
+ pullAt(ref.fields, removed)
201
+ prop.ref[key] = ref
202
+ }
203
+ for (const key of ignored) {
204
+ delete prop.ref[key]
205
+ }
206
+ }
207
+ const dupes = _refKeys.filter((item, index) => _refKeys.indexOf(item) !== index)
208
+ if (dupes.length > 0) throw this.error('duplicateRefKeys%s%s', schema.name, dupes.join(', '))
209
+ }
210
+
211
+ /**
212
+ * Sanitizes all model schemas, ensuring that properties, indexes, and references are properly defined and validated.
213
+ * It also determines the sortable fields based on the defined indexes.
214
+ * @async
215
+ * @param {object} schema - The model schema
216
+ * @returns {Promise&lt;void>}
217
+ */
218
+ export async function sanitizeAll (schema) {
219
+ const { runHook } = this.app.bajo
220
+ const { pick, keys, map, uniq, camelCase, filter } = this.app.lib._
221
+ const { defaultsDeep } = this.app.lib.aneka
222
+ const allPropNames = uniq(map(schema.properties, 'name'))
223
+ const propType = this.constructor.propertyType
224
+ const indexTypes = this.constructor.indexTypes
225
+
226
+ await runHook(`dobo.${camelCase(schema.name)}:beforeSanitizeModel`, schema)
227
+ // properties
228
+ for (const idx in schema.properties) {
229
+ let prop = schema.properties[idx]
230
+ const def = propType[prop.type]
231
+ prop = pick(defaultsDeep(prop, def), this.getPropertyKeysByType(prop.type))
232
+ if (!keys(propType).includes(prop.type)) this.fatal('unknownPropType%s%s', `${prop.name}.${def.name}`, prop.type)
233
+ if (prop.type === 'string') {
234
+ prop.minLength = parseInt(prop.minLength) ?? 0
235
+ prop.maxLength = parseInt(prop.maxLength) ?? 255
236
+ if (prop.minLength > 0) prop.required = true
237
+ if (prop.minLength === 0) delete prop.minLength
238
+ }
239
+ schema.properties[idx] = prop
240
+ }
241
+ // indexes
242
+ for (const index of schema.indexes) {
243
+ if (!indexTypes.includes(index.type)) this.fatal('unknownIndexType%s%s', index.type, schema.name)
244
+ for (const field of index.fields) {
245
+ if (!allPropNames.includes(field)) this.fatal('unknownPropNameOnIndex%s%s', field, schema.name)
246
+ }
247
+ }
248
+ await runHook(`dobo.${camelCase(schema.name)}:afterSanitizeModel`, schema)
249
+ // sorting only possible using these fields
250
+ schema.sortables = []
251
+ for (const index of schema.indexes) {
252
+ schema.sortables.push(...index.fields)
253
+ }
254
+ schema.hidden = filter(uniq(schema.hidden), prop => allPropNames.includes(prop))
255
+ }
256
+
257
+ /**
258
+ * Creates a model schema by sanitizing its properties, features, and indexes, and ensuring that all references are valid.
259
+ * It also applies any buildStart and buildEnd handlers defined in the schema.
260
+ * @param {object} item - The model definition object
261
+ * @returns {object} - The sanitized model schema
262
+ */
263
+ async function createSchema (item) {
264
+ const { find, orderBy, get } = this.app.lib._
265
+ const { mergeObjectsByKey, defaultsDeep, parseObject } = this.app.lib.aneka
266
+ const feats = item.features ?? []
267
+ const props = item.properties ?? []
268
+ const indexes = item.indexes ?? []
269
+ item.features = []
270
+ item.properties = []
271
+ item.indexes = []
272
+ item.hidden = item.hidden ?? []
273
+ item.rules = item.rules ?? []
274
+ item.buildLevel = item.buildLevel ?? 999
275
+ item.hooks = item.hooks ?? []
276
+ item.disabled = item.disabled ?? []
277
+ item.scanables = item.scanables ?? []
278
+ if (item.disabled === 'all') item.disabled = ['find', 'get', 'create', 'update', 'remove']
279
+ else if (item.disabled === 'readonly') item.disabled = ['create', 'update', 'remove']
280
+ const conn = item.connection ?? 'default'
281
+ if (!(conn instanceof this.app.baseClass.DoboConnection)) {
282
+ item.connection = null
283
+ // Is there any overwritten connection?
284
+ const newConn = find(this.connections, c => c.options.models.includes(item.name))
285
+ if (newConn) item.connection = newConn
286
+ else {
287
+ item.connection = this.getConnection(conn, true)
288
+ if (!item.connection &amp;&amp; conn === 'default') item.connection = this.getConnection('memory')
289
+ }
290
+ if (!item.connection) this.fatal('unknownConn%s%s', conn, item.name)
291
+ }
292
+ // cache settings
293
+ const defCache = defaultsDeep({}, item.connection.options.cache, get(this, 'app.bajoCache.config.default', this.config.default.cache))
294
+ if (item.cache === false) item.cache = { ttlDur: 0 }
295
+ else if (item.cache === true) item.cache = defCache
296
+ else item.cache = defaultsDeep({}, item.cache, defCache)
297
+ item.cache = parseObject(item.cache)
298
+ if (item.connection.name === 'memory') item.cache.ttlDur = 0
299
+
300
+ // let's run
301
+ await findAllProps.call(this, item, props, indexes)
302
+ await findAllFeats.call(this, item, feats, indexes)
303
+ await findAllIndexes.call(this, item, indexes)
304
+ for (const key of ['properties', 'indexes']) {
305
+ item[key] = mergeObjectsByKey(item[key], 'name')
306
+ }
307
+ item.hooks = orderBy(item.hooks, ['name', 'level'])
308
+ delete item.features
309
+ await sanitizeAll.call(this, item)
310
+ return item
311
+ }
312
+
313
+ /**
314
+ * Collects all model schemas from the application, sanitizes them, and creates model instances.
315
+ * It also handles any buildStart and buildEnd handlers defined in the model definitions.
316
+ * @async
317
+ * @method
318
+ * @returns {Promise&lt;void>}
319
+ */
320
+ export async function collectModels () {
321
+ const { eachPlugins, callHandler } = this.app.bajo
322
+ const { orderBy, has, omit } = this.app.lib._
323
+ await actionFactory.call(this)
324
+ await modelFactory.call(this)
325
+
326
+ this.log.trace('collecting%s', this.t('model'))
327
+ const me = this
328
+ let schemas = []
329
+ await eachPlugins(async function ({ file }) {
330
+ const { readConfig, callHandler } = this.app.bajo
331
+ const { pascalCase } = this.app.lib.aneka
332
+ const { isPlainObject, isEmpty, isArray } = this.app.lib._
333
+
334
+ let items = await readConfig(file, { ns: this.ns, baseNs: me.ns, merge: true })
335
+ if (isEmpty(items)) return undefined
336
+ if (isPlainObject(items)) {
337
+ items.baseName = items.baseName ?? path.basename(file, path.extname(file))
338
+ items.name = items.name ?? pascalCase(`${this.alias} ${items.baseName}`)
339
+ }
340
+ if (!isArray(items)) items = [items]
341
+ for (const item of items) {
342
+ if (!item.baseName) me.fatal('missing%s%s', 'baseName', file)
343
+ item.name = item.name ?? pascalCase(`${this.alias} ${item.baseName}`)
344
+ me.log.trace('- %s', item.name)
345
+ item.collName = item.collName ?? item.name
346
+ item.options = item.options ?? {}
347
+ item.options.attachment = item.options.attachment ?? true
348
+ item.options.persistence = item.options.persistence ?? true
349
+ item.ns = this.ns
350
+ if (item.buildStart) await callHandler(this, item.buildStart, item)
351
+ const schema = await createSchema.call(me, item)
352
+ schemas.push(schema)
353
+ }
354
+ }, { glob: ['model/*.*', 'model.*'], prefix: this.ns })
355
+ schemas = orderBy(schemas, ['buildLevel', 'name'])
356
+ for (const schema of schemas) {
357
+ const idProp = schema.properties.find(p => p.name === 'id')
358
+ if (!this.constructor.idTypes.includes(idProp.type)) this.fatal('invalidIdType%s%s', schema.name, this.constructor.idTypes.join(', '))
359
+ if (idProp.type === 'string' &amp;&amp; !has(idProp, 'maxLength')) idProp.maxLength = 50
360
+ const plugin = this.app[schema.ns]
361
+ await sanitizeRef.call(this, schema, schemas)
362
+ for (const item of schema.indexes) {
363
+ for (const field of item.fields) {
364
+ const prop = schema.properties.find(p => p.name === field)
365
+ if (!prop || (prop &amp;&amp; prop.virtual)) throw this.error('virtualFieldIn%s%s%s', field, 'index', schema.name)
366
+ }
367
+ }
368
+ for (const field of schema.scanables) {
369
+ const prop = schema.properties.find(p => p.name === field)
370
+ if (!prop || (prop &amp;&amp; prop.virtual)) throw this.error('virtualFieldIn%s%s%s', field, 'scanable', schema.name)
371
+ }
372
+ const model = new this.app.baseClass.DoboModel(plugin, omit(schema, ['beforeCreate', 'afterCreate']))
373
+ me.models.push(model)
374
+ if (schema.buildEnd) await callHandler(plugin, schema.buildEnd, model)
375
+ }
376
+ schemas = []
377
+ this.log.debug('collected%s%d', this.t('model'), this.models.length)
378
+ }
379
+
380
+ /**
381
+ * Collects all model features from loaded plugins
382
+ * @async
383
+ * @method
384
+ * @returns {Promise&lt;void>}
385
+ */
386
+ export async function collectFeatures () {
387
+ const { eachPlugins } = this.app.bajo
388
+ await featureFactory.call(this)
389
+
390
+ this.log.trace('collecting%s', this.t('feature'))
391
+ const me = this
392
+ await eachPlugins(async function ({ file }) {
393
+ const { importModule } = this.app.bajo
394
+ const { camelCase, isFunction } = this.app.lib._
395
+
396
+ const name = camelCase(path.basename(file, '.js'))
397
+ const handler = await importModule(file)
398
+ if (!isFunction(handler)) this.fatal('invalidFeatureHandler%s%s', this.ns, name)
399
+ me.features.push(new this.app.baseClass.DoboFeature(this, { name, handler }))
400
+ me.log.trace('- %s:%s', this.ns, name)
401
+ }, { glob: 'feature/*.js', prefix: this.ns })
402
+ this.log.debug('collected%s%d', this.t('feature'), this.features.length)
403
+ }
404
+
405
+ /**
406
+ * Collects all database connections from loaded plugins, initializes their adapters, and ensures that a default connection is available.
407
+ * It also handles any memory-based connections and merges their models into a single memory connection.
408
+ * @async
409
+ * @method
410
+ * @returns {Promise&lt;void>}
411
+ */
412
+ export async function collectConnections () {
413
+ const { buildCollections } = this.app.bajo
414
+ const { pullAt } = this.app.lib._
415
+ const { filterIndex } = this.app.lib.aneka
416
+ await connectionFactory.call(this)
417
+
418
+ async function handler ({ item }) {
419
+ const { has } = this.app.lib._
420
+ if (!has(item, 'adapter')) this.fatal('unknownDbAdapter%s')
421
+ const conn = new this.app.baseClass.DoboConnection(this, item)
422
+ await conn.initAdapter(item.adapter)
423
+ return conn
424
+ }
425
+ const memIndexes = filterIndex(this.config.connections, current => current.adapter === 'dobo:memory' || current.name === 'memory')
426
+ const models = memIndexes.map(idx => [...(this.config.connections[idx].models ?? [])])
427
+ pullAt(this.config.connections, memIndexes)
428
+ this.config.connections.push({
429
+ adapter: 'dobo:memory',
430
+ name: 'memory',
431
+ models
432
+ })
433
+ this.connections = await buildCollections({ ns: this.ns, container: 'connections', handler, dupChecks: ['name'] })
434
+ const defConn = this.connections.find(conn => conn.name === 'default')
435
+ if (!defConn) this.log.warn('noDefaultConnection')
436
+ }
437
+
438
+ /**
439
+ * Collects all database adapters from loaded plugins.
440
+ * @async
441
+ * @method
442
+ * @returns {Promise&lt;void>}
443
+ */
444
+ export async function collectAdapters () {
445
+ const { eachPlugins, runHook } = this.app.bajo
446
+ const { importModule } = this.app.bajo
447
+ const { camelCase, isFunction } = this.app.lib._
448
+ await adapterFactory.call(this)
449
+
450
+ this.log.trace('collecting%s', this.t('adapter'))
451
+ const me = this
452
+ await runHook(`${this.ns}:beforeCollectAdapters`)
453
+ await eachPlugins(async function ({ file }) {
454
+ const name = camelCase(path.basename(file, '.js'))
455
+ const factory = await importModule(file)
456
+ if (!isFunction(factory)) this.fatal('invalidAdapterClassFactory%s%s', this.ns, name)
457
+ const Cls = await factory.call(this)
458
+ const instance = new Cls(this, name)
459
+ if (!(instance instanceof this.app.baseClass.DoboAdapter)) this.fatal('invalidAdapterClass%s%s', this.ns, name)
460
+ me.adapters.push(instance)
461
+ me.log.trace('- %s:%s', this.ns, name)
462
+ }, { glob: 'adapter/*.js', prefix: this.ns })
463
+ await runHook(`${this.ns}:afterCollectAdapters`)
464
+ this.log.debug('collected%s%d', this.t('adapter'), this.adapters.length)
465
+ }
466
+ </code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><a href="/" class="sidebar-title sidebar-title-anchor">Dobo API</a><div class="mobile-nav-links"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/dobo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/dobo" target="">Github</a></div><div class="navbar-item"><a id="" href="https://dobo.bajo.app/" target="">Dobo</a></div><div class="navbar-item"><a id="" href="https://bajo.app/" target="">Bajo</a></div></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="Dobo.html">Dobo</a></div><div class="sidebar-section-children"><a href="DoboAction.html">DoboAction</a></div><div class="sidebar-section-children"><a href="DoboAdapter.html">DoboAdapter</a></div><div class="sidebar-section-children"><a href="DoboConnection.html">DoboConnection</a></div><div class="sidebar-section-children"><a href="DoboFeature.html">DoboFeature</a></div><div class="sidebar-section-children"><a href="DoboModel.html">DoboModel</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-Helper.html">Helper</a></div><div class="sidebar-section-children"><a href="module-Helper_Model.html">Helper/Model</a></div><div class="sidebar-section-children"><a href="module-Hook.html">Hook</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="external-Tools.html">Tools</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#actionFactory">actionFactory</a></div><div class="sidebar-section-children"><a href="global.html#adapterFactory">adapterFactory</a></div><div class="sidebar-section-children"><a href="global.html#connectionFactory">connectionFactory</a></div><div class="sidebar-section-children"><a href="global.html#featureFactory">featureFactory</a></div><div class="sidebar-section-children"><a href="global.html#modelFactory">modelFactory</a></div><div class="sidebar-section-children"><a href="global.html#pluginFactory">pluginFactory</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>
@@ -0,0 +1,3 @@
1
+ <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Module: Helper</title><!--[if lt IE 9]>
2
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
+ <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="light"><div class="sidebar-container"><div class="sidebar" id="sidebar"><a href="/" class="sidebar-title sidebar-title-anchor">Dobo API</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="Dobo.html">Dobo</a></div><div class="sidebar-section-children"><a href="DoboAction.html">DoboAction</a></div><div class="sidebar-section-children"><a href="DoboAdapter.html">DoboAdapter</a></div><div class="sidebar-section-children"><a href="DoboConnection.html">DoboConnection</a></div><div class="sidebar-section-children"><a href="DoboFeature.html">DoboFeature</a></div><div class="sidebar-section-children"><a href="DoboModel.html">DoboModel</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-Helper.html">Helper</a></div><div class="sidebar-section-children"><a href="module-Helper_Model.html">Helper/Model</a></div><div class="sidebar-section-children"><a href="module-Hook.html">Hook</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="external-Tools.html">Tools</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#actionFactory">actionFactory</a></div><div class="sidebar-section-children"><a href="global.html#adapterFactory">adapterFactory</a></div><div class="sidebar-section-children"><a href="global.html#connectionFactory">connectionFactory</a></div><div class="sidebar-section-children"><a href="global.html#featureFactory">featureFactory</a></div><div class="sidebar-section-children"><a href="global.html#modelFactory">modelFactory</a></div><div class="sidebar-section-children"><a href="global.html#pluginFactory">pluginFactory</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/dobo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/dobo" target="">Github</a></div><div class="navbar-item"><a id="" href="https://dobo.bajo.app/" target="">Dobo</a></div><div class="navbar-item"><a id="" href="https://bajo.app/" target="">Bajo</a></div></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section><header></header><article><div class="container-overview"></div><h2 id="methods" class="subsection-title has-anchor">Methods</h2><h3 class="name has-anchor" id=".collectAdapters"><span class="type-signature">(async, static) </span>collectAdapters<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Collects all database adapters from loaded plugins.</p></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line442">line 442</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id=".collectConnections"><span class="type-signature">(async, static) </span>collectConnections<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Collects all database connections from loaded plugins, initializes their adapters, and ensures that a default connection is available. It also handles any memory-based connections and merges their models into a single memory connection.</p></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line410">line 410</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id=".collectFeatures"><span class="type-signature">(async, static) </span>collectFeatures<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Collects all model features from loaded plugins</p></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line384">line 384</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id=".collectModels"><span class="type-signature">(async, static) </span>collectModels<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Collects all model schemas from the application, sanitizes them, and creates model instances. It also handles any buildStart and buildEnd handlers defined in the model definitions.</p></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line318">line 318</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id=".sanitizeAll"><span class="type-signature">(async, static) </span>sanitizeAll<span class="signature">(schema)</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Sanitizes all model schemas, ensuring that properties, indexes, and references are properly defined and validated. It also determines the sortable fields based on the defined indexes.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line216">line 216</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id=".sanitizeRef"><span class="type-signature">(async, static) </span>sanitizeRef<span class="signature">(schema, schemas)</span><span class="type-signature"> &rarr; {Promise.&lt;void>}</span></h3><div class="description"><p>Sanitizes the references in a model schema, ensuring that all references point to valid models and properties. It checks for duplicate reference keys and validates the existence of referenced models and properties.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema to sanitize</p></td></tr><tr><td class="name"><code>schemas</code></td><td class="type"><span class="param-type">Array.&lt;object></span></td><td class="description last"><p>The list of all model schemas</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line163">line 163</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">Promise.&lt;void></span></dd></dl></div><h3 class="name has-anchor" id="~applyFeature"><span class="type-signature">(async, inner) </span>applyFeature<span class="signature">(schema, feature, options, indexes)</span></h3><div class="description"><p>Applies a feature to a model schema, adding properties, rules, hooks, and other configurations as defined by the feature.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema</p></td></tr><tr><td class="name"><code>feature</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The feature to apply</p></td></tr><tr><td class="name"><code>options</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The options for the feature</p></td></tr><tr><td class="name"><code>indexes</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of indexes to update</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line98">line 98</a></li></ul></dd></div></dl><h3 class="name has-anchor" id="~createSchema"><span class="type-signature">(async, inner) </span>createSchema<span class="signature">(item)</span><span class="type-signature"> &rarr; {object}</span></h3><div class="description"><p>Creates a model schema by sanitizing its properties, features, and indexes, and ensuring that all references are valid. It also applies any buildStart and buildEnd handlers defined in the schema.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>item</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model definition object</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line261">line 261</a></li></ul></dd></div></dl><div class="method-member-container mt-20"><strong>Returns:</strong><div class="param-desc"><ul><li>The sanitized model schema</li></ul></div><dl class="param-type"><dt>Type:&nbsp;</dt><dd><span class="param-type">object</span></dd></dl></div><h3 class="name has-anchor" id="~findAllFeats"><span class="type-signature">(async, inner) </span>findAllFeats<span class="signature">(schema, inputs, indexes)</span></h3><div class="description"><p>Finds and applies all features for a given model schema, ensuring that each feature is properly processed</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema</p></td></tr><tr><td class="name"><code>inputs</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of features to apply</p></td></tr><tr><td class="name"><code>indexes</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of indexes to update</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line127">line 127</a></li></ul></dd></div></dl><h3 class="name has-anchor" id="~findAllIndexes"><span class="type-signature">(async, inner) </span>findAllIndexes<span class="signature">(schema, inputs, indexes)</span></h3><div class="description"><p>Finds and applies all indexes for a given model schema, ensuring that each index is properly processed</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema</p></td></tr><tr><td class="name"><code>inputs</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of indexes to apply</p></td></tr><tr><td class="name"><code>indexes</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of existing indexes to update</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line144">line 144</a></li></ul></dd></div></dl><h3 class="name has-anchor" id="~findAllProps"><span class="type-signature">(async, inner) </span>findAllProps<span class="signature">(schema, inputs, indexes)</span></h3><div class="description"><p>Finds and sanitizes all properties for a given model schema, ensuring that the 'id' property is included and that all properties are properly processed.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>schema</code></td><td class="type"><span class="param-type">object</span></td><td class="description last"><p>The model schema</p></td></tr><tr><td class="name"><code>inputs</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of input properties to process</p></td></tr><tr><td class="name"><code>indexes</code></td><td class="type"><span class="param-type">array</span></td><td class="description last"><p>The list of indexes to update</p></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line75">line 75</a></li></ul></dd></div></dl><h3 class="name has-anchor" id="~sanitizeProp"><span class="type-signature">(async, inner) </span>sanitizeProp<span class="signature">(model, prop, indexes)</span></h3><div class="description"><p>Sanitizes a property definition for a model, ensuring it adheres to the expected structure and types. It handles various property attributes such as type, index, required status, and more.</p><p>If the property is virtual, it processes it accordingly; otherwise, it adds it to the model's properties and indexes.</p></div><div class="method-member-container flex flex-col w-100 overflow-auto mt-20"><strong>Parameters:</strong><table class="params"><thead><tr><th>Name</th><th>Type</th><th class="last">Description</th></tr></thead><tbody><tr><td class="name"><code>model</code></td><td class="type"><span class="param-type"><a href="DoboModel.html">DoboModel</a></span></td><td class="description last"></td></tr><tr><td class="name"><code>prop</code></td><td class="type"><span class="param-type">DoboModel.<wbr>TProperty</span></td><td class="description last"></td></tr><tr><td class="name"><code>indexes</code></td><td class="type"><span class="param-type">Array.&lt;DoboModel.TIndex></span></td><td class="description last"></td></tr></tbody></table></div><dl class="details"><div class="details-item-container"><dt class="tag-source bold">Source</dt><dd class="tag-source"><ul><li><a href="lib_helper.js.html">lib/helper.js</a>, <a href="lib_helper.js.html#line22">line 22</a></li></ul></dd></div></dl></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><a href="/" class="sidebar-title sidebar-title-anchor">Dobo API</a><div class="mobile-nav-links"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/dobo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/dobo" target="">Github</a></div><div class="navbar-item"><a id="" href="https://dobo.bajo.app/" target="">Dobo</a></div><div class="navbar-item"><a id="" href="https://bajo.app/" target="">Bajo</a></div></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="Dobo.html">Dobo</a></div><div class="sidebar-section-children"><a href="DoboAction.html">DoboAction</a></div><div class="sidebar-section-children"><a href="DoboAdapter.html">DoboAdapter</a></div><div class="sidebar-section-children"><a href="DoboConnection.html">DoboConnection</a></div><div class="sidebar-section-children"><a href="DoboFeature.html">DoboFeature</a></div><div class="sidebar-section-children"><a href="DoboModel.html">DoboModel</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-Helper.html">Helper</a></div><div class="sidebar-section-children"><a href="module-Helper_Model.html">Helper/Model</a></div><div class="sidebar-section-children"><a href="module-Hook.html">Hook</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="external-Tools.html">Tools</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#actionFactory">actionFactory</a></div><div class="sidebar-section-children"><a href="global.html#adapterFactory">adapterFactory</a></div><div class="sidebar-section-children"><a href="global.html#connectionFactory">connectionFactory</a></div><div class="sidebar-section-children"><a href="global.html#featureFactory">featureFactory</a></div><div class="sidebar-section-children"><a href="global.html#modelFactory">modelFactory</a></div><div class="sidebar-section-children"><a href="global.html#pluginFactory">pluginFactory</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>