bajo 2.23.0 → 2.25.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 (108) hide show
  1. package/.jsdoc.conf.json +2 -1
  2. package/class/app.js +220 -107
  3. package/class/bajo.js +257 -177
  4. package/class/base.js +85 -24
  5. package/class/cache.js +8 -16
  6. package/class/err.js +31 -10
  7. package/class/log.js +46 -38
  8. package/class/plugin.js +53 -30
  9. package/class/print.js +18 -15
  10. package/class/tools.js +17 -7
  11. package/docs/App.html +51 -1
  12. package/docs/Bajo.html +1 -1
  13. package/docs/Base.html +34 -1
  14. package/docs/Cache.html +1 -1
  15. package/docs/Err.html +2 -2
  16. package/docs/Log.html +2 -2
  17. package/docs/Main.html +3 -0
  18. package/docs/Plugin.html +1 -1
  19. package/docs/Print.html +1 -1
  20. package/docs/Tools.html +1 -1
  21. package/docs/class_app.js.html +222 -109
  22. package/docs/class_bajo.js.html +260 -179
  23. package/docs/class_base.js.html +87 -26
  24. package/docs/class_cache.js.html +10 -18
  25. package/docs/class_err.js.html +33 -12
  26. package/docs/class_log.js.html +48 -40
  27. package/docs/class_plugin.js.html +55 -32
  28. package/docs/class_print.js.html +20 -17
  29. package/docs/class_tools.js.html +19 -9
  30. package/docs/data/search.json +1 -1
  31. package/docs/global.html +22 -1
  32. package/docs/index.html +1 -1
  33. package/docs/index.js.html +53 -16
  34. package/docs/lib_applet-hook.js.html +328 -0
  35. package/docs/lib_config.js.html +167 -0
  36. package/docs/lib_helper.js.html +186 -192
  37. package/docs/module-Applet.html +3 -0
  38. package/docs/module-Helper.html +1 -8
  39. package/docs/module-Hook.html +1 -1
  40. package/docs/tutorial-01_WELCOME.html +3 -0
  41. package/docs/tutorial-02_GETTING_STARTED.html +125 -0
  42. package/docs/tutorial-03_USER_GUIDE.html +54 -0
  43. package/docs/tutorial-04_DEV_GUIDE.html +178 -0
  44. package/docs/tutorial-05_ECOSYSTEM.html +3 -0
  45. package/extend/bajo/intl/en-US.json +2 -1
  46. package/extend/bajo/intl/id.json +2 -1
  47. package/index.js +51 -14
  48. package/lib/applet-hook.js +325 -0
  49. package/lib/config.js +164 -0
  50. package/lib/helper.js +185 -191
  51. package/package.json +6 -2
  52. package/test/00-global-hooks.test.js +44 -0
  53. package/test/e2e/_run.js +19 -0
  54. package/test/e2e/e2e-applet-process.test.js +66 -0
  55. package/test/e2e/e2e-boot-process.test.js +62 -0
  56. package/test/e2e/e2e-hooks-process.test.js +68 -0
  57. package/test/integration/_setup.js +55 -0
  58. package/test/integration/aspect-01-boot-instance.test.js +24 -0
  59. package/test/integration/aspect-02-plugin-loading.test.js +24 -0
  60. package/test/integration/aspect-03-config-merge.test.js +27 -0
  61. package/test/integration/aspect-04-intl-loading.test.js +29 -0
  62. package/test/integration/aspect-05-cache-roundtrip.test.js +26 -0
  63. package/test/integration/aspect-06-log-file-save.test.js +28 -0
  64. package/test/integration/aspect-07-plugin-data-dir.test.js +25 -0
  65. package/test/integration/aspect-08-plugin-lookup.test.js +25 -0
  66. package/test/integration/aspect-09-config-formats.test.js +26 -0
  67. package/test/integration/aspect-10-hooks.test.js +38 -0
  68. package/test/unit/app.test.js +115 -0
  69. package/test/unit/applet-hook.test.js +10 -0
  70. package/test/unit/bajo.test.js +151 -0
  71. package/test/unit/base.test.js +90 -0
  72. package/test/unit/cache.test.js +89 -0
  73. package/test/unit/config.test.js +14 -0
  74. package/test/unit/err.test.js +57 -0
  75. package/test/unit/helper.test.js +116 -0
  76. package/test/unit/index.test.js +40 -0
  77. package/test/unit/log.test.js +84 -0
  78. package/test/unit/plugin.test.js +95 -0
  79. package/test/unit/print.test.js +72 -0
  80. package/test/unit/tools.test.js +29 -0
  81. package/wiki/CHANGES.md +10 -0
  82. package/wiki/tutorials/01_WELCOME.md +18 -0
  83. package/wiki/tutorials/02_GETTING_STARTED.md +366 -0
  84. package/wiki/tutorials/03_USER_GUIDE.md +262 -0
  85. package/wiki/tutorials/04_DEV_GUIDE.md +386 -0
  86. package/wiki/tutorials/05_ECOSYSTEM.md +95 -0
  87. package/wiki/tutorials/tutorials.json +17 -0
  88. package/docs/lib_hook.js.html +0 -231
  89. package/docs/module-Lib.html +0 -3
  90. package/lib/hook.js +0 -228
  91. package/test/app.test.js +0 -183
  92. package/test/bajo.test.js +0 -124
  93. package/test/base.test.js +0 -75
  94. package/test/cache.test.js +0 -94
  95. package/test/e2e.test.js +0 -137
  96. package/test/err.test.js +0 -73
  97. package/test/helper.test.js +0 -39
  98. package/test/import-module.test.js +0 -138
  99. package/test/integration.test.js +0 -218
  100. package/test/log.test.js +0 -119
  101. package/test/plugin.test.js +0 -116
  102. package/test/print.test.js +0 -100
  103. package/test/tools.test.js +0 -38
  104. package/wiki/CONFIG.md +0 -36
  105. package/wiki/DEV_GUIDE.md +0 -3
  106. package/wiki/ECOSYSTEM.md +0 -93
  107. package/wiki/GETTING-STARTED.md +0 -356
  108. package/wiki/USER-GUIDE.md +0 -256
@@ -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>Tutorial: Welcome</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">Bajo API</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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><h2>Welcome</h2></header><article><h1 id="welcome-to-bajo">Welcome to Bajo</h1><p>Welcome to Bajo, <strong>the ultimate framework for whipping up a massive app in no time!</strong></p><p>Bajo is a framework that allows you to build apps with ease, whether it's a command line app or web app of any size. It is designed to be simple, yet powerful, and can be used for a wide range of applications.</p><p>Bajo grew out of the need for a framework that:</p><ul><li>is easy to use and understand even for beginners.</li><li>is modular and extensible. It's like playing with Lego blocks, you can build anything you want by combining different plugins with each other.</li><li>is plug &amp; play, yet easy to customize through configurations only. Less code is always better.</li><li>is fast and efficient, yet easy to scale.</li><li>and last but not least: so much magic! Many people will be critical about it, but hey, who doesn't like magic?</li></ul><p>In Bajo philosophy, everything is a plugin. A plugin should be handling a single responsibility, and can be extended by other plugins. This allows for a very flexible and modular architecture, where you can easily add or remove features as needed.</p><p>A typical Bajo app should be able to run within a few minutes: create a new project directory, create <code>package.json</code> file, create a <a href="global.html#boot">boot file</a>, install as many plugins as you want, done! Yes, it's that simple.</p><p>Now dive in to the tutorials to learn more about Bajo and how to use it to build your next app.</p></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">Bajo API</a><div class="mobile-nav-links"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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,125 @@
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>Tutorial: Getting Started</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">Bajo API</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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><h2>Getting Started</h2></header><article><h1 id="getting-started">Getting Started</h1><p>Welcome! In this guide, we will take our first steps with Bajo together.</p><p>If this is your first time working with this framework, that is completely fine. We will move step by step: installation, project structure, basic configuration, and your first small app. Along the way, you will also meet two important ideas in Bajo: plugins and hook/lifecycle.</p><p>By the end of this tutorial, you should feel comfortable enough to continue to Bajo's sub-frameworks, such as Dobo and Waibu.</p><h2 id="installation">Installation</h2><p>First, create a new empty directory named <code>my-project</code>. We will use this as the app directory throughout the tutorial. Then, move into that directory with <code>cd</code> and run:</p><pre class="prettyprint source lang-bash"><code>$ npm init
4
+ </code></pre><p>You will be asked for information such as project name, description, and author. Continue until the <em>package.json</em> file is created.</p><p>Next, open that file in your editor and add the following lines:</p><pre class="prettyprint source lang-javascript"><code>...
5
+ &quot;type&quot;: &quot;module&quot;,
6
+ &quot;bajo&quot;: {
7
+ &quot;type&quot;: &quot;app&quot;
8
+ },
9
+ ...
10
+ </code></pre><p>After that, install Bajo:</p><pre class="prettyprint source lang-bash"><code>$ npm install bajo
11
+ </code></pre><p>Now create a bootstrap file named <code>index.js</code> and add:</p><pre class="prettyprint source lang-javascript"><code>// index.js file
12
+ import { boot } from 'bajo'
13
+ await boot()
14
+ </code></pre><p>A Bajo app <strong>always</strong> needs a data directory for configuration files and related resources. This directory can be inside or outside your app directory.</p><p>If the directory does not exist yet, Bajo will ask you whether to create one automatically or to abort. If you decide to create it, Bajo will make a directory named <code>data</code>, next to your <code>index.js</code> file. By default, this becomes your data directory.</p><p>Now run your app:</p><pre class="prettyprint source lang-bash"><code>$ node index.js
15
+ </code></pre><p>Great work. Your first Bajo app is now running.</p><h2 id="playing-around">Playing Around</h2><p>At this point, your project structure should look like this:</p><pre class="prettyprint source"><code>.
16
+ └── my-project
17
+ ├── data
18
+ │ └── config
19
+ ├── main
20
+ │ └── index.js
21
+ ├── node_modules
22
+ │ └── ...
23
+ ├── index.js
24
+ ├── package.json
25
+ └── package-lock.json
26
+ </code></pre><p>Bajo automatically creates a <code>main</code> plugin for you. This is the main plugin of your app, and it is where you will put your code.</p><p>By default, the app runs in the <code>dev</code> environment. In this mode, the log level is set to <code>debug</code>. You can override it using program arguments to something like <code>trace</code>, which is the most verbose level, and some other options:</p><pre class="prettyprint source lang-bash"><code>$ node index.js --log-level=trace --log-timeTaken --log-pretty
27
+ </code></pre><p>You should now see more colorful logs, including timing information for each step. This is very useful for debugging and for finding slow parts of the startup process.</p><p>Typing arguments every time can feel repetitive, so let's move those settings into a config file. Create <code>data/config/bajo.yml</code> and add:</p><pre class="prettyprint source lang-yaml"><code>env: dev
28
+ log:
29
+ pretty: true
30
+ level: trace
31
+ timeTaken: true
32
+ </code></pre><blockquote><p>If you like JSON, you can also use <code>bajo.json</code> instead of <code>bajo.yml</code>. Bajo supports both formats.</p></blockquote><p>Now try running the app again without extra arguments:</p><pre class="prettyprint source lang-bash"><code>$ node index.js
33
+ </code></pre><p>Much easier.</p><p>You can combine config values, program arguments, environment variables, and even use a dotenv file (<code>.env</code>) whenever needed. For a deeper explanation, please see the <em>User Guide</em>.</p><h2 id="your-first-project">Your First Project</h2><p>Now let's build a simple <strong>Hello World</strong> example, Bajo style.</p><p>Our goals are:</p><ol><li>Read values from configuration.</li><li>Copy those values into plugin properties during initialization.</li><li>Display the values while the app is running.</li><li>Print a message when the app exits.</li></ol><p>Let's begin.</p><h3 id="config-object">Config Object</h3><p>Open <code>data/config/main.yml</code> (or create it if it does not exist). This is the configuration file for the main plugin.</p><p>Add:</p><pre class="prettyprint source lang-yaml"><code>firstName: Tanjiro
34
+ lastName: Kamado
35
+ age: 15
36
+ </code></pre><p>Each Bajo plugin can read its configuration from <code>{dataDir}/config/{ns}.yml</code>, where <code>{dataDir}</code> is your data directory and <code>{ns}</code> is the plugin namespace or name. You can read more in the <a href="tutorial-03_USER_GUIDE.html">User Guide</a>.</p><p>In Bajo, most features are built through plugins. For small projects, using the built-in <code>main</code> plugin is usually enough. As your project grows, you can split responsibilities into smaller independent plugins.</p><p>If you want to build your own plugin, please continue with the <a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a>.</p><h3 id="plugin-factory">Plugin Factory</h3><p>Now open <code>main/index.js</code> and update it like this:</p><p>This file is your main plugin factory. Bajo creates it automatically when needed.</p><pre class="prettyprint source lang-javascript"><code>async function factory (pkgName) {
37
+ const me = this
38
+
39
+ return class Main extends this.app.baseClass.Base {
40
+ constructor () {
41
+ super(pkgName, me.app)
42
+ this.config = {}
43
+ }
44
+
45
+ // start adding these lines
46
+ init = async () => {
47
+ this.firstName = this.config.firstName
48
+ this.lastName = this.config.lastName
49
+ this.age = this.config.age
50
+ }
51
+
52
+ start = async () => {
53
+ this.log.info('First name: %s, Last name: %s, age: %d', this.firstName, this.lastName, this.age)
54
+ }
55
+
56
+ exit = async () => {
57
+ this.log.warn('Program aborted')
58
+ }
59
+ // end of added lines
60
+ }
61
+ }
62
+
63
+ export default factory
64
+ </code></pre><p>Here is what happens during the lifecycle:</p><ul><li>During boot, the main plugin reads <code>main.yml</code> and merges it with matching program arguments and environment variables to build the plugin's configuration object.</li><li>Next, initialization runs through main plugin <code>init</code> method. In this example, we copy values from <code>this.config</code> into plugin properties.</li><li>Then the plugin starts through the <code>start</code> method, where we print the values to the logger.</li><li>Finally, when the app exits, the <code>exit</code> method runs.</li></ul><p>This is the standard lifecycle pattern for all Bajo plugins, including the special main plugin.</p><p>But if you run it now, you will likely get an error. The reason is that keys from the config file (<code>firstName</code>, <code>lastName</code>, and <code>age</code>) are not yet declared in <code>this.config</code>, so they are ignored during initialization.</p><p>Let's fix that by defining default values first:</p><pre class="prettyprint source lang-javascript"><code>...
65
+ constructor () {
66
+ super(pkgName, me.app)
67
+ this.config = {
68
+ firstName: 'John',
69
+ lastName: 'Doe',
70
+ age: 50
71
+ }
72
+ }
73
+ ...
74
+ </code></pre><p>The <code>this.config</code> object in the constructor acts as the default configuration. During startup, Bajo merges it with values from configuration files or program options. If any key is missing in the file, the default value is used.</p><p>Run the app again, and this time let's keep output concise with:</p><pre class="prettyprint source lang-bash"><code>$ node index.js --log-level=info
75
+ 2025-09-12T00:09:38.946Z +97ms INFO: main First name: Tanjiro, Last name: Kamado, age: 15
76
+ 2025-09-12T00:09:38.949Z +3ms WARN: main Program aborted
77
+ </code></pre><p>Nice!</p><h2 id="the-hook-system">The Hook System</h2><h3 id="tapping-a-hook">Tapping a Hook</h3><p>Bajo has a very powerful, yet so simple hook system so you can add custom behavior at specific moments. We will start with a simple case: running code right after boot completes.</p><p>Create <code>main/extend/bajo/hook/bajo@after-boot.js</code>. If the naming looks unusual, that is expected; please read <a href="module-Hook.html">module:Hook</a> file naming instructions for more.</p><pre class="prettyprint source lang-javascript"><code>async function afterBootComplete () {
78
+ this.log.info('Hook after boot complete')
79
+ }
80
+
81
+ export default afterBootComplete
82
+ </code></pre><p>That is your first hook listener. It taps into the <code>bajo:afterBoot</code> hook, which runs after the boot process completes. You can check the full list of hooks <a href="module-Hook.html">here</a>.</p><h3 id="your-own-hook">Your Own Hook</h3><p>Now let's write your own custom hook. For this small example it may feel too over the top, but it shows how flexible Bajo can be.</p><p>This time, we will update all properties through a hook.</p><p>Open <code>index.js</code> and update it like this:</p><pre class="prettyprint source lang-javascript"><code>...
83
+ init = async () => {
84
+ const { runHook } = this.app.bajo // add this line
85
+ this.firstName = this.config.firstName
86
+ this.lastName = this.config.lastName
87
+ this.age = this.config.age
88
+ await runHook('main:myHook') // and this line
89
+ }
90
+ ...
91
+ </code></pre><p>This will add a hook named <code>main:myHook</code> during app boot.</p><p>Now create a new file as the hook listener for the hook you just created: <code>main/extend/bajo/hook/main@my-hook.js</code></p><pre class="prettyprint source lang-javascript"><code>async function myHook () {
92
+ // 'this' is bound to the owner plugin, that is the main plugin in this case
93
+ this.lastName = 'THE Daemon Slayer'
94
+ }
95
+
96
+ export default myHook
97
+ </code></pre><p>In Bajo, class methods, hooks, and handlers run within its plugin scope, so setting <code>this.lastName</code> directly inside the hook is enough.</p><p>Run the app again. You should see output similar to this:</p><pre class="prettyprint source lang-bash"><code>2025-09-12T12:09:09.004Z +115ms INFO: main First name: Tanjiro, Last name: THE Daemon Slayer, age: 15
98
+ 2025-09-12T12:09:09.008Z +4ms INFO: main Hook after boot complete
99
+ 2025-09-12T12:09:09.009Z +1ms WARN: main Program aborted
100
+ </code></pre><p>As you can see, <code>this.lastName</code> was updated by the hook successfully. You can also see the <code>afterBoot</code> hook running after the main plugin starts.</p><h2 id="using-external-plugins">Using External Plugins</h2><p>Bajo is designed as an ecosystem of small plugins. You can think of them like building blocks: combine the ones you need to create your own app behavior.</p><p>In this section, we will use plugins to extend the app.</p><h3 id="toml-file-format">TOML File Format</h3><p>Let's switch the configuration format to TOML.</p><ol><li>TOML support is provided by the <code>bajo-config</code> plugin, so install it first:<pre class="prettyprint source lang-bash"><code>$ npm install bajo-config
101
+ </code></pre></li><li>Open <code>data/config/.plugins</code> and add <code>bajo-config</code> in it. If the file does not exist yet, create it first. Plugin order is usually resolved automatically by Bajo.</li><li>Remove <code>data/config/main.yml</code> and create <code>data/config/main.toml</code>.</li><li>Add the same object as before, now in TOML:<pre class="prettyprint source"><code>firstName = &quot;Tanjiro&quot;
102
+ lastName = &quot;Kamado&quot;
103
+ age = 15
104
+ </code></pre></li><li>Run the app and check the result. It should match the previous behavior, except for different timestamps.</li></ol><h3 id="applet-mode">Applet Mode</h3><p><strong>Applets</strong> are small tools embedded within plugins that run when Bajo is in <strong>applet mode</strong>. They have their own lifecycle, separate from the main program, but they can still reuse shared resources and config.</p><p>To run Bajo in applet mode, use <code>--applet</code> or <code>-a</code>:</p><pre class="prettyprint source lang-bash"><code>$ node index.js -a
105
+ </code></pre><p>Applet mode needs <code>bajo-cli</code>, so install it first:</p><pre class="prettyprint source lang-bash"><code>$ npm install bajo-cli
106
+ </code></pre><p>Then add <code>bajo-cli</code> to the <code>data/config/.plugins</code> file. Again, plugin order is not a concern in this case.</p><p>If you run it now, your terminal may show something like this:</p><pre class="prettyprint source lang-bash"><code>ℹ App runs in applet mode
107
+ ? Please select: (Use arrow keys)
108
+ ❯ bajoConfig
109
+ bajoCli
110
+ </code></pre><p>Notice that the app reports it is running in applet mode. The interface becomes an interactive CLI view, and regular logs are hidden.</p><p>By default, logs are disabled in applet mode to keep the console clean. During debugging, you can enable logs again by adding <code>--log-applet</code> to your command.</p><p>Applets are optional utilities provided by plugin authors, so it could be the case that some plugins have many applets in it while others have none.</p><h3 id="system-info">System Info</h3><p>Now let's install one more plugin: <code>bajo-sysinfo</code>. It is a thin wrapper over <a href="https://github.com/sebhildebrandt/systeminformation">systeminformation</a> with a few helpful additions:</p><ul><li>It can be called directly as an applet.</li><li>It is also exposed as Waibu REST API endpoints. We will cover it much later.</li></ul><p>If you run the app like this (yes, <code>--applet</code> can take a value; details are <a href="module-Applet.html">here</a>, you may see output like the following after loading:</p><pre class="prettyprint source lang-bash"><code>$ node index.js -a bajoSysinfo:battery
111
+ ℹ App runs in applet mode
112
+ ℹ Done!
113
+ ┌──────────────────┬─────────────────────┐
114
+ │ hasBattery │ true │
115
+ ├──────────────────┼─────────────────────┤
116
+ │ cycleCount │ 0 │
117
+ ├──────────────────┼─────────────────────┤
118
+ │ isCharging │ true │
119
+ ├──────────────────┼─────────────────────┤
120
+ │ designedCapacity │ 61998 │
121
+ ├──────────────────┼─────────────────────┤
122
+ │ maxCapacity │ 51686 │
123
+ ├──────────────────┼─────────────────────┤
124
+ ...
125
+ </code></pre><h2 id="more">More</h2><p>Bajo offers much more beyond this tiny introduction. When you are ready, continue with these sub-framework guides below. In the mean time, please feel free to also explore the <a href="tutorial-03_USER_GUIDE.html">User Guide</a> and <a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a>.</p><ul><li><a href="https://github.com/ardhi/dobo/wiki/GETTING-STARTED.md">Dobo DBMS</a></li><li><a href="https://github.com/ardhi/waibu/wiki/GETTING-STARTED.md">Waibu Web Framework</a></li><li><a href="https://github.com/ardhi/sumba/wiki/GETTING-STARTED.md">Sumba Biz Suites</a></li><li><a href="https://github.com/ardhi/masohi/wiki/GETTING-STARTED.md">Masohi Messaging</a></li></ul></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">Bajo API</a><div class="mobile-nav-links"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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,54 @@
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>Tutorial: User Guide</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">Bajo API</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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><h2>User Guide</h2></header><article><h1 id="user-guide">User Guide</h1><h2 id="overview">Overview</h2><h3 id="definitions">Definitions</h3><p>Before we go any further, let's define some terms that will be used throughout this guide:</p><ol><li><code>{appDir}</code> - The application directory, which is the root directory of your Bajo app. This is where all your application files reside, and it is typically the directory where you run your app from.</li><li><code>{dataDir}</code> - The data directory, which is where Bajo stores its configuration files, plugin data, and other persistent information. By default, this is a subdirectory named <code>data</code> within your <code>{appDir}</code>.</li><li><code>{tmpDir}</code> - The temporary directory, which is where Bajo stores temporary files and caches. By default, Bajo will simply use the system's temporary directory, but you can configure it to be a directory of your choice.</li><li><code>{pkgName}</code> - The plugin's package name, that is the name in <code>package.json</code>, typically matching its npm listing.</li><li><code>{ns}</code>: The plugin namespace or name for short, which is the camel-cased version of the package name.</li><li><code>{mainNs}</code> - The special plugin's <code>main</code> namespace and directory named <code>main</code> within your <code>{appDir}</code>; this is where all application code should be written. It is created automatically if it doesn't exist yet.</li></ol><h3 id="directory-structure">Directory Structure</h3><p>Your typical Bajo app directory structure should look like this:</p><pre class="prettyprint source"><code>.
4
+ └── {appDir}
5
+ ├── {dataDir}
6
+ │ ├── config
7
+ │ │ ├── .plugin
8
+ │ │ ├── bajo.yml
9
+ │ │ ├── main.yml
10
+ │ │ └── ...
11
+ │ └── plugins
12
+ │ └── ...
13
+ ├── main
14
+ │ ├── extend
15
+ │ │ └── ...
16
+ │ ├── index.js
17
+ │ └── ...
18
+ ├── package.json
19
+ ├── index.js
20
+ └── ...
21
+ </code></pre><p>This to note:</p><ol><li>You can move <code>{dataDir}</code> out of <code>{appDir}</code> if you want, but you need to tell Bajo where to find it. For more on this, please follow along.</li><li><code>{dataDir}</code> should be the only place Bajo <strong>writes</strong> anything. Bajo and its plugins should <strong>never</strong> be allowed to write anything outside <code>{dataDir}</code> on their own.</li><li><code>config</code> is a special directory within <code>{dataDir}</code> where your configuration files should reside. Inside this directory, you should find:<ul><li>a special file named <code>.plugins</code> that tells Bajo which plugins should be loaded</li><li>a file named <code>bajo.yml</code> to override global settings</li><li>all plugin-specific config files, named after their namespace</li><li>you can use <code>.json</code> if you prefer, but <code>.yml</code> is recommended for better readability</li></ul></li><li>The <code>main</code> directory, or <code>{mainNs}</code> namespace, is the <a href="Main.html">special plugin</a> where you put your application code. And yes, it is actually a normal Bajo plugin! This means everything in there will be handled just like a regular plugin like it has the ability to extend other plugins, has its own config file, and more — with a few differences:<ul><li>it's always available and can't be disabled</li><li>it's always the last one to start</li><li>if this directory is missing, it will be created automatically on startup</li><li>if the plugin's factory function is missing (<code>index.js</code>), it will be created dynamically</li><li><a href="Main.html">click here</a> for more details about the <code>main</code> plugin</li></ul></li><li><code>index.js</code> is the main entry point for your app.</li></ol><p>To set your <code>{dataDir}</code> somewhere else, you need to tell Bajo where to find it by using an argument switch.</p><p>Assuming your data directory is <code>my-data-dir</code> at the same level as your app directory, run your app like this:</p><pre class="prettyprint source lang-bash"><code>$ node index.js --dir-data=../my-data-dir
22
+ </code></pre><p>If using program arguments seems a bit like a hassle for you, just use Bajo's <a href="https://github.com/motdotla/dotenv">dotenv</a> support. Create a <code>.env</code> file in your app directory and put this inside:</p><pre class="prettyprint source lang-text"><code>DIR__DATA=../my-data-dir # double underscores!!!
23
+ </code></pre><p>From now on, you can start the app just by typing:</p><pre class="prettyprint source lang-bash"><code>$ node index.js
24
+ </code></pre><h3 id="runtime">Runtime</h3><p>Bajo should run perfectly fine on Node.js version 20 or higher. Using the latest stable runtime is recommended. Bajo-based apps are also known to run with <strong>Bun</strong> without any problems. But Bajo <strong>cannot</strong> run on Deno due to its heavy reliance on Node.js-specific libraries and environments.</p><p>Bajo is a pure ES6 framework that utilizes dynamic imports <code>a lot</code>. Running on a system with a fast disk (e.g., SSD) and enough RAM is highly recommended, especially when you load a lot of plugins.</p><h2 id="configuration">Configuration</h2><h3 id="general-rules">General Rules</h3><ul><li>All configuration files must be placed in the <code>{dataDir}/config</code> subfolder.</li><li>Config files must be named after their plugin namespace.</li><li>The file format should be either <code>.yml</code>, <code>.json</code> or <code>.js</code>. If a <code>.js</code> file is used, it must be in ES6 format and should export either a plain JavaScript object or a function. Both synchronous and asynchronous functions are supported. If it returns a function, this function will be called within its plugin scope and should return a plain JS object.</li><li>Other formats e.g. <code>.toml</code> can also be used by installing and loading the <a href="https://ardhi.github.io/bajo-config">bajoConfig</a> plugin.</li><li>The order of precedence is <code>.js</code> &gt; <code>.json</code> &gt; <code>.yml</code> &gt; <code>.toml</code>. This means that if a <code>.js</code> file exists, it will be used instead of a <code>.json</code> file or any other format.</li></ul><p>Example: bajo.yml</p><pre class="prettyprint source lang-yaml"><code>env: prod
25
+ log:
26
+ pretty: true
27
+ timeTaken: true
28
+ lang: id
29
+ </code></pre><h3 id="using-plugins">Using Plugins</h3><p>Plugins are what make the Bajo Framework so great and flexible: they extend app features and functionalities!</p><p>To use plugins, follow these steps:</p><ol><li>Install it with <code>npm install {pkgName}</code>, where <code>{pkgName}</code> is the plugin's package name. You can install as many plugins as you want; for a complete list of plugins, please <a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a>.</li><li>Optionally, create <code>{dataDir}/config/{ns}.yml</code> to customize the plugin's settings, where <code>{ns}</code> is the plugin namespace/name.</li><li>Open or create <code>{dataDir}/config/.plugins</code> and list the plugin's <code>{pkgName}</code> name in it, one per line. Use a <code>#</code> hash mark in front of the package name to disable it. The order of the plugins in this file is mostly NOT important, as Bajo will detect automatically.</li></ol><p>For example, the text below will load <code>bajo-config</code>, <code>bajo-extra</code>, and <code>bajo-template</code> plugins:</p><pre class="prettyprint source lang-text"><code># .plugin file
30
+ bajo-config
31
+ bajo-extra
32
+ bajo-template
33
+ </code></pre><p>If you later decide to disable one or more plugins, you just need to remove them from the <code>.plugins</code> file or place a <code>#</code> hash mark in front of the package name and restart your app.</p><blockquote><p><strong>Warning</strong>: Please do not confuse <code>{pkgName}</code> and <code>{ns}</code>. The plugin package name is the name of the JS package listed on npm, while <code>{ns}</code> is the plugin namespace or name for short, which is basically the camel-cased version of the plugin's package name.</p></blockquote><h3 id="environment-support">Environment Support</h3><p>Configuration file support for different environments is also available. All you need to do is create a <code>{ns}-{env}.yml</code> file in your <code>{dataDir}/config</code>, where:</p><ul><li><code>{ns}</code>: the namespace/plugin name</li><li><code>{env}</code>: your desired environment (<code>dev</code> or <code>prod</code>)</li></ul><p>App-wide settings with <code>bajo-{env}.yml</code> are also possible.</p><p>Bajo is smart enough to select which config file will be used based on the following order of precedence:</p><ol><li>Use <code>{ns}-{env}.yml</code> if the file exists.</li><li>If not, use <code>{ns}.yml</code>.</li><li>If that also doesn't exist, then use the plugin's default config values.</li></ol><h3 id="runtime-override">Runtime Override</h3><h4 id="environment-variables">Environment Variables</h4><p>You can easily override ANY key-value pair setting with environment variables and program argument switches. Bajo also supports <a href="https://github.com/motdotla/dotenv">dotenv</a> with a <code>.env</code> file.</p><p>The order of precedence is always: environment variable &gt; argument switches &gt; config files &gt; default, built-in values.</p><p>All values (whether they come from environment variables, argument switches, or config files) will be parsed using <a href="https://github.com/ladjs/dotenv-parse-variables">dotenv-parse-variables</a>, so please make sure you visit the repository to fully understand how it works.</p><ul><li>Create or open <code>{appDir}/.env</code></li><li>Use <code>__</code> (double underscores) as replacement for dots in an object.</li><li><code>DIR__DATA</code>: Sets the <code>{dataDir}</code> data directory.</li><li><code>DIR__TMP</code>: Sets <code>{tmpDir}</code> temporary directory.</li><li>For every key in <code>{ns|bajo}.yml</code>, use its snake-cased, upper-cased version, e.g.:<ul><li><code>env: 'prod'</code> → <code>ENV=prod</code></li><li><code>log.dateFormat: 'YYYY-MM-DD'</code> → <code>LOG__DATE_FORMAT=YYYY-MM-DD</code></li><li><code>exitHandler: true</code> → <code>EXIT_HANDLER=true</code></li></ul></li></ul><p>To override a plugin's config, prepend every key in the plugin's config with the snake-cased, upper-cased version of the namespace followed by a dot. For example:</p><ul><li><code>key</code> in <code>myPlugin</code> → <code>MY_PLUGIN.KEY=...</code></li><li><code>key.subKey.subSubKey</code> in <code>myPlugin</code> → <code>MY_PLUGIN.KEY__SUB_KEY__SUB_SUB_KEY=...</code></li></ul><p>Example:</p><pre class="prettyprint source lang-text"><code># .env file
34
+ ENV=prod
35
+ LOG__PRETTY=true
36
+ LOG__TIME_TAKEN=true
37
+ LANG=id
38
+ </code></pre><h4 id="argument-switches">Argument Switches</h4><p>You can also override ANY key-value pair setting with argument switches. This is especially useful when you want to run your app with different settings without changing the <code>.env</code> file or config files:</p><ul><li>Use switches, e.g.: <code>node index.js --xxx=one --yyy=two</code></li><li>Use <code>-</code> as the replacement for dots in an object.</li><li><code>--dir-data</code>: Sets the <code>{dataDir}</code> data directory.</li><li><code>--dir-tmp</code>: Sets the <code>{tmpDir}</code> temporary directory.</li><li>For every key in <code>{ns|bajo}.yml</code>, add <code>--</code> prefix. E.g.:<ul><li><code>env: 'prod'</code> → <code>--env=prod</code></li><li><code>log.dateFormat: 'YYYY-MM-DD'</code> → <code>--log-dateFormat=YYYY-MM-DD</code></li><li><code>exitHandler: true</code> → <code>--exitHandler</code></li></ul></li><li>To override a plugin's config, prepend every key in the plugin's config with the plugin name followed by a colon <code>:</code>. E.g.:<ul><li><code>key</code> in <code>myPlugin</code> → <code>--myPlugin:key=...</code></li><li><code>key.subKey.subSubKey</code> in <code>myPlugin</code> → <code>--myPlugin:key-subKey-subSubKey=...</code></li></ul></li></ul><p>Example:</p><pre class="prettyprint source lang-bash"><code>$ node index.js --env=prod --log-pretty --log-timeTaken --lang=id
39
+ </code></pre><h2 id="system-hook">System Hook</h2><p>A <strong>hook</strong> refers to a mechanism that allows you to inject a custom function to extend Bajo's functionality at specific points. These points are typically predefined by the framework, providing opportunities to execute code before, or after a particular operation.</p><h3 id="usage">Usage</h3><p>In Bajo, hooks can be created anywhere very easily. Simply call the <code>runHook</code> method followed by a number of parameters you want to pass or none at all. The hook name is always in the form of <a href="Bajo.html#.TNsPathPairs">Bajo.TNsPathPairs</a>, and represents the hook point any plugin can hook into.</p><p>You can then create a hook listener in your <code>main</code> plugin hook directory, which will be called when the hook is executed.</p><p>For more info, please read the <a href="module-Hook.html">here</a>.</p><p>Example:</p><ol><li><p>Somewhere in your JavaScript file, add the following code snippet:</p><pre class="prettyprint source lang-javascript"><code>const { runHook } = this.app.bajo
40
+ await runHook('main:sayHello', 'Don', 'Meri', { movie: 'Jumbo', year: 2025 })
41
+ </code></pre></li><li><p>Go to directory <code>{appDir}/main/extend/bajo/hook</code>. Create one if it doesn't exist yet.</p></li><li><p>Create file <code>main@say-hello.js</code> in the directory above.</p></li><li><p>Enter these lines:</p><pre class="prettyprint source lang-javascript"><code>async function sayHello (...params) {
42
+ const [mainChar, friend, payload] = params
43
+ console.log(mainChar, friend, payload) // output: Don, Meri, { movie: 'Jumbo', year: 2025 }
44
+ }
45
+
46
+ export default sayHello
47
+ </code></pre></li></ol><p>Note the hook name and its associated file name:</p><p><code>main:sayHello</code> → <code>main@say-hello.js</code></p><p>This is because a colon (<code>:</code>) is prohibited in a file name, so Bajo replaces it with the <code>@</code> symbol. And yes, the file name is case-sensitive and must match a correct hook name, so make sure you use the exact same name in both places. But you are also allowed to use the kebab-cased version of the hook name (in fact this is the recommended way to make your file name more readable).</p><p>During the boot process, Bajo will scan for hook files and load them into the app hook list. When your <code>runHook</code> is executed, Bajo will find its related hook from the list. If such a hook exists, its function handler will be called.</p><h3 id="anatomy">Anatomy</h3><p>Many times, there are more than one handler listening for a particular hook name. Especially in a framework that uses plugins extensively like Bajo, many plugins can listen to one hook at the same time. This creates a problem with call order.</p><p>To overcome this problem, Bajo gives you the opportunity to set a <code>level</code>. Function handlers with a lower level will be called earlier. Functions with no level will be assigned level <code>999</code> by default.</p><p>Now, change your <code>main@say-hello.js</code> file above to export an object instead of a function:</p><pre class="prettyprint source lang-javascript"><code>const sayHello = {
48
+ level: 10, // &lt;-- will get called earlier than any other handler with a higher level
49
+ handler: async function (...params) {
50
+ const [mainChar, friend, payload] = params
51
+ console.log(mainChar, friend, payload) // output: Don, Meri, { movie: 'Jumbo', year: 2025 }
52
+ }
53
+ }
54
+ </code></pre><h3 id="caveats">Caveats</h3><p>Hooks give you a lot of flexibility and freedom, but you need to be aware of the following caveats:</p><ol><li>You need to use an <strong>asynchronous</strong> function. Even if your function is synchronous, it will be called as an asynchronous one—and as you know, there is a performance degradation when using asynchronous operations</li><li><strong>Stay away</strong> from using <code>runHook</code> inside a hook! Even though it's possible, your code will become unreadable and messy pretty soon.</li><li>It's hard to trace errors in a hook. Because of its sequential nature, if a handler that's called earlier than yours throws an error, your hook won't be called at all.</li><li>If you use so many plugins that use the hook system so extensively with so many files, your app's boot time can take much longer than it's supposed to.</li></ol><p>Our advice is to <strong>use it wisely</strong>. Don't use hooks unless necessary; this will make your app or plugin clean and easy to understand.</p></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">Bajo API</a><div class="mobile-nav-links"><div class="navbar-item"><a id="" href="https://www.npmjs.com/package/bajo" target="">NPM</a></div><div class="navbar-item"><a id="" href="https://github.com/ardhi/bajo" target="">Github</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-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-01_WELCOME.html">Welcome</a></div><div class="sidebar-section-children"><a href="tutorial-02_GETTING_STARTED.html">Getting Started</a></div><div class="sidebar-section-children"><a href="tutorial-03_USER_GUIDE.html">User Guide</a></div><div class="sidebar-section-children"><a href="tutorial-04_DEV_GUIDE.html">Developer Guide</a></div><div class="sidebar-section-children"><a href="tutorial-05_ECOSYSTEM.html">Ecosystem</a></div></div><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="App.html">App</a></div><div class="sidebar-section-children"><a href="Bajo.html">Bajo</a></div><div class="sidebar-section-children"><a href="Base.html">Base</a></div><div class="sidebar-section-children"><a href="Cache.html">Cache</a></div><div class="sidebar-section-children"><a href="Err.html">Err</a></div><div class="sidebar-section-children"><a href="Log.html">Log</a></div><div class="sidebar-section-children"><a href="Main.html">Main</a></div><div class="sidebar-section-children"><a href="Plugin.html">Plugin</a></div><div class="sidebar-section-children"><a href="Print.html">Print</a></div><div class="sidebar-section-children"><a href="Tools.html">Tools</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-Applet.html">Applet</a></div><div class="sidebar-section-children"><a href="module-Helper.html">Helper</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-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#TConfig">TConfig</a></div><div class="sidebar-section-children"><a href="global.html#boot">boot</a></div><div class="sidebar-section-children"><a href="global.html#package%25C2%25B7json">package·json</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>