@underpostnet/cyberia 3.3.0 → 3.3.76

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 (568) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +17 -5
  3. package/.github/workflows/coverall.cyberia.ci.yml +39 -14
  4. package/.github/workflows/cyberia-client.cd.yml +5 -0
  5. package/.github/workflows/cyberia-server.cd.yml +5 -0
  6. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  7. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  8. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  9. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  10. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  11. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  12. package/.github/workflows/engine-cyberia.cd.yml +3 -0
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +35 -20
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +1 -0
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +96 -0
  22. package/CHANGELOG.md +653 -2513
  23. package/CLI-HELP.md +323 -157
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +5 -5
  27. package/README.md +48 -28
  28. package/bin/build.js +86 -41
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +1494 -1403
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +1494 -1403
  33. package/compose.env +17 -5
  34. package/conf.js +98 -7
  35. package/deploy/cyberia-client/deploy.sh +46 -0
  36. package/deploy/cyberia-client/package.sh +17 -0
  37. package/deploy/cyberia-client/state.sh +15 -0
  38. package/deploy/cyberia-server/deploy.sh +46 -0
  39. package/deploy/cyberia-server/package.sh +17 -0
  40. package/deploy/cyberia-server/state.sh +15 -0
  41. package/deploy/dd-cyberia/deploy.sh +9 -29
  42. package/deploy/dd-cyberia/init.sh +38 -45
  43. package/deploy/dd-cyberia/package.sh +16 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +133 -147
  46. package/deploy/lib/config.sh +29 -0
  47. package/deploy/lib/github-actions-logging.sh +610 -0
  48. package/deploy/lib/host.sh +194 -0
  49. package/deploy/lib/state.sh +65 -0
  50. package/deploy/pwa-microservices-template/deploy.sh +17 -42
  51. package/deploy/release/deploy.sh +9 -41
  52. package/deployment.yaml +7 -2
  53. package/docker-compose.yml +23 -17
  54. package/examples/static-page/README.md +19 -19
  55. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  56. package/hardhat/hardhat.config.js +1 -6
  57. package/hardhat/package-lock.json +101 -40
  58. package/hardhat/package.json +2 -2
  59. package/manifests/alertmanager/deployment.yaml +81 -0
  60. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  61. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
  62. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
  63. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  64. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  65. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  66. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  67. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  68. package/manifests/deployment/mongo-express/service.yaml +16 -0
  69. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  70. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  71. package/manifests/grafana/deployment.yaml +26 -7
  72. package/manifests/grafana/kustomization.yaml +1 -0
  73. package/manifests/grafana/service.yaml +6 -1
  74. package/manifests/mariadb/pv.yaml +1 -0
  75. package/manifests/mongodb/statefulset.yaml +9 -2
  76. package/manifests/mysql/pv-pvc.yaml +14 -1
  77. package/manifests/postgresql/pv.yaml +12 -1
  78. package/manifests/postgresql/pvc.yaml +1 -0
  79. package/manifests/prometheus/deployment.yaml +18 -22
  80. package/package.json +87 -12
  81. package/scripts/event-monitor.sh +56 -0
  82. package/scripts/k3s-node-setup.sh +27 -14
  83. package/scripts/kubeadm-node-setup.sh +31 -11
  84. package/scripts/maas-setup.sh +8 -8
  85. package/scripts/selinux-normalize.sh +907 -0
  86. package/scripts/shutdown-machine.sh +843 -0
  87. package/scripts/test-monitor.sh +5 -5
  88. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +15 -10
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +7 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +90 -186
  92. package/src/api/core/core.controller.js +1 -1
  93. package/src/api/core/core.router.js +2 -2
  94. package/src/api/core/core.service.js +2 -2
  95. package/src/api/crypto/crypto.controller.js +1 -1
  96. package/src/api/crypto/crypto.service.js +1 -1
  97. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  98. package/src/api/cyberia-action/cyberia-action.router.js +3 -3
  99. package/src/api/cyberia-action/cyberia-action.service.js +5 -6
  100. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  101. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  102. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  103. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  104. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +2 -4
  105. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  106. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +13 -35
  107. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +17 -34
  108. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  109. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  110. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
  111. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  112. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  113. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  114. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  115. package/src/api/cyberia-entity/cyberia-entity.service.js +3 -3
  116. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  117. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  118. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -2
  119. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +468 -5
  120. package/src/api/cyberia-instance/cyberia-fallback-capture.js +502 -0
  121. package/src/api/cyberia-instance/cyberia-fallback-world.js +29 -40
  122. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  123. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  124. package/src/api/cyberia-instance/cyberia-instance-map.service.js +35 -142
  125. package/src/api/cyberia-instance/cyberia-instance.controller.js +2 -5
  126. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  127. package/src/api/cyberia-instance/cyberia-instance.router.js +5 -18
  128. package/src/api/cyberia-instance/cyberia-instance.service.js +5 -45
  129. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  130. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  131. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  132. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  133. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +76 -3
  134. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  135. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  136. package/src/api/cyberia-map/cyberia-map.service.js +8 -4
  137. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  138. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  139. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  140. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  141. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  142. package/src/api/cyberia-quest/cyberia-quest.router.js +4 -4
  143. package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
  144. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  145. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  146. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  147. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  148. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  149. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  150. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  151. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -214
  152. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  153. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  154. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  155. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  156. package/src/api/default/default.controller.js +1 -1
  157. package/src/api/default/default.router.js +1 -1
  158. package/src/api/default/default.service.js +2 -2
  159. package/src/api/document/document.controller.js +1 -1
  160. package/src/api/document/document.router.js +1 -1
  161. package/src/api/document/document.service.js +2 -2
  162. package/src/api/file/file.controller.js +1 -1
  163. package/src/api/file/file.ref.js +153 -0
  164. package/src/api/file/file.ref.json +11 -2
  165. package/src/api/file/file.router.js +1 -1
  166. package/src/api/file/file.service.js +2 -2
  167. package/src/api/instance/instance.controller.js +1 -1
  168. package/src/api/instance/instance.router.js +1 -1
  169. package/src/api/instance/instance.service.js +2 -2
  170. package/src/api/ipfs/ipfs.controller.js +1 -1
  171. package/src/api/ipfs/ipfs.router.js +2 -2
  172. package/src/api/ipfs/ipfs.service.js +2 -2
  173. package/src/api/object-layer/object-layer.controller.js +1 -1
  174. package/src/api/object-layer/object-layer.model.js +47 -12
  175. package/src/api/object-layer/object-layer.router.js +12 -5
  176. package/src/api/object-layer/object-layer.service.js +116 -123
  177. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  178. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  179. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  180. package/src/api/test/test.controller.js +1 -1
  181. package/src/api/test/test.service.js +1 -1
  182. package/src/api/user/guest.service.js +3 -3
  183. package/src/api/user/user.controller.js +1 -1
  184. package/src/api/user/user.router.js +2 -2
  185. package/src/api/user/user.service.js +4 -4
  186. package/src/api.js +5 -9
  187. package/src/cli/app.js +402 -0
  188. package/src/cli/baremetal.js +30 -35
  189. package/src/cli/client.js +306 -0
  190. package/src/cli/cloud-init.js +3 -3
  191. package/src/cli/cluster.js +191 -82
  192. package/src/cli/db.js +120 -68
  193. package/src/cli/deploy.js +157 -75
  194. package/src/cli/docker-compose.js +5 -5
  195. package/src/cli/domains.js +184 -0
  196. package/src/cli/dotenv-store.js +143 -0
  197. package/src/cli/event.js +2281 -0
  198. package/src/cli/fs-selection.js +115 -0
  199. package/src/cli/fs.js +159 -343
  200. package/src/cli/host.js +672 -0
  201. package/src/cli/image.js +4 -6
  202. package/src/cli/index.js +343 -151
  203. package/src/cli/ipfs.js +34 -30
  204. package/src/cli/kickstart.js +1 -1
  205. package/src/cli/kubectl.js +218 -41
  206. package/src/cli/lxd.js +3 -3
  207. package/src/cli/monitor.js +1359 -26
  208. package/src/cli/package.js +90 -0
  209. package/src/cli/release.js +16 -12
  210. package/src/cli/repository.js +586 -363
  211. package/src/cli/run.js +398 -843
  212. package/src/cli/secrets.js +2158 -964
  213. package/src/cli/ssh.js +478 -279
  214. package/src/cli/state.js +394 -0
  215. package/src/cli/static.js +2 -2
  216. package/src/cli/system.js +1 -1
  217. package/src/cli/test.js +203 -125
  218. package/src/cli/vultr.js +61 -21
  219. package/src/cli/wireguard.js +1112 -306
  220. package/src/client/components/core/CalendarCore.js +53 -96
  221. package/src/client/components/core/Docs.js +327 -303
  222. package/src/client/components/core/FileExplorer.js +0 -21
  223. package/src/client/components/core/Modal.js +56 -1
  224. package/src/client/components/core/PanelForm.js +4 -4
  225. package/src/client/components/core/Repository.js +56 -0
  226. package/src/client/components/core/Translate.js +7 -0
  227. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  228. package/src/client/components/core/Wallet.js +0 -11
  229. package/src/client/components/core/Worker.js +7 -1
  230. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  231. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  232. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  233. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  234. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  235. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  236. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  237. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  238. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  239. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  240. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -35
  241. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  242. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  243. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  244. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  245. package/src/client/components/default/AppShellDefault.js +1 -1
  246. package/src/client/components/default/SettingsDefault.js +2 -2
  247. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  248. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  249. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  250. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  251. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +313 -30
  252. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  253. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  254. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  255. package/src/client/public/cyberia-docs/CYBERIA.md +48 -28
  256. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  257. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  258. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  259. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  260. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  261. package/src/client/public/default/android-chrome-144x144.png +0 -0
  262. package/src/client/public/default/android-chrome-192x192.png +0 -0
  263. package/src/client/public/default/android-chrome-256x256.png +0 -0
  264. package/src/client/public/default/android-chrome-36x36.png +0 -0
  265. package/src/client/public/default/android-chrome-384x384.png +0 -0
  266. package/src/client/public/default/android-chrome-48x48.png +0 -0
  267. package/src/client/public/default/android-chrome-512x512.png +0 -0
  268. package/src/client/public/default/android-chrome-72x72.png +0 -0
  269. package/src/client/public/default/android-chrome-96x96.png +0 -0
  270. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  271. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  272. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  273. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  274. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  275. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  276. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  277. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  278. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  279. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  280. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  281. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  282. package/src/client/public/default/apple-touch-icon.png +0 -0
  283. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  284. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  285. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  286. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  287. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  288. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  289. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  290. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  291. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  292. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  293. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  294. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  295. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  296. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  297. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  298. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  299. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  300. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  301. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  302. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  303. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  304. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  305. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  306. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  307. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  308. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  309. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  310. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  311. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  312. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  313. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  314. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  315. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  316. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  317. package/src/client/public/default/assets/background/white.jpg +0 -0
  318. package/src/client/public/default/browserconfig.xml +1 -1
  319. package/src/client/public/default/favicon-16x16.png +0 -0
  320. package/src/client/public/default/favicon-32x32.png +0 -0
  321. package/src/client/public/default/favicon-48x48.png +0 -0
  322. package/src/client/public/default/favicon.ico +0 -0
  323. package/src/client/public/default/manifest.webmanifest +5 -5
  324. package/src/client/public/default/mstile-144x144.png +0 -0
  325. package/src/client/public/default/mstile-150x150.png +0 -0
  326. package/src/client/public/default/mstile-310x150.png +0 -0
  327. package/src/client/public/default/mstile-310x310.png +0 -0
  328. package/src/client/public/default/mstile-70x70.png +0 -0
  329. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  330. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  331. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  332. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  333. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  334. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  335. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  336. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  337. package/src/client/services/object-layer/object-layer.management.js +6 -10
  338. package/src/client/services/object-layer/object-layer.service.js +3 -1
  339. package/src/client/ssr/RootDocument.js +1 -1
  340. package/src/client/ssr/body/404.js +1 -1
  341. package/src/client/ssr/body/500.js +1 -1
  342. package/src/client/ssr/body/CacheControl.js +1 -1
  343. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  344. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  345. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  346. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  347. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  348. package/src/client/ssr/head/Css.js +1 -1
  349. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  350. package/src/client/ssr/head/DefaultScripts.js +1 -1
  351. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  352. package/src/client/ssr/head/Microdata.js +1 -1
  353. package/src/client/ssr/head/Production.js +1 -1
  354. package/src/client/ssr/head/Pwa.js +1 -1
  355. package/src/client/ssr/head/PwaItemledger.js +1 -1
  356. package/src/client/ssr/head/Seo.js +1 -1
  357. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  358. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  359. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  360. package/src/client/ssr/views/Cyberia404.js +7 -5
  361. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  362. package/src/client/ssr/views/Maintenance.js +1 -1
  363. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  364. package/src/client/ssr/views/Test.js +1 -1
  365. package/src/client/sw/core.sw.js +20 -14
  366. package/src/client-builder/client-build-docs.js +92 -77
  367. package/src/client-builder/client-build-live.js +2 -2
  368. package/src/client-builder/client-build.js +105 -74
  369. package/src/client-builder/client-bundle.js +347 -0
  370. package/src/client-builder/client-dev-server.js +3 -3
  371. package/src/client-builder/client-icons.js +2 -2
  372. package/src/client-builder/ssr.js +3 -3
  373. package/src/client.build.js +3 -6
  374. package/src/client.dev.js +3 -6
  375. package/src/db/DataBaseProvider.js +186 -3
  376. package/src/db/mariadb/MariaDB.js +3 -2
  377. package/src/db/mongo/MongoBootstrap.js +273 -101
  378. package/src/db/mongo/MongoExpress.js +187 -0
  379. package/src/db/mongo/MongooseDB.js +7 -8
  380. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  381. package/src/grpc/cyberia/grpc-server.js +6 -8
  382. package/src/index.js +79 -23
  383. package/src/mailer/EmailRender.js +2 -2
  384. package/src/mailer/MailerInterceptor.js +87 -0
  385. package/src/mailer/MailerProvider.js +50 -6
  386. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +144 -147
  387. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  388. package/src/projects/cyberia/besu-genesis-generator.js +8 -17
  389. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  390. package/src/projects/cyberia/catalog-cyberia.js +54 -10
  391. package/src/projects/cyberia/gemini-client.js +4 -4
  392. package/src/projects/cyberia/generate-saga.js +5 -12
  393. package/src/projects/cyberia/hot-reload-trigger.js +18 -29
  394. package/src/projects/cyberia/instance-backup.js +210 -0
  395. package/src/projects/cyberia/instance-data.js +178 -258
  396. package/src/projects/cyberia/ipfs-client.js +4 -4
  397. package/src/projects/cyberia/map-preview-generator.js +33 -69
  398. package/src/projects/cyberia/object-layer.js +153 -320
  399. package/src/projects/cyberia/seed-audio.js +139 -0
  400. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  401. package/src/projects/cyberia/semantic-layer-generator.js +3 -19
  402. package/src/projects/cyberia/stat-balance.js +81 -0
  403. package/src/projects/cyberia/stat-commands.js +23 -0
  404. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  405. package/src/projects/underpost/catalog-underpost.js +9 -1
  406. package/src/proxy.js +4 -7
  407. package/src/runtime/cyberia-client/Dockerfile +17 -8
  408. package/src/runtime/cyberia-client/Dockerfile.dev +13 -4
  409. package/src/runtime/cyberia-server/Dockerfile +18 -6
  410. package/src/runtime/cyberia-server/Dockerfile.dev +16 -3
  411. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  412. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  413. package/src/runtime/engine-cyberia/Dockerfile.test +5 -5
  414. package/src/runtime/engine-cyberia/compose.env +17 -5
  415. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  416. package/src/runtime/express/Express.js +32 -27
  417. package/src/runtime/lampp/Lampp.js +22 -70
  418. package/src/runtime/nginx/Nginx.js +1 -1
  419. package/src/runtime/wp/Wp.js +16 -48
  420. package/src/server/{catalog.js → build/catalog.js} +15 -5
  421. package/src/server/build/coverage.js +188 -0
  422. package/src/server/build/execution.js +402 -0
  423. package/src/server/build/package.js +508 -0
  424. package/src/server/build/testing.js +578 -0
  425. package/src/server/{dns.js → network/dns.js} +144 -11
  426. package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
  427. package/src/server/{middlewares.js → network/middlewares.js} +11 -5
  428. package/src/server/network/node-capability.js +98 -0
  429. package/src/server/{peer.js → network/peer.js} +3 -3
  430. package/src/server/{proxy.js → network/proxy.js} +7 -13
  431. package/src/server/network/router.js +356 -0
  432. package/src/server/{tls.js → network/tls.js} +2 -2
  433. package/src/server/{underpost-compression.js → network/underpost-compression.js} +1 -1
  434. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
  435. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
  436. package/src/server/{cri.js → ops/cri.js} +2 -2
  437. package/src/server/{cron.js → ops/cron.js} +349 -74
  438. package/src/server/ops/event-notification.js +284 -0
  439. package/src/server/{logger.js → ops/logger.js} +143 -23
  440. package/src/server/ops/monitoring.js +1724 -0
  441. package/src/server/{systemd.js → ops/systemd.js} +55 -1
  442. package/src/server/{conf.js → runtime/conf.js} +516 -423
  443. package/src/server/runtime/config-scope.js +215 -0
  444. package/src/server/runtime/environment.js +149 -0
  445. package/src/server/{process.js → runtime/process.js} +153 -12
  446. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  447. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  448. package/src/server/{start.js → runtime/start.js} +128 -39
  449. package/src/server/{auth.js → security/auth.js} +7 -8
  450. package/src/server/security/container-storage.js +382 -0
  451. package/src/server/{crypto.js → security/crypto.js} +1 -1
  452. package/src/server/{selinux.js → security/selinux.js} +1 -1
  453. package/src/server/{backup.js → storage/backup.js} +17 -8
  454. package/src/server/{data-query.js → storage/data-query.js} +17 -1
  455. package/src/server/storage/downloader.js +121 -0
  456. package/src/server/storage/repository.js +68 -0
  457. package/src/server/storage/zip.js +153 -0
  458. package/src/server.js +4 -7
  459. package/src/ws/IoInterface.js +1 -1
  460. package/src/ws/IoServer.js +1 -1
  461. package/src/ws/core/core.ws.connection.js +1 -1
  462. package/src/ws/core/core.ws.emit.js +1 -1
  463. package/src/ws/core/core.ws.server.js +1 -1
  464. package/src/ws/default/default.ws.connection.js +1 -1
  465. package/src/ws/default/default.ws.emit.js +1 -1
  466. package/src/ws/default/default.ws.server.js +1 -1
  467. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  468. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  469. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  470. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  471. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  472. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  473. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +64 -0
  474. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  475. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  476. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +17 -23
  477. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  478. package/test/integration/app/cyberia/cyberia-load.test.js +466 -0
  479. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  480. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  481. package/test/integration/app/cyberia/fallback-world-capture.test.js +338 -0
  482. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  483. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  484. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  485. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  486. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  487. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  488. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  489. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  490. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  491. package/test/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
  492. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  493. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  494. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  495. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  496. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  497. package/test/integration/infra/2-network/wireguard-cli.test.js +1187 -0
  498. package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +649 -55
  499. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  500. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  501. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  502. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  503. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  504. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  505. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  506. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  507. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +6 -6
  508. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -4
  509. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  510. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  511. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  512. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  513. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  514. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  515. package/test/support/shell-harness.js +73 -0
  516. package/test/unit/build-template.test.js +97 -0
  517. package/test/unit/build-workflow-offline.test.js +132 -0
  518. package/test/unit/catalog.test.js +71 -0
  519. package/test/unit/client-build-docs.test.js +361 -0
  520. package/test/unit/client-bundle.test.js +313 -0
  521. package/test/unit/conf-loading.test.js +303 -0
  522. package/test/unit/conf-resolution.test.js +996 -0
  523. package/test/unit/coverage-artifact.test.js +221 -0
  524. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  525. package/test/unit/cyberia/instance-backup.test.js +183 -0
  526. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  527. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  528. package/test/unit/cyberia/stat-balance.test.js +69 -0
  529. package/test/unit/deploy-env-resolution.test.js +38 -0
  530. package/test/unit/deploy-log-table.test.js +518 -0
  531. package/test/unit/downloader-integrity.test.js +98 -0
  532. package/test/unit/execution-profiles.test.js +219 -0
  533. package/test/unit/file-reference-registry.test.js +141 -0
  534. package/test/unit/fleet-sync-source.test.js +149 -0
  535. package/test/unit/fs-storage-paths.test.js +596 -0
  536. package/test/unit/logger-redaction.test.js +141 -0
  537. package/test/unit/package.test.js +457 -0
  538. package/test/unit/prepare-host.test.js +382 -0
  539. package/test/unit/process-environment.test.js +18 -0
  540. package/test/unit/propagation-message.test.js +78 -0
  541. package/test/unit/redeploy-plan.test.js +24 -0
  542. package/test/unit/release-bump.test.js +474 -0
  543. package/test/unit/ssh-output-redaction.test.js +28 -0
  544. package/test/unit/start-options.test.js +46 -0
  545. package/test/unit/test-tiers.test.js +220 -0
  546. package/test/unit/zip-archive.test.js +142 -0
  547. package/vitest.config.js +66 -0
  548. package/.nycrc +0 -9
  549. package/deploy/lib/logging.sh +0 -96
  550. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  551. package/manifests/mongodb/pv-pvc.yaml +0 -59
  552. package/scripts/coverall-test-cyberia.sh +0 -24
  553. package/scripts/coverall-test.sh +0 -24
  554. package/scripts/link-local-underpost-cli.sh +0 -6
  555. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  556. package/src/api/user/user.build.js +0 -16
  557. package/src/cli/env.js +0 -177
  558. package/src/client/components/core/Blockchain.js +0 -41
  559. package/src/client/components/core/Blog.js +0 -9
  560. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  561. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
  562. package/src/client/public/default/assets/background/dark.jpg +0 -0
  563. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  564. package/src/client/public/default/assets/background/white0.jpg +0 -0
  565. package/src/client/public/doc/favicon.ico +0 -0
  566. package/src/client/public/doc/sitemap +0 -148
  567. package/src/server/downloader.js +0 -73
  568. package/src/server/environment.js +0 -98
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Mongo Express Deployment Module
3
+ * @module src/db/mongo/MongoExpress
4
+ * @namespace MongoExpress
5
+ * @description Deploys the mongo-express web client used to inspect the cluster's MongoDB
6
+ * StatefulSet collections. The workload is a plain Deployment plus a ClusterIP Service, so the
7
+ * same manifests converge identically under Kind, Kubeadm and K3s; the only runtime-dependent
8
+ * decision is whether the deployed mongod enforces authentication, which selects the overlay.
9
+ */
10
+
11
+ import { loggerFactory } from '../../server/ops/logger.js';
12
+ import { shellExec } from '../../server/runtime/process.js';
13
+ // Cyclic by construction (index -> cluster -> MongoExpress -> index), same as MongoBootstrap.js.
14
+ // Safe because the binding is only dereferenced inside method bodies, never at module scope.
15
+ import Underpost from '../../index.js';
16
+ import { MONGODB_DEFAULT_PORT, MONGODB_SERVICE_NAME, MONGODB_STATEFULSET_NAME } from './MongooseDB.js';
17
+
18
+ const logger = loggerFactory(import.meta);
19
+
20
+ const MONGO_EXPRESS_NAME = 'mongo-express';
21
+ const MONGO_EXPRESS_SERVICE_NAME = 'mongo-express-service';
22
+ const MONGO_EXPRESS_IMAGE = 'mongo-express:1.0.2';
23
+ const MONGO_EXPRESS_PORT = 8081;
24
+ const MONGO_EXPRESS_NODE_PORT = 32081;
25
+ const MONGO_EXPRESS_BASE_URL = '/mongo/';
26
+ // The UI reads the root credentials and gates its own session with the same pair, so it consumes
27
+ // the StatefulSet's secret rather than owning a second credential of its own.
28
+ const MONGO_EXPRESS_SECRET_NAME = 'mongodb-secret';
29
+ const MONGO_EXPRESS_MANIFEST_DIR = 'manifests/deployment/mongo-express';
30
+ const MONGO_EXPRESS_NO_AUTH_MANIFEST_DIR = 'manifests/deployment/mongo-express-no-auth';
31
+
32
+ // Literal and unescaped: kubectl's jsonpath quotes carry escape sequences of their own, and no
33
+ // mongod argument contains a pipe.
34
+ const MONGOD_ARGS_FIELD_SEPARATOR = '|';
35
+
36
+ /**
37
+ * Parses the mongod argument vector reported by `kubectl -o jsonpath` for the StatefulSet.
38
+ * @param {string} raw - Raw jsonpath stdout: the StatefulSet name, then one field per argument.
39
+ * @returns {Array<string>|null} Argument vector, or null when no StatefulSet was reported.
40
+ * @memberof MongoExpress
41
+ */
42
+ const parseMongodArgs = (raw) => {
43
+ const value = `${raw || ''}`;
44
+ if (!value.trim()) return null;
45
+ const [, ...args] = value.split(MONGOD_ARGS_FIELD_SEPARATOR);
46
+ return args.map((arg) => arg.trim()).filter(Boolean);
47
+ };
48
+
49
+ /**
50
+ * Decides whether mongo-express must authenticate against the deployed mongod.
51
+ *
52
+ * The deployed StatefulSet is the authority: `manifests/mongodb` starts mongod with `--auth` and
53
+ * `manifests/mongodb-4.4` does not, and either can be the one running regardless of which flag
54
+ * this invocation carries. The flags only answer for a cluster with no StatefulSet deployed yet,
55
+ * where `--mongodb` (the auth-enabled manifest set) is the default the platform installs.
56
+ * @param {object} [params={}] - Resolution inputs.
57
+ * @param {Array<string>|null} [params.args=null] - mongod argument vector, or null when undeployed.
58
+ * @param {object} [params.options={}] - Cluster options (`mongodb`, `mongodb4`).
59
+ * @returns {boolean} True when the admin credential pair must be projected.
60
+ * @memberof MongoExpress
61
+ */
62
+ const mongoAuthEnabledFactory = ({ args = null, options = {} } = {}) => {
63
+ if (Array.isArray(args)) return args.includes('--auth');
64
+ return options.mongodb4 !== true;
65
+ };
66
+
67
+ /**
68
+ * Resolves the kustomization root the auth mode selects.
69
+ * @param {object} [params={}] - Path inputs.
70
+ * @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
71
+ * @param {boolean} [params.authEnabled=true] - Whether mongod enforces authentication.
72
+ * @returns {string} Kustomization directory path.
73
+ * @memberof MongoExpress
74
+ */
75
+ const mongoExpressManifestPathFactory = ({ underpostRoot = '.', authEnabled = true } = {}) =>
76
+ `${underpostRoot}/${authEnabled ? MONGO_EXPRESS_MANIFEST_DIR : MONGO_EXPRESS_NO_AUTH_MANIFEST_DIR}`;
77
+
78
+ /**
79
+ * Resolves the opt-in NodePort Service manifest path. It lives in the base directory and is left
80
+ * out of both kustomizations: exposing an admin UI on the node network is a caller's decision.
81
+ * @param {object} [params={}] - Path inputs.
82
+ * @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
83
+ * @returns {string} NodePort manifest path.
84
+ * @memberof MongoExpress
85
+ */
86
+ const mongoExpressNodePortManifestFactory = ({ underpostRoot = '.' } = {}) =>
87
+ `${underpostRoot}/${MONGO_EXPRESS_MANIFEST_DIR}/mongo-express-nodeport.yaml`;
88
+
89
+ /**
90
+ * @class MongoExpress
91
+ * @description Static deployment surface for the mongo-express admin client.
92
+ * @memberof MongoExpress
93
+ */
94
+ class MongoExpress {
95
+ /**
96
+ * Reads the mongod argument vector from the deployed MongoDB StatefulSet.
97
+ *
98
+ * The projection leads with the StatefulSet name so a deployed server that declares no arguments
99
+ * stays distinguishable from no server at all — one is mongod on its defaults, the other is a
100
+ * cluster with no data tier yet, and both would otherwise reduce to empty output.
101
+ * @param {string} [namespace='default'] - Namespace holding the StatefulSet.
102
+ * @returns {Array<string>|null} Argument vector, or null when no StatefulSet is deployed.
103
+ * @memberof MongoExpress
104
+ */
105
+ static readMongodArgs(namespace = 'default') {
106
+ const raw = shellExec(
107
+ `kubectl get statefulset ${MONGODB_STATEFULSET_NAME} -n ${namespace} --ignore-not-found -o jsonpath=` +
108
+ `'{.metadata.name}{"${MONGOD_ARGS_FIELD_SEPARATOR}"}` +
109
+ `{range .spec.template.spec.containers[?(@.name=="${MONGODB_STATEFULSET_NAME}")].args[*]}` +
110
+ `{@}{"${MONGOD_ARGS_FIELD_SEPARATOR}"}{end}'`,
111
+ { stdout: true, silent: true, silentOnError: true },
112
+ );
113
+ return parseMongodArgs(raw);
114
+ }
115
+
116
+ /**
117
+ * Deploys mongo-express and, once it is Ready, applies the exposure and placement the caller
118
+ * asked for. Cluster-type agnostic by construction: only the image pull differs between Kind
119
+ * (loaded into the node's image store) and Kubeadm/K3s (pulled through the CRI).
120
+ * @param {object} [params={}] - Deployment parameters.
121
+ * @param {string} [params.namespace='default'] - Target namespace.
122
+ * @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
123
+ * @param {object} [params.options={}] - Cluster options (`pullImage`, `nodePort`, `nodeName`, `mongodb4`).
124
+ * @returns {Promise<boolean>} Whether the deployment reported Ready.
125
+ * @memberof MongoExpress
126
+ */
127
+ static async deploy({ namespace = 'default', underpostRoot = '.', options = {} } = {}) {
128
+ // Secret before workload: the Deployment's secretKeyRef must resolve at pod admission, and
129
+ // the encrypted store stays the source of truth wherever a manifest exists.
130
+ if (!Underpost.secret.applyIfPresent(MONGO_EXPRESS_SECRET_NAME, namespace))
131
+ Underpost.secret.applyFromOriginSeed(MONGO_EXPRESS_SECRET_NAME, namespace);
132
+
133
+ if (options.pullImage) Underpost.cluster.pullImage(MONGO_EXPRESS_IMAGE, options);
134
+
135
+ const args = MongoExpress.readMongodArgs(namespace);
136
+ const authEnabled = mongoAuthEnabledFactory({ args, options });
137
+ const manifestPath = mongoExpressManifestPathFactory({ underpostRoot, authEnabled });
138
+ logger.info('Deploying mongo-express', {
139
+ namespace,
140
+ authEnabled,
141
+ manifestPath,
142
+ mongodb: args ? 'deployed' : 'not deployed',
143
+ });
144
+ shellExec(`kubectl apply -k ${manifestPath} -n ${namespace}`);
145
+
146
+ const ready = await Underpost.test.statusMonitor(MONGO_EXPRESS_NAME, 'Running', 'pods', 1000, 60 * 10);
147
+ if (!ready) {
148
+ logger.error('mongo-express did not report Running', { namespace });
149
+ return false;
150
+ }
151
+
152
+ if (options.nodePort)
153
+ shellExec(`kubectl apply -f ${mongoExpressNodePortManifestFactory({ underpostRoot })} -n ${namespace}`);
154
+ if (options.nodeName)
155
+ Underpost.cluster.pinToNode({
156
+ kind: 'deployment',
157
+ name: MONGO_EXPRESS_NAME,
158
+ namespace,
159
+ node: options.nodeName,
160
+ });
161
+
162
+ logger.info('mongo-express ready', {
163
+ server: `${MONGODB_STATEFULSET_NAME}-0.${MONGODB_SERVICE_NAME}:${MONGODB_DEFAULT_PORT}`,
164
+ basicAuth: `secret/${MONGO_EXPRESS_SECRET_NAME}`,
165
+ clusterIp: `${MONGO_EXPRESS_SERVICE_NAME}:${MONGO_EXPRESS_PORT}${MONGO_EXPRESS_BASE_URL}`,
166
+ nodePort: options.nodePort ? `<node>:${MONGO_EXPRESS_NODE_PORT}${MONGO_EXPRESS_BASE_URL}` : null,
167
+ portForward: `kubectl port-forward -n ${namespace} svc/${MONGO_EXPRESS_SERVICE_NAME} ${MONGO_EXPRESS_PORT}:${MONGO_EXPRESS_PORT}`,
168
+ });
169
+ return true;
170
+ }
171
+ }
172
+
173
+ export {
174
+ MONGO_EXPRESS_BASE_URL,
175
+ MONGO_EXPRESS_IMAGE,
176
+ MONGO_EXPRESS_NAME,
177
+ MONGO_EXPRESS_NODE_PORT,
178
+ MONGO_EXPRESS_PORT,
179
+ MONGO_EXPRESS_SECRET_NAME,
180
+ MONGO_EXPRESS_SERVICE_NAME,
181
+ MongoExpress,
182
+ mongoAuthEnabledFactory,
183
+ mongoExpressManifestPathFactory,
184
+ mongoExpressNodePortManifestFactory,
185
+ parseMongodArgs,
186
+ };
187
+ export default MongoExpress;
@@ -1,6 +1,6 @@
1
1
  import mongoose from 'mongoose';
2
2
  import { getCapVariableName } from '../../client/components/core/CommonJs.js';
3
- import { loggerFactory } from '../../server/logger.js';
3
+ import { loggerFactory } from '../../server/ops/logger.js';
4
4
 
5
5
  /**
6
6
  * Module for connecting to and loading models for a MongoDB database using Mongoose.
@@ -13,16 +13,13 @@ const logger = loggerFactory(import.meta);
13
13
  const MONGODB_SERVICE_NAME = 'mongodb-service';
14
14
  const MONGODB_STATEFULSET_NAME = 'mongodb';
15
15
  const MONGODB_DEFAULT_AUTH_SOURCE = 'admin';
16
+ const MONGODB_DEFAULT_PORT = 27017;
16
17
  const MONGODB_DEFAULT_REPLICA_SET = 'rs0';
17
18
  const MONGODB_DEFAULT_REPLICA_COUNT = 3;
18
- // Node-local base path backing the hostPath PVs (`<root>/v<replica index>`),
19
- // generated one-per-replica by MongoBootstrap.applyReplicaVolumes().
20
19
  const MONGODB_DATA_ROOT = '/data/mongodb';
21
- // Replica volumes are hostPath PVs generated one per member, each pinned by `claimRef`. The class
22
- // must stay static: a dynamic provisioner competes with the static binder and makes
23
- // member-to-directory assignment non-deterministic.
24
20
  const MONGODB_STORAGE_CLASS_NAME = 'mongodb-storage-class';
25
21
  const MONGODB_STORAGE_CLASS_PROVISIONER = 'kubernetes.io/no-provisioner';
22
+
26
23
  /**
27
24
  * Mongoose connection options for MongoDB, with sensible defaults for production and development environments.
28
25
  * @type {import('mongoose').ConnectOptions}
@@ -51,12 +48,12 @@ const resolveMongoReplicaHosts = ({ hostList = '', replicaCount = MONGODB_DEFAUL
51
48
  .split(',')
52
49
  .map((host) => host.trim())
53
50
  .filter(Boolean)
54
- .map((host) => (host.includes(':') ? host : `${host}:27017`));
51
+ .map((host) => (host.includes(':') ? host : `${host}:${MONGODB_DEFAULT_PORT}`));
55
52
  }
56
53
 
57
54
  return Array.from(
58
55
  { length: replicaCount },
59
- (_, index) => `${MONGODB_STATEFULSET_NAME}-${index}.${MONGODB_SERVICE_NAME}:27017`,
56
+ (_, index) => `${MONGODB_STATEFULSET_NAME}-${index}.${MONGODB_SERVICE_NAME}:${MONGODB_DEFAULT_PORT}`,
60
57
  );
61
58
  };
62
59
 
@@ -208,6 +205,8 @@ export {
208
205
  MongooseDB,
209
206
  MongooseDBService as MongooseDBClass,
210
207
  MONGODB_DATA_ROOT,
208
+ MONGODB_DEFAULT_AUTH_SOURCE,
209
+ MONGODB_DEFAULT_PORT,
211
210
  MONGODB_DEFAULT_REPLICA_COUNT,
212
211
  MONGODB_DEFAULT_REPLICA_SET,
213
212
  MONGODB_SERVICE_NAME,
@@ -9,12 +9,13 @@
9
9
  * Out of scope: domain model factories, DTO projection — those belong in
10
10
  * their respective service modules (e.g. guest.service.js).
11
11
  *
12
- * @module src/server/valkey.js
12
+ * @module src/db/valkey/Valkey.js
13
13
  * @namespace ValkeyService
14
14
  */
15
15
  import Valkey from 'iovalkey';
16
- import { loggerFactory } from './logger.js';
17
- import Underpost from '../index.js';
16
+ import { loggerFactory } from '../../server/ops/logger.js';
17
+ import Underpost from '../../index.js';
18
+ import { latchRuntimeError } from '../../server/runtime/runtime-status.js';
18
19
 
19
20
  const logger = loggerFactory(import.meta);
20
21
 
@@ -71,7 +72,7 @@ const createValkeyConnection = async (instance = {}, connectionOptions = {}) =>
71
72
  client.on('error', (err) => {
72
73
  ValkeyStatus[key] = 'error';
73
74
  logger.error('Valkey error', { err: err?.message, instance });
74
- if (Underpost.env.isInsideContainer()) Underpost.env.set('container-status', 'error');
75
+ latchRuntimeError();
75
76
  });
76
77
  client.on('reconnecting', () => {
77
78
  ValkeyStatus[key] = 'reconnecting';
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * gRPC transport for the Cyberia Engine data pipeline.
3
3
  *
4
- * Runs alongside Express on a separate port (default 50051).
5
- * Thin adapter over src/projects/cyberia/instance-data.js the shared
6
- * world-load/boot assembly also served by the REST fallback at
7
- * /api/cyberia-instance/boot/* — so both transports stay equivalent.
4
+ * Runs beside Express on its own port (default 50051). Thin adapter over
5
+ * src/projects/cyberia/instance-data.js, the same assembly the REST fallback
6
+ * at /api/cyberia-instance/boot/* serves, so both transports stay equivalent.
8
7
  *
9
8
  * @module src/grpc/cyberia/grpc-server.js
10
9
  */
@@ -13,10 +12,9 @@ import * as grpc from '@grpc/grpc-js';
13
12
  import * as protoLoader from '@grpc/proto-loader';
14
13
  import path from 'path';
15
14
  import { fileURLToPath } from 'url';
16
- import { loggerFactory } from '../../server/logger.js';
15
+ import { loggerFactory } from '../../server/ops/logger.js';
17
16
  import {
18
17
  buildFallbackConfig,
19
- buildFallbackInstanceConfig,
20
18
  fetchFullInstance,
21
19
  fetchMapData,
22
20
  fetchObjectLayer,
@@ -131,7 +129,7 @@ class GrpcServer {
131
129
 
132
130
  server.addService(proto.CyberiaDataService.service, buildHandlers(dbKey));
133
131
 
134
- // gRPC runs over Kubernetes internal network (ClusterIP) always insecure
132
+ // gRPC stays on the cluster-internal network, so credentials are insecure.
135
133
  const creds = grpc.ServerCredentials.createInsecure();
136
134
 
137
135
  return new Promise((resolve, reject) => {
@@ -159,4 +157,4 @@ class GrpcServer {
159
157
  }
160
158
  }
161
159
 
162
- export { GrpcServer, buildFallbackConfig, buildFallbackInstanceConfig };
160
+ export { GrpcServer, buildFallbackConfig };
package/src/index.js CHANGED
@@ -5,23 +5,28 @@
5
5
  */
6
6
 
7
7
  import UnderpostBaremetal from './cli/baremetal.js';
8
+ import UnderpostApp from './cli/app.js';
9
+ import UnderpostClient from './cli/client.js';
10
+ import UnderpostHost from './cli/host.js';
8
11
  import UnderpostCloudInit from './cli/cloud-init.js';
9
12
  import UnderpostKickStart from './cli/kickstart.js';
10
13
  import UnderpostCluster from './cli/cluster.js';
11
14
  import UnderpostDB from './cli/db.js';
12
15
  import UnderpostDeploy from './cli/deploy.js';
13
16
  import UnderpostDockerCompose from './cli/docker-compose.js';
17
+ import UnderpostEvent from './cli/event.js';
14
18
  import UnderpostKubectl from './cli/kubectl.js';
15
- import UnderpostRootEnv from './cli/env.js';
16
19
  import UnderpostFileStorage from './cli/fs.js';
17
20
  import UnderpostIPFS from './cli/ipfs.js';
18
21
  import UnderpostImage from './cli/image.js';
19
22
  import UnderpostLxd from './cli/lxd.js';
20
23
  import UnderpostMonitor from './cli/monitor.js';
24
+ import UnderpostPackage from './cli/package.js';
21
25
  import UnderpostRepository from './cli/repository.js';
22
26
  import UnderpostRun from './cli/run.js';
23
27
  import UnderpostSecret from './cli/secrets.js';
24
28
  import UnderpostSSH from './cli/ssh.js';
29
+ import UnderpostState from './cli/state.js';
25
30
  import UnderpostStatic from './cli/static.js';
26
31
  import UnderpostTest from './cli/test.js';
27
32
  import UnderpostRelease from './cli/release.js';
@@ -29,11 +34,11 @@ import UnderpostSystemProvisionig from './cli/system.js';
29
34
  import UnderpostVultr from './cli/vultr.js';
30
35
  import UnderpostWireguard from './cli/wireguard.js';
31
36
 
32
- import UnderpostDns from './server/dns.js';
33
- import UnderpostBackup from './server/backup.js';
34
- import UnderpostCron from './server/cron.js';
35
- import UnderpostStartUp from './server/start.js';
36
- import UnderpostTLS from './server/tls.js';
37
+ import UnderpostDns from './server/network/dns.js';
38
+ import UnderpostBackup from './server/storage/backup.js';
39
+ import UnderpostCron from './server/ops/cron.js';
40
+ import UnderpostStartUp from './server/runtime/start.js';
41
+ import UnderpostTLS from './server/network/tls.js';
37
42
 
38
43
  /**
39
44
  * Underpost main module methods
@@ -47,7 +52,7 @@ class Underpost {
47
52
  * @type {String}
48
53
  * @memberof Underpost
49
54
  */
50
- static version = 'v3.3.0';
55
+ static version = 'v3.3.76';
51
56
 
52
57
  /**
53
58
  * Required Node.js major version
@@ -67,24 +72,14 @@ class Underpost {
67
72
  return UnderpostRepository.API;
68
73
  }
69
74
  /**
70
- * Root Env cli API
75
+ * Client build cli API
71
76
  * @static
72
- * @type {UnderpostRootEnv.API}
77
+ * @type {UnderpostClient.API}
73
78
  * @memberof Underpost
74
79
  */
75
- static get env() {
76
- return UnderpostRootEnv.API;
80
+ static get client() {
81
+ return UnderpostClient.API;
77
82
  }
78
- /**
79
- * Test cli API
80
- * @static
81
- * @type {UnderpostTest.API}
82
- * @memberof Underpost
83
- */
84
- static get test() {
85
- return UnderpostTest.API;
86
- }
87
-
88
83
  /**
89
84
  * Static cli API
90
85
  * @static
@@ -119,6 +114,33 @@ class Underpost {
119
114
  * @type {UnderpostSecret.API}
120
115
  * @memberof Underpost
121
116
  */
117
+ static get host() {
118
+ return UnderpostHost.API;
119
+ }
120
+ /**
121
+ * App deployment environment domain cli API
122
+ * @static
123
+ * @type {UnderpostApp.API}
124
+ * @memberof Underpost
125
+ */
126
+ static get app() {
127
+ return UnderpostApp.API;
128
+ }
129
+ /**
130
+ * Workload secret store domain cli API
131
+ * @static
132
+ * @type {UnderpostSecret.API}
133
+ * @memberof Underpost
134
+ */
135
+ static get state() {
136
+ return UnderpostState.API;
137
+ }
138
+ /**
139
+ * Workload secret store domain cli API
140
+ * @static
141
+ * @type {UnderpostSecret.API}
142
+ * @memberof Underpost
143
+ */
122
144
  static get secret() {
123
145
  return UnderpostSecret.API;
124
146
  }
@@ -185,6 +207,15 @@ class Underpost {
185
207
  static get monitor() {
186
208
  return UnderpostMonitor.API;
187
209
  }
210
+ /**
211
+ * Operational event dispatcher cli API
212
+ * @static
213
+ * @type {UnderpostEvent.API}
214
+ * @memberof Underpost
215
+ */
216
+ static get event() {
217
+ return UnderpostEvent.API;
218
+ }
188
219
  /**
189
220
  * SSH cli API
190
221
  * @static
@@ -333,6 +364,26 @@ class Underpost {
333
364
  static get release() {
334
365
  return UnderpostRelease.API;
335
366
  }
367
+
368
+ /**
369
+ * Test runner cli API
370
+ * @static
371
+ * @type {UnderpostTest.API}
372
+ * @memberof Underpost
373
+ */
374
+ static get test() {
375
+ return UnderpostTest.API;
376
+ }
377
+
378
+ /**
379
+ * Deploy package manifest cli API
380
+ * @static
381
+ * @type {UnderpostPackage.API}
382
+ * @memberof Underpost
383
+ */
384
+ static get package() {
385
+ return UnderpostPackage.API;
386
+ }
336
387
  }
337
388
 
338
389
  if (!process.version || !process.version.startsWith(`${Underpost.majorNodejsVersion}.`))
@@ -354,20 +405,25 @@ export {
354
405
  UnderpostDB,
355
406
  UnderpostDeploy,
356
407
  UnderpostDockerCompose,
408
+ UnderpostEvent,
357
409
  UnderpostKubectl,
358
- UnderpostRootEnv,
359
410
  UnderpostFileStorage,
360
411
  UnderpostImage,
361
412
  UnderpostStatic,
413
+ UnderpostTest,
362
414
  UnderpostLxd,
363
415
  UnderpostKickStart,
364
416
  UnderpostIPFS,
365
417
  UnderpostMonitor,
418
+ UnderpostPackage,
419
+ UnderpostApp,
420
+ UnderpostClient,
421
+ UnderpostHost,
366
422
  UnderpostRepository,
367
423
  UnderpostRun,
368
424
  UnderpostSecret,
369
425
  UnderpostSSH,
370
- UnderpostTest,
426
+ UnderpostState,
371
427
  UnderpostDns,
372
428
  UnderpostBackup,
373
429
  UnderpostCron,
@@ -98,8 +98,8 @@ class EmailRenderService {
98
98
  for (const templateKey of Object.keys(options.templates)) {
99
99
  const ssrEmailComponent = options.templates[templateKey];
100
100
  // Note: ssrFactory is assumed to load and return a functional component/function
101
- const SrrComponent = await ssrFactory(`./src/client/ssr/mailer/${ssrEmailComponent}.js`);
102
- templates[templateKey] = SrrComponent(this, options);
101
+ const SSRComponent = await ssrFactory(`./src/client/ssr/mailer/${ssrEmailComponent}.js`);
102
+ templates[templateKey] = SSRComponent(this, options);
103
103
  }
104
104
  return templates;
105
105
  }
@@ -0,0 +1,87 @@
1
+ import { MailerProvider } from './MailerProvider.js';
2
+
3
+ /**
4
+ * General-purpose capture of everything {@link MailerProviderService#send}
5
+ * delivers, built on the provider's send middleware.
6
+ *
7
+ * Assertions about mail are otherwise only possible against a real inbox. The
8
+ * interceptor records the delivery context and the transport result of each
9
+ * send, which is what lets a caller wait for a specific message and know
10
+ * whether the transport actually accepted it.
11
+ *
12
+ * @module src/mailer/MailerInterceptor.js
13
+ * @namespace MailerInterceptor
14
+ */
15
+
16
+ /**
17
+ * @typedef {object} InterceptedMail
18
+ * @property {string} id - Mailer instance the message was sent through.
19
+ * @property {object} sendOptions - Nodemailer options as the transport received them.
20
+ * @property {object|undefined} info - Transport result; `undefined` when delivery failed.
21
+ * @property {boolean} accepted - Whether the transport accepted the message.
22
+ * @property {string} at - ISO timestamp of the delivery attempt.
23
+ * @memberof MailerInterceptor
24
+ */
25
+
26
+ /**
27
+ * @method mailerInterceptorFactory
28
+ * @description Installs a send interceptor and returns its recorder.
29
+ *
30
+ * The interceptor is transparent: it forwards every send to the transport and
31
+ * records the outcome. `suppress` holds the message instead, for callers that
32
+ * must exercise the send path without delivering.
33
+ *
34
+ * @param {object} [params]
35
+ * @param {import('./MailerProvider.js').MailerProvider} [params.provider] - Provider to intercept.
36
+ * @param {function(object): boolean} [params.filter] - Records only the contexts it accepts.
37
+ * @param {boolean} [params.suppress=false] - Record without handing the message to the transport.
38
+ * @returns {{messages: Array<InterceptedMail>, waitFor: function, close: function(): void}} Recorder.
39
+ * @memberof MailerInterceptor
40
+ */
41
+ const mailerInterceptorFactory = ({ provider = MailerProvider, filter, suppress = false } = {}) => {
42
+ const messages = [];
43
+
44
+ const dispose = provider.use(async (context, next) => {
45
+ const matched = !filter || filter(context);
46
+ const info = matched && suppress ? { messageId: `suppressed:${Date.now()}`, suppressed: true } : await next();
47
+ if (matched)
48
+ messages.push({
49
+ id: context.id,
50
+ sendOptions: context.sendOptions,
51
+ info,
52
+ accepted: Boolean(info),
53
+ at: new Date().toISOString(),
54
+ });
55
+ return info;
56
+ });
57
+
58
+ return {
59
+ messages,
60
+
61
+ /**
62
+ * Resolves with the first recorded message matching `predicate`.
63
+ *
64
+ * Polls rather than resolving on registration, because a send started
65
+ * before the caller began waiting must still satisfy the wait.
66
+ *
67
+ * @param {function(InterceptedMail): boolean} predicate - Match to wait for.
68
+ * @param {object} [options]
69
+ * @param {number} [options.timeoutMs=60000] - Maximum wait.
70
+ * @param {number} [options.intervalMs=250] - Poll interval.
71
+ * @returns {Promise<InterceptedMail|undefined>} The match, or `undefined` on timeout.
72
+ */
73
+ async waitFor(predicate, { timeoutMs = 60000, intervalMs = 250 } = {}) {
74
+ const deadline = Date.now() + timeoutMs;
75
+ do {
76
+ const match = messages.find(predicate);
77
+ if (match) return match;
78
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
79
+ } while (Date.now() < deadline);
80
+ return messages.find(predicate);
81
+ },
82
+
83
+ close: dispose,
84
+ };
85
+ };
86
+
87
+ export { mailerInterceptorFactory };
@@ -1,5 +1,5 @@
1
1
  import nodemailer from 'nodemailer';
2
- import { loggerFactory } from '../server/logger.js';
2
+ import { loggerFactory } from '../server/ops/logger.js';
3
3
  import { EmailRender } from './EmailRender.js';
4
4
 
5
5
  /**
@@ -45,6 +45,12 @@ class MailerProviderService {
45
45
  */
46
46
  #instance = {};
47
47
 
48
+ /**
49
+ * Registered send middlewares, in the order they wrap a delivery.
50
+ * @type {Array<function(object, function(): Promise<object|undefined>): Promise<object|undefined>>}
51
+ */
52
+ #middlewares = [];
53
+
48
54
  /**
49
55
  * Retrieves the internal instance storage for direct access (used for backward compatibility).
50
56
  * @returns {object.<string, object>} The internal mailer instance map.
@@ -53,6 +59,28 @@ class MailerProviderService {
53
59
  return this.#instance;
54
60
  }
55
61
 
62
+ /**
63
+ * Registers a send middleware.
64
+ *
65
+ * Middlewares wrap every {@link MailerProviderService#send}, in registration
66
+ * order, and receive the delivery context plus the `next` continuation that
67
+ * yields the transport result. A middleware that never calls `next` suppresses
68
+ * the delivery, which is what makes this usable both for cross-cutting
69
+ * concerns (auditing, rate limiting) and for capturing mail in a test run.
70
+ *
71
+ * @param {function(object, function(): Promise<object|undefined>): Promise<object|undefined>} middleware -
72
+ * Receives `({ id, sendOptions, sender }, next)`.
73
+ * @returns {function(): void} Disposer that unregisters the middleware.
74
+ */
75
+ use(middleware) {
76
+ if (typeof middleware !== 'function') throw new Error('[mailer] a send middleware must be a function');
77
+ this.#middlewares.push(middleware);
78
+ return () => {
79
+ const index = this.#middlewares.indexOf(middleware);
80
+ if (index !== -1) this.#middlewares.splice(index, 1);
81
+ };
82
+ }
83
+
56
84
  /**
57
85
  * Loads and initializes a new mailer provider instance using Nodemailer.
58
86
  * The created instance is stored internally and includes the transporter and rendered templates.
@@ -145,6 +173,24 @@ class MailerProviderService {
145
173
  }
146
174
  }
147
175
 
176
+ /**
177
+ * Closes a loaded instance's transport and forgets it.
178
+ *
179
+ * A transport holds an open socket, which keeps a one-shot process alive long
180
+ * after its work is done. Callers that load an instance for a single delivery
181
+ * release it here; a long-running server keeps its instances loaded instead.
182
+ *
183
+ * @param {string} id - Mailer instance id.
184
+ * @returns {boolean} True when an instance was closed.
185
+ */
186
+ close(id) {
187
+ const instance = this.#instance[id];
188
+ if (!instance) return false;
189
+ if (typeof instance.transporter?.close === 'function') instance.transporter.close();
190
+ delete this.#instance[id];
191
+ return true;
192
+ }
193
+
148
194
  /**
149
195
  * Sends an email using a previously loaded transporter instance.
150
196
  *
@@ -189,12 +235,10 @@ class MailerProviderService {
189
235
 
190
236
  if (!sendOptions.from) sendOptions.from = `${instance.sender.name} <${instance.sender.email}>`;
191
237
 
192
- // send mail with defined transport object
193
- const info = await instance.transporter.sendMail(sendOptions);
194
-
195
- // logger.info('Message sent', info);
238
+ const context = { id, sendOptions, sender: instance.sender };
239
+ const deliver = () => instance.transporter.sendMail(sendOptions);
196
240
 
197
- return info;
241
+ return await this.#middlewares.reduceRight((next, middleware) => () => middleware(context, next), deliver)();
198
242
  } catch (error) {
199
243
  logger.error(error, error.stack);
200
244
  return undefined;