cyberia 3.1.3 → 3.2.9

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 (377) hide show
  1. package/.env.example +0 -2
  2. package/.github/workflows/engine-cyberia.cd.yml +10 -8
  3. package/.github/workflows/engine-cyberia.ci.yml +12 -29
  4. package/.github/workflows/ghpkg.ci.yml +4 -4
  5. package/.github/workflows/npmpkg.ci.yml +28 -11
  6. package/.github/workflows/publish.ci.yml +21 -2
  7. package/.github/workflows/pwa-microservices-template-page.cd.yml +4 -5
  8. package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
  9. package/.github/workflows/release.cd.yml +14 -10
  10. package/CHANGELOG.md +783 -1
  11. package/CLI-HELP.md +95 -18
  12. package/Dockerfile +0 -2
  13. package/README.md +290 -220
  14. package/bin/build.js +24 -7
  15. package/bin/cyberia.js +2838 -252
  16. package/bin/deploy.js +747 -125
  17. package/bin/file.js +9 -0
  18. package/bin/index.js +2838 -252
  19. package/bin/vs.js +1 -1
  20. package/conf.js +99 -65
  21. package/deployment.yaml +18 -164
  22. package/hardhat/hardhat.config.js +13 -13
  23. package/hardhat/ignition/modules/ObjectLayerToken.js +1 -1
  24. package/hardhat/package-lock.json +2559 -5864
  25. package/hardhat/package.json +14 -23
  26. package/hardhat/scripts/deployObjectLayerToken.js +1 -1
  27. package/hardhat/test/ObjectLayerToken.js +4 -2
  28. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  29. package/hardhat/types/ethers-contracts/common.ts +92 -0
  30. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  31. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  32. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  33. package/hardhat/types/ethers-contracts/index.ts +6 -0
  34. package/jsconfig.json +1 -1
  35. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +6 -5
  36. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +6 -5
  37. package/manifests/deployment/dd-cyberia-development/deployment.yaml +18 -164
  38. package/manifests/deployment/dd-cyberia-development/proxy.yaml +7 -79
  39. package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
  40. package/manifests/deployment/dd-test-development/deployment.yaml +112 -28
  41. package/manifests/deployment/dd-test-development/proxy.yaml +46 -1
  42. package/manifests/deployment/playwright/deployment.yaml +1 -1
  43. package/nodemon.json +1 -1
  44. package/package.json +39 -24
  45. package/proxy.yaml +7 -79
  46. package/scripts/k3s-node-setup.sh +2 -2
  47. package/scripts/nat-iptables.sh +103 -18
  48. package/scripts/rhel-grpc-setup.sh +56 -0
  49. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +58 -14
  50. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +23 -14
  51. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  52. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +148 -20
  53. package/src/api/core/core.controller.js +10 -10
  54. package/src/api/core/core.service.js +10 -10
  55. package/src/api/crypto/crypto.controller.js +8 -8
  56. package/src/api/crypto/crypto.service.js +8 -8
  57. package/src/api/cyberia-action/cyberia-action.controller.js +74 -0
  58. package/src/api/cyberia-action/cyberia-action.model.js +87 -0
  59. package/src/api/cyberia-action/cyberia-action.router.js +27 -0
  60. package/src/api/cyberia-action/cyberia-action.service.js +42 -0
  61. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
  62. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  63. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
  64. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
  65. package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
  66. package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
  67. package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
  68. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  69. package/src/api/cyberia-instance/cyberia-fallback-world.js +178 -0
  70. package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
  71. package/src/api/cyberia-instance/cyberia-instance.model.js +87 -0
  72. package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
  73. package/src/api/cyberia-instance/cyberia-instance.service.js +156 -0
  74. package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
  75. package/src/api/cyberia-instance/cyberia-world-generator.js +505 -0
  76. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
  77. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +574 -0
  78. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +231 -0
  79. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
  80. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
  81. package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
  82. package/src/api/cyberia-map/cyberia-map.model.js +30 -0
  83. package/src/api/cyberia-map/cyberia-map.router.js +40 -0
  84. package/src/api/cyberia-map/cyberia-map.service.js +74 -0
  85. package/src/api/cyberia-quest/cyberia-quest.controller.js +74 -0
  86. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  87. package/src/api/cyberia-quest/cyberia-quest.router.js +27 -0
  88. package/src/api/cyberia-quest/cyberia-quest.service.js +42 -0
  89. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +74 -0
  90. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  91. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +27 -0
  92. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  93. package/src/api/default/default.controller.js +10 -10
  94. package/src/api/default/default.service.js +10 -10
  95. package/src/api/document/document.controller.js +12 -12
  96. package/src/api/document/document.model.js +10 -16
  97. package/src/api/file/file.controller.js +8 -8
  98. package/src/api/file/file.model.js +10 -10
  99. package/src/api/file/file.ref.json +18 -0
  100. package/src/api/file/file.service.js +36 -36
  101. package/src/api/instance/instance.controller.js +10 -10
  102. package/src/api/instance/instance.model.js +4 -10
  103. package/src/api/instance/instance.service.js +10 -10
  104. package/src/api/ipfs/ipfs.controller.js +15 -36
  105. package/src/api/ipfs/ipfs.model.js +47 -47
  106. package/src/api/ipfs/ipfs.router.js +8 -13
  107. package/src/api/ipfs/ipfs.service.js +67 -129
  108. package/src/api/object-layer/object-layer.controller.js +12 -12
  109. package/src/api/object-layer/object-layer.model.js +4 -17
  110. package/src/api/object-layer/object-layer.router.js +30 -0
  111. package/src/api/object-layer/object-layer.service.js +126 -43
  112. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +10 -10
  113. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +6 -16
  114. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +18 -14
  115. package/src/api/test/test.controller.js +8 -8
  116. package/src/api/test/test.service.js +8 -8
  117. package/src/api/user/guest.service.js +99 -0
  118. package/src/api/user/user.controller.js +6 -6
  119. package/src/api/user/user.model.js +8 -13
  120. package/src/api/user/user.service.js +11 -27
  121. package/src/cli/cluster.js +68 -21
  122. package/src/cli/db.js +753 -825
  123. package/src/cli/deploy.js +215 -125
  124. package/src/cli/env.js +29 -0
  125. package/src/cli/fs.js +82 -8
  126. package/src/cli/image.js +43 -1
  127. package/src/cli/index.js +74 -3
  128. package/src/cli/kubectl.js +211 -0
  129. package/src/cli/release.js +340 -0
  130. package/src/cli/repository.js +475 -74
  131. package/src/cli/run.js +582 -43
  132. package/src/cli/secrets.js +73 -0
  133. package/src/cli/ssh.js +1 -1
  134. package/src/cli/static.js +43 -115
  135. package/src/cli/test.js +3 -3
  136. package/src/client/Cryptokoyn.index.js +18 -22
  137. package/src/client/CyberiaPortal.index.js +19 -24
  138. package/src/client/Default.index.js +21 -34
  139. package/src/client/Itemledger.index.js +20 -27
  140. package/src/client/Underpost.index.js +19 -24
  141. package/src/client/components/core/404.js +4 -4
  142. package/src/client/components/core/500.js +4 -4
  143. package/src/client/components/core/Account.js +73 -60
  144. package/src/client/components/core/AgGrid.js +23 -33
  145. package/src/client/components/core/Alert.js +12 -13
  146. package/src/client/components/core/AppStore.js +69 -0
  147. package/src/client/components/core/Auth.js +35 -37
  148. package/src/client/components/core/Badge.js +7 -13
  149. package/src/client/components/core/BtnIcon.js +15 -17
  150. package/src/client/components/core/CalendarCore.js +43 -64
  151. package/src/client/components/core/Chat.js +13 -15
  152. package/src/client/components/core/ClientEvents.js +87 -0
  153. package/src/client/components/core/ColorPaletteElement.js +309 -0
  154. package/src/client/components/core/Content.js +17 -14
  155. package/src/client/components/core/Css.js +15 -71
  156. package/src/client/components/core/CssCore.js +12 -16
  157. package/src/client/components/core/D3Chart.js +4 -4
  158. package/src/client/components/core/Docs.js +64 -91
  159. package/src/client/components/core/DropDown.js +194 -96
  160. package/src/client/components/core/EventBus.js +92 -0
  161. package/src/client/components/core/EventsUI.js +14 -17
  162. package/src/client/components/core/FileExplorer.js +96 -228
  163. package/src/client/components/core/FullScreen.js +47 -75
  164. package/src/client/components/core/Input.js +24 -69
  165. package/src/client/components/core/Keyboard.js +26 -19
  166. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  167. package/src/client/components/core/LoadingAnimation.js +25 -31
  168. package/src/client/components/core/LogIn.js +43 -43
  169. package/src/client/components/core/LogOut.js +25 -16
  170. package/src/client/components/core/Modal.js +462 -179
  171. package/src/client/components/core/NotificationManager.js +14 -18
  172. package/src/client/components/core/Panel.js +54 -51
  173. package/src/client/components/core/PanelForm.js +44 -144
  174. package/src/client/components/core/Polyhedron.js +110 -214
  175. package/src/client/components/core/PublicProfile.js +39 -32
  176. package/src/client/components/core/Recover.js +48 -44
  177. package/src/client/components/core/Responsive.js +88 -32
  178. package/src/client/components/core/RichText.js +9 -18
  179. package/src/client/components/core/Router.js +24 -3
  180. package/src/client/components/core/SearchBox.js +37 -37
  181. package/src/client/components/core/SignUp.js +39 -30
  182. package/src/client/components/core/SocketIo.js +112 -30
  183. package/src/client/components/core/SocketIoHandler.js +75 -0
  184. package/src/client/components/core/Stream.js +143 -95
  185. package/src/client/components/core/ToggleSwitch.js +8 -20
  186. package/src/client/components/core/ToolTip.js +5 -17
  187. package/src/client/components/core/Translate.js +56 -59
  188. package/src/client/components/core/Validator.js +26 -16
  189. package/src/client/components/core/Wallet.js +15 -26
  190. package/src/client/components/core/Webhook.js +40 -7
  191. package/src/client/components/core/Worker.js +163 -27
  192. package/src/client/components/core/windowGetDimensions.js +7 -7
  193. package/src/client/components/cryptokoyn/{MenuCryptokoyn.js → AppShellCryptokoyn.js} +59 -59
  194. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  195. package/src/client/components/cryptokoyn/CssCryptokoyn.js +15 -15
  196. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +9 -7
  197. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +8 -6
  198. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  199. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +4 -4
  200. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +6 -4
  201. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
  202. package/src/client/components/cyberia/InstanceEngineCyberia.js +781 -0
  203. package/src/client/components/cyberia/MapEngineCyberia.js +1836 -2
  204. package/src/client/components/cyberia/ObjectLayerEngine.js +19 -0
  205. package/src/client/components/cyberia/ObjectLayerEngineModal.js +1220 -99
  206. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +252 -316
  207. package/src/client/components/cyberia-portal/{MenuCyberiaPortal.js → AppShellCyberiaPortal.js} +136 -103
  208. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  209. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +462 -32
  210. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +15 -15
  211. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +9 -7
  212. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +8 -6
  213. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +4 -4
  214. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +60 -0
  215. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +4 -4
  216. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +6 -4
  217. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
  218. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +8 -4
  219. package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +91 -91
  220. package/src/client/components/default/AppStoreDefault.js +5 -0
  221. package/src/client/components/default/CssDefault.js +12 -12
  222. package/src/client/components/default/LogInDefault.js +9 -7
  223. package/src/client/components/default/LogOutDefault.js +8 -6
  224. package/src/client/components/default/RouterDefault.js +47 -0
  225. package/src/client/components/default/SettingsDefault.js +4 -4
  226. package/src/client/components/default/SignUpDefault.js +6 -4
  227. package/src/client/components/default/SocketIoDefault.js +3 -51
  228. package/src/client/components/default/TranslateDefault.js +3 -3
  229. package/src/client/components/itemledger/{MenuItemledger.js → AppShellItemledger.js} +59 -59
  230. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  231. package/src/client/components/itemledger/CssItemledger.js +15 -15
  232. package/src/client/components/itemledger/LogInItemledger.js +9 -7
  233. package/src/client/components/itemledger/LogOutItemledger.js +8 -6
  234. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  235. package/src/client/components/itemledger/SettingsItemledger.js +4 -4
  236. package/src/client/components/itemledger/SignUpItemledger.js +6 -4
  237. package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
  238. package/src/client/components/itemledger/TranslateItemledger.js +3 -3
  239. package/src/client/components/underpost/{MenuUnderpost.js → AppShellUnderpost.js} +92 -92
  240. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  241. package/src/client/components/underpost/CssUnderpost.js +14 -14
  242. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +4 -4
  243. package/src/client/components/underpost/DocumentSearchProvider.js +1 -1
  244. package/src/client/components/underpost/LabGalleryUnderpost.js +12 -15
  245. package/src/client/components/underpost/LogInUnderpost.js +9 -7
  246. package/src/client/components/underpost/LogOutUnderpost.js +8 -6
  247. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  248. package/src/client/components/underpost/SettingsUnderpost.js +4 -4
  249. package/src/client/components/underpost/SignUpUnderpost.js +6 -4
  250. package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
  251. package/src/client/components/underpost/TranslateUnderpost.js +4 -4
  252. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +235 -0
  253. package/src/client/public/cyberia-docs/ARCHITECTURE.md +443 -0
  254. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +417 -0
  255. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +313 -0
  256. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +260 -0
  257. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +241 -0
  258. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  259. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +279 -0
  260. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +206 -0
  261. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  262. package/src/client/public/cyberia-docs/WHITE-PAPER.md +732 -0
  263. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +14 -20
  264. package/src/client/services/core/core.service.js +35 -55
  265. package/src/client/services/crypto/crypto.service.js +8 -13
  266. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  267. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
  268. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  269. package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
  270. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  271. package/src/client/services/cyberia-instance/cyberia-instance.service.js +116 -0
  272. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
  273. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  274. package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
  275. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  276. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  277. package/src/client/services/default/default.management.js +159 -267
  278. package/src/client/services/default/default.service.js +10 -16
  279. package/src/client/services/document/document.service.js +14 -19
  280. package/src/client/services/file/file.service.js +8 -13
  281. package/src/client/services/instance/instance.management.js +6 -6
  282. package/src/client/services/instance/instance.service.js +10 -15
  283. package/src/client/services/ipfs/ipfs.service.js +14 -40
  284. package/src/client/services/object-layer/object-layer.management.js +14 -14
  285. package/src/client/services/object-layer/object-layer.service.js +39 -24
  286. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +10 -16
  287. package/src/client/services/test/test.service.js +8 -13
  288. package/src/client/services/user/guest.service.js +86 -0
  289. package/src/client/services/user/user.management.js +6 -6
  290. package/src/client/services/user/user.service.js +14 -20
  291. package/src/client/ssr/body/404.js +3 -3
  292. package/src/client/ssr/body/500.js +3 -3
  293. package/src/client/ssr/body/CacheControl.js +5 -2
  294. package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
  295. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +13 -6
  296. package/src/client/ssr/head/PwaItemledger.js +197 -60
  297. package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
  298. package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
  299. package/src/client/ssr/offline/Maintenance.js +12 -11
  300. package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
  301. package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
  302. package/src/client/ssr/pages/Test.js +2 -2
  303. package/src/client/sw/core.sw.js +212 -0
  304. package/src/grpc/cyberia/grpc-server.js +642 -0
  305. package/src/index.js +24 -1
  306. package/src/runtime/cyberia-client/Dockerfile +80 -0
  307. package/src/runtime/cyberia-server/Dockerfile +37 -0
  308. package/src/runtime/express/Dockerfile +5 -1
  309. package/src/runtime/express/Express.js +18 -1
  310. package/src/runtime/lampp/Dockerfile +17 -5
  311. package/src/runtime/lampp/Lampp.js +27 -4
  312. package/src/runtime/wp/Dockerfile +62 -0
  313. package/src/runtime/wp/Wp.js +639 -0
  314. package/src/server/atlas-sprite-sheet-generator.js +4 -2
  315. package/src/server/auth.js +24 -1
  316. package/src/server/backup.js +37 -9
  317. package/src/server/client-build-docs.js +52 -46
  318. package/src/server/client-build.js +356 -82
  319. package/src/server/client-formatted.js +140 -57
  320. package/src/server/conf.js +29 -13
  321. package/src/server/cron.js +25 -23
  322. package/src/server/data-query.js +32 -20
  323. package/src/server/dns.js +24 -1
  324. package/src/server/ipfs-client.js +253 -89
  325. package/src/server/object-layer.js +150 -114
  326. package/src/server/peer.js +8 -0
  327. package/src/server/process.js +13 -27
  328. package/src/server/runtime.js +25 -1
  329. package/src/server/semantic-layer-generator-floor.js +319 -0
  330. package/src/server/semantic-layer-generator-resource.js +259 -0
  331. package/src/server/semantic-layer-generator-skin.js +1164 -0
  332. package/src/server/semantic-layer-generator.js +211 -542
  333. package/src/server/shape-generator.js +108 -0
  334. package/src/server/start.js +19 -5
  335. package/src/server/valkey.js +141 -235
  336. package/src/ws/IoInterface.js +1 -10
  337. package/src/ws/IoServer.js +14 -33
  338. package/src/ws/core/channels/core.ws.chat.js +65 -20
  339. package/src/ws/core/channels/core.ws.mailer.js +113 -32
  340. package/src/ws/core/channels/core.ws.stream.js +90 -31
  341. package/src/ws/core/core.ws.connection.js +12 -33
  342. package/src/ws/core/core.ws.emit.js +10 -26
  343. package/src/ws/core/core.ws.server.js +25 -58
  344. package/src/ws/default/channels/default.ws.main.js +53 -12
  345. package/src/ws/default/default.ws.connection.js +26 -13
  346. package/src/ws/default/default.ws.server.js +30 -12
  347. package/tsconfig.docs.json +15 -0
  348. package/typedoc.dd-cyberia.json +29 -0
  349. package/typedoc.json +29 -0
  350. package/WHITE-PAPER.md +0 -1540
  351. package/hardhat/README.md +0 -531
  352. package/hardhat/WHITE-PAPER.md +0 -1540
  353. package/jsdoc.dd-cyberia.json +0 -59
  354. package/jsdoc.json +0 -59
  355. package/src/api/object-layer/README.md +0 -347
  356. package/src/client/components/core/ColorPalette.js +0 -5267
  357. package/src/client/components/core/JoyStick.js +0 -80
  358. package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
  359. package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
  360. package/src/client/components/cryptokoyn/RoutesCryptokoyn.js +0 -39
  361. package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
  362. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +0 -58
  363. package/src/client/components/cyberia-portal/ServerCyberiaPortal.js +0 -136
  364. package/src/client/components/default/ElementsDefault.js +0 -38
  365. package/src/client/components/default/RoutesDefault.js +0 -49
  366. package/src/client/components/itemledger/CommonItemledger.js +0 -29
  367. package/src/client/components/itemledger/ElementsItemledger.js +0 -38
  368. package/src/client/components/itemledger/RoutesItemledger.js +0 -40
  369. package/src/client/components/underpost/CommonUnderpost.js +0 -29
  370. package/src/client/components/underpost/ElementsUnderpost.js +0 -38
  371. package/src/client/components/underpost/RoutesUnderpost.js +0 -47
  372. package/src/client/sw/default.sw.js +0 -127
  373. package/src/client/sw/template.sw.js +0 -84
  374. package/src/ws/core/management/core.ws.chat.js +0 -8
  375. package/src/ws/core/management/core.ws.mailer.js +0 -16
  376. package/src/ws/core/management/core.ws.stream.js +0 -8
  377. package/src/ws/default/management/default.ws.main.js +0 -8
@@ -155,6 +155,26 @@ registerShape('parabola', (t, params) => {
155
155
  return { x, y: a * x * x };
156
156
  });
157
157
 
158
+ registerShape('thick-parabola', (t, params) => {
159
+ // Closed parabolic band — traces the outer curve forward then the inner
160
+ // curve backward, producing a thick filled crescent when rasterized.
161
+ // `a` controls curvature, `rangeX` controls horizontal span, and
162
+ // `thickness` controls band width (vertical gap between outer/inner).
163
+ const a = params.a ?? 0.6;
164
+ const rangeX = params.rangeX ?? 1.3;
165
+ const thickness = params.thickness ?? 0.35;
166
+ if (t <= 0.5) {
167
+ // Outer parabola (forward: left → right)
168
+ const u = t * 2;
169
+ const xNorm = -rangeX + 2 * rangeX * u;
170
+ return { x: xNorm, y: a * xNorm * xNorm };
171
+ }
172
+ // Inner parabola (reverse: right → left, shifted up by thickness)
173
+ const u = 1 - (t - 0.5) * 2;
174
+ const xNorm = -rangeX + 2 * rangeX * u;
175
+ return { x: xNorm, y: a * xNorm * xNorm + thickness };
176
+ });
177
+
158
178
  registerShape('heart', (t) => {
159
179
  const angle = t * Math.PI * 2;
160
180
  const x = 16 * Math.pow(Math.sin(angle), 3);
@@ -408,6 +428,42 @@ registerShape('bezier-path', (t, params) => {
408
428
  return { x, y };
409
429
  });
410
430
 
431
+ registerShape('regular-polygon', (t, params) => {
432
+ // Regular convex polygon with `sides` edges.
433
+ // Traces straight vertex-to-vertex segments for perfect geometric figures.
434
+ const sides = Math.max(3, params.sides ?? 4);
435
+ const r = params.r ?? 1;
436
+ const segAngle = (2 * Math.PI) / sides;
437
+ const angle = t * Math.PI * 2;
438
+ // Which segment are we in?
439
+ const seg = Math.floor(angle / segAngle);
440
+ const frac = (angle - seg * segAngle) / segAngle;
441
+ // Offset: -π/2 puts first vertex at top (flat bottom for odd-sided).
442
+ // For even-sided polygons, shift by half a segment so edges are axis-aligned.
443
+ const offset = -Math.PI / 2 + (sides % 2 === 0 ? Math.PI / sides : 0);
444
+ const a0 = seg * segAngle + offset;
445
+ const a1 = (seg + 1) * segAngle + offset;
446
+ const x = r * ((1 - frac) * Math.cos(a0) + frac * Math.cos(a1));
447
+ const y = r * ((1 - frac) * Math.sin(a0) + frac * Math.sin(a1));
448
+ return { x, y };
449
+ });
450
+
451
+ registerShape('rectangle', (t, params) => {
452
+ // Axis-aligned rectangle with configurable aspect ratio.
453
+ // `width` and `height` control proportions (default: 1.4 × 1.0).
454
+ const w = params.width ?? 1.4;
455
+ const h = params.height ?? 1.0;
456
+ const hw = w / 2,
457
+ hh = h / 2;
458
+ const perim = 2 * (w + h);
459
+ const d = t * perim;
460
+ // Traverse: bottom-left → bottom-right → top-right → top-left
461
+ if (d < w) return { x: -hw + d, y: hh };
462
+ if (d < w + h) return { x: hw, y: hh - (d - w) };
463
+ if (d < 2 * w + h) return { x: hw - (d - w - h), y: -hh };
464
+ return { x: -hw, y: -hh + (d - 2 * w - h) };
465
+ });
466
+
411
467
  /* ═══════════════════════════════════════════════════════════════════════════
412
468
  * GEOMETRY HELPERS
413
469
  * ═══════════════════════════════════════════════════════════════════════════ */
@@ -677,6 +733,49 @@ function rasterizeContour(normalizedPoints, gridW, gridH, closed) {
677
733
  return unique;
678
734
  }
679
735
 
736
+ /**
737
+ * Scanline-fills the interior of a closed contour on an integer grid.
738
+ * Takes the contour points produced by `rasterizeContour` and returns a
739
+ * new array containing both the contour AND all interior cells.
740
+ *
741
+ * Uses the standard even-odd scanline algorithm: for each row, find the
742
+ * leftmost and rightmost contour cell then fill everything in between.
743
+ *
744
+ * @param {ShapePoint[]} contourPoints - Contour cells from rasterizeContour.
745
+ * @param {number} gridW - Grid width.
746
+ * @param {number} gridH - Grid height.
747
+ * @returns {ShapePoint[]} All unique filled cells (contour + interior).
748
+ * @memberof ShapeGenerator
749
+ */
750
+ function scanlineFill(contourPoints, gridW, gridH) {
751
+ // Build per-row min/max from contour
752
+ const rowBounds = new Map();
753
+ for (const p of contourPoints) {
754
+ const b = rowBounds.get(p.y);
755
+ if (b) {
756
+ if (p.x < b.min) b.min = p.x;
757
+ if (p.x > b.max) b.max = p.x;
758
+ } else {
759
+ rowBounds.set(p.y, { min: p.x, max: p.x });
760
+ }
761
+ }
762
+
763
+ const seen = new Set();
764
+ const filled = [];
765
+
766
+ for (const [y, { min, max }] of rowBounds) {
767
+ for (let x = min; x <= max; x++) {
768
+ const k = x * 100000 + y;
769
+ if (!seen.has(k)) {
770
+ seen.add(k);
771
+ filled.push({ x, y });
772
+ }
773
+ }
774
+ }
775
+
776
+ return filled;
777
+ }
778
+
680
779
  /**
681
780
  * Renders an integer-coordinate ShapeResult as an ASCII grid string.
682
781
  * Useful for quick visual verification of pixel-art shapes.
@@ -738,6 +837,9 @@ export function renderGrid(shapeResult, opts = {}) {
738
837
  * with Bresenham rasterization so that even on a 16×16 grid the full contour
739
838
  * is visible as a connected set of cells. `count` is ignored in this mode;
740
839
  * the number of output points equals the number of unique rasterized cells.
840
+ * @property {boolean} [fill=false] - When true (and intCoords is enabled),
841
+ * scanline-fills the interior of the closed contour, producing a solid
842
+ * silhouette instead of an outline-only shape.
741
843
  * @memberof ShapeGenerator
742
844
  */
743
845
 
@@ -810,6 +912,7 @@ export function generateShape(key, options = {}) {
810
912
  closed = true,
811
913
  normalize = true,
812
914
  intCoords = false,
915
+ fill = false,
813
916
  color,
814
917
  ...extraParams
815
918
  } = options;
@@ -896,6 +999,11 @@ export function generateShape(key, options = {}) {
896
999
  if (useIntCoords) {
897
1000
  points = rasterizeContour(points, gridW, gridH, closed);
898
1001
 
1002
+ // ---- Scanline fill (solid silhouette) -----------------------------------
1003
+ if (fill && closed) {
1004
+ points = scanlineFill(points, gridW, gridH);
1005
+ }
1006
+
899
1007
  // Build metadata for integer grid mode
900
1008
  const bbox = computeBbox(points);
901
1009
  /** @type {ShapeMetadata} */
@@ -131,11 +131,21 @@ class UnderpostStartUp {
131
131
  * @param {boolean} options.build - Whether to build the deployment.
132
132
  * @param {boolean} options.run - Whether to run the deployment.
133
133
  * @param {boolean} options.underpostQuicklyInstall - Whether to use underpost quickly install.
134
+ * @param {boolean} options.skipPullBase - Whether to skip pulling the base code.
135
+ * @param {boolean} options.skipFullBuild - Whether to skip building the full client bundle.
136
+ * @param {boolean} options.pullBundle - When true, download pre-built client bundle from Cloudinary via pull-bundle before starting.
134
137
  */
135
138
  async callback(
136
139
  deployId = 'dd-default',
137
140
  env = 'development',
138
- options = { build: false, run: false, underpostQuicklyInstall: false },
141
+ options = {
142
+ build: false,
143
+ run: false,
144
+ underpostQuicklyInstall: false,
145
+ skipPullBase: false,
146
+ skipFullBuild: false,
147
+ pullBundle: false,
148
+ },
139
149
  ) {
140
150
  Underpost.env.set('container-status', `${deployId}-${env}-build-deployment`);
141
151
  if (options.build === true) await Underpost.start.build(deployId, env, options);
@@ -149,12 +159,15 @@ class UnderpostStartUp {
149
159
  * @param {Object} options - Options for the build.
150
160
  * @param {boolean} options.skipPullBase - Whether to skip pulling the base code and use the current workspace code directly.
151
161
  * @param {boolean} options.underpostQuicklyInstall - Whether to use underpost quickly install.
162
+ * @param {boolean} options.skipFullBuild - Whether to skip building the full client bundle.
163
+ * @param {boolean} options.pullBundle - When true, download pre-built client bundle from Cloudinary via pull-bundle (must be pushed first with push-bundle).
164
+ * This flag is independent of skipFullBuild: it can be combined with skipFullBuild or used alone.
152
165
  * @memberof UnderpostStartUp
153
166
  */
154
167
  async build(
155
168
  deployId = 'dd-default',
156
169
  env = 'development',
157
- options = { underpostQuicklyInstall: false, skipPullBase: false },
170
+ options = { underpostQuicklyInstall: false, skipPullBase: false, skipFullBuild: false, pullBundle: false },
158
171
  ) {
159
172
  const buildBasePath = `/home/dd`;
160
173
  const repoName = `engine-${deployId.split('-')[1]}`;
@@ -163,10 +176,9 @@ class UnderpostStartUp {
163
176
  shellExec(`mkdir -p ${buildBasePath}/engine`);
164
177
  shellExec(`cd ${buildBasePath} && sudo cp -a ./${repoName}/. ./engine`);
165
178
  shellExec(`cd ${buildBasePath} && sudo rm -rf ./${repoName}`);
166
- shellExec(`cd ${buildBasePath}/engine && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}-private`);
167
- shellExec(`cd ${buildBasePath}/engine && sudo mv ./${repoName}-private ./engine-private`);
168
179
  }
169
180
  shellCd(`${buildBasePath}/engine`);
181
+ Underpost.repo.privateEngineRepoFactory(deployId);
170
182
  shellExec(options?.underpostQuicklyInstall ? `underpost install` : `npm install`);
171
183
  shellExec(`node bin env ${deployId} ${env}`);
172
184
  if (fs.existsSync('./engine-private/itc-scripts')) {
@@ -174,7 +186,8 @@ class UnderpostStartUp {
174
186
  for (const itcScript of itcScripts)
175
187
  if (itcScript.match(deployId)) shellExec(`node ./engine-private/itc-scripts/${itcScript}`);
176
188
  }
177
- shellExec(`node bin client ${deployId}`);
189
+ if (options.pullBundle === true) shellExec(`node bin run pull-bundle --deploy-id ${deployId}`);
190
+ else if (!options.skipFullBuild) shellExec(`node bin client ${deployId}`);
178
191
  },
179
192
  /**
180
193
  * Runs a deployment.
@@ -197,6 +210,7 @@ class UnderpostStartUp {
197
210
  shellExec(`node bin env ${deployId} ${env}`);
198
211
  shellExec(`npm ${runCmd} ${deployId}`, { async: true });
199
212
  await awaitDeployMonitor(true);
213
+ if (env === 'production' && Underpost.env.isInsideContainer()) Underpost.secret.globalSecretClean();
200
214
  Underpost.env.set('container-status', `${deployId}-${env}-running-deployment`);
201
215
  },
202
216
  };
@@ -1,293 +1,199 @@
1
1
  /**
2
- * Module for managing Valkey
2
+ * Valkey connection and key-value store module.
3
+ *
4
+ * Responsibilities:
5
+ * - Manage per-instance Valkey connections keyed by `${host}${path}`.
6
+ * - Provide a thin, typed CRUD surface: get / set / del / update.
7
+ * - Expose connection status helpers.
8
+ *
9
+ * Out of scope: domain model factories, DTO projection — those belong in
10
+ * their respective service modules (e.g. guest.service.js).
11
+ *
3
12
  * @module src/server/valkey.js
4
13
  * @namespace ValkeyService
5
14
  */
6
-
7
15
  import Valkey from 'iovalkey';
8
- import mongoose from 'mongoose';
9
- import { hashPassword } from './auth.js';
10
16
  import { loggerFactory } from './logger.js';
11
17
 
12
18
  const logger = loggerFactory(import.meta);
13
19
 
14
- // Per-instance registries keyed by `${host}${path}`
20
+ // ─── Instance registry ────────────────────────────────────────────────────────
21
+
22
+ /** @type {Record<string, import('iovalkey').default>} */
15
23
  const ValkeyInstances = {};
16
- const DummyStores = {}; // in-memory Maps per instance
17
- const ValkeyStatus = {}; // 'connected' | 'dummy' | 'error' | undefined
24
+
25
+ /** @type {Record<string, 'connected' | 'reconnecting' | 'error'>} */
26
+ const ValkeyStatus = {};
18
27
 
19
28
  /**
20
- * Checks if any Valkey instance is connected.
21
- * This is a backward-compatible overall flag.
22
- * @returns {boolean} True if any instance has a 'connected' status.
23
- * @memberof ValkeyService
29
+ * Derives the registry key from an instance descriptor.
30
+ * @param {{ host?: string, path?: string }} opts
31
+ * @returns {string}
24
32
  */
25
- const isValkeyEnable = () => Object.values(ValkeyStatus).some((s) => s === 'connected');
33
+ const _instanceKey = (opts = {}) => `${opts.host || ''}${opts.path || ''}`;
34
+
35
+ // ─── Connection ───────────────────────────────────────────────────────────────
26
36
 
27
37
  /**
28
- * Generates a unique key for a Valkey instance based on its host and path.
29
- * @param {object} [opts={ host: '', path: '' }] - The instance options.
30
- * @param {string} [opts.host=''] - The host of the instance.
31
- * @param {string} [opts.path=''] - The path of the instance.
32
- * @returns {string} The instance key.
33
- * @private
38
+ * Returns true when at least one Valkey instance is connected.
39
+ * @returns {boolean}
34
40
  * @memberof ValkeyService
35
41
  */
36
- const _instanceKey = (opts = { host: '', path: '' }) => `${opts.host || ''}${opts.path || ''}`;
42
+ const isValkeyEnable = () => Object.values(ValkeyStatus).some((s) => s === 'connected');
37
43
 
38
44
  /**
39
- * Creates and manages a connection to a Valkey server for a given instance.
40
- * It sets up a client, attaches event listeners for connection status, and implements a fallback to an in-memory dummy store if the connection fails.
41
- * @param {object} [instance={ host: '', path: '' }] - The instance identifier.
42
- * @param {string} [instance.host=''] - The host of the instance.
43
- * @param {string} [instance.path=''] - The path of the instance.
44
- * @param {object} [valkeyServerConnectionOptions={ host: '', path: '' }] - Connection options for the iovalkey client.
45
- * @returns {Promise<Valkey|undefined>} A promise that resolves to the Valkey client instance, or undefined if creation fails.
45
+ * Creates a Valkey client for the given instance and waits for connectivity.
46
+ * Throws on connection failure callers decide whether to abort or continue
47
+ * without Valkey.
48
+ *
49
+ * @param {{ host?: string, path?: string }} instance - Registry key descriptor.
50
+ * @param {{ host?: string, port?: number }} connectionOptions - iovalkey connection options.
51
+ * @returns {Promise<import('iovalkey').default>}
46
52
  * @memberof ValkeyService
47
53
  */
48
- const createValkeyConnection = async (
49
- instance = { host: '', path: '' },
50
- valkeyServerConnectionOptions = { host: '', path: '' },
51
- ) => {
54
+ const createValkeyConnection = async (instance = {}, connectionOptions = {}) => {
52
55
  const key = _instanceKey(instance);
53
- // Initialize dummy store for the instance
54
- if (!DummyStores[key]) DummyStores[key] = new Map();
55
56
 
56
- try {
57
- const client = await ValkeyAPI.valkeyClientFactory(valkeyServerConnectionOptions);
58
-
59
- // Attach listeners for visibility
60
- client.on?.('ready', () => {
61
- ValkeyStatus[key] = 'connected';
62
- logger.info('Valkey connected', { instance, status: ValkeyStatus[key] });
63
- });
64
- client.on?.('error', (err) => {
65
- // Switch to dummy if not yet connected
66
- if (ValkeyStatus[key] !== 'connected') {
67
- ValkeyStatus[key] = 'dummy';
68
- } else {
69
- ValkeyStatus[key] = 'error';
70
- }
71
- logger.warn('Valkey error', { err: err?.message, instance, status: ValkeyStatus[key] });
72
- });
73
- client.on?.('end', () => {
74
- if (ValkeyStatus[key] !== 'dummy') ValkeyStatus[key] = 'error';
75
- logger.warn('Valkey connection ended', { instance, status: ValkeyStatus[key] });
76
- });
77
-
78
- // Probe connectivity with a short timeout
79
- const probe = async () => {
57
+ const client = new Valkey({
58
+ port: connectionOptions.port ?? undefined,
59
+ host: connectionOptions.host ?? undefined,
60
+ // Retry indefinitely with capped exponential backoff (1 s → 30 s)
61
+ retryStrategy: (attempt) => Math.min(attempt * 1000, 30000),
62
+ // Fail commands immediately when not connected; do NOT queue them
63
+ maxRetriesPerRequest: 0,
64
+ });
65
+
66
+ client.on('ready', () => {
67
+ ValkeyStatus[key] = 'connected';
68
+ logger.info('Valkey connected', { instance });
69
+ });
70
+ client.on('error', (err) => {
71
+ ValkeyStatus[key] = 'error';
72
+ logger.error('Valkey error', { err: err?.message, instance });
73
+ });
74
+ client.on('reconnecting', () => {
75
+ ValkeyStatus[key] = 'reconnecting';
76
+ logger.warn('Valkey reconnecting...', { instance });
77
+ });
78
+ client.on('end', () => {
79
+ ValkeyStatus[key] = 'error';
80
+ logger.warn('Valkey connection ended', { instance });
81
+ });
82
+
83
+ // Verify connectivity with a probe before marking ready
84
+ await Promise.race([
85
+ (async () => {
80
86
  try {
81
- // basic ping via SET/GET roundtrip
82
- const probeKey = `__vk_probe_${Date.now()}`;
83
- await client.set(probeKey, '1');
84
- await client.get(probeKey);
87
+ const probe = `__vk_probe_${Date.now()}`;
88
+ await client.set(probe, '1');
89
+ await client.get(probe);
90
+ await client.del(probe);
85
91
  ValkeyStatus[key] = 'connected';
86
- } catch (e) {
87
- ValkeyStatus[key] = 'dummy';
88
- logger.warn('Valkey probe failed, falling back to dummy', { instance, error: e?.message });
92
+ } catch {
93
+ ValkeyStatus[key] = 'error';
89
94
  }
90
- };
91
-
92
- // Race with timeout to avoid hanging
93
- await Promise.race([probe(), new Promise((resolve) => setTimeout(resolve, 1000))]);
95
+ })(),
96
+ new Promise((resolve) => setTimeout(resolve, 1500)),
97
+ ]);
94
98
 
95
- ValkeyInstances[key] = client;
96
- if (!ValkeyStatus[key]) ValkeyStatus[key] = 'dummy';
97
- } catch (err) {
98
- ValkeyStatus[key] = 'dummy';
99
- logger.warn('Valkey client creation failed, using dummy', { instance, error: err?.message });
100
- }
101
-
102
- return ValkeyInstances[key];
99
+ ValkeyInstances[key] = client;
100
+ logger.info('Valkey instance registered', { key, status: ValkeyStatus[key] });
101
+ return client;
103
102
  };
104
103
 
104
+ // ─── Internal client resolver ─────────────────────────────────────────────────
105
+
105
106
  /**
106
- * Factory function to create a Data Transfer Object (DTO) from a payload.
107
- * It filters the payload to include only the keys specified in the `select` object.
108
- * @param {object} payload - The source object.
109
- * @param {object} select - An object where keys are field names and values are 1 to include them.
110
- * @returns {object} A new object containing only the selected fields from the payload.
111
- * @memberof ValkeyService
107
+ * Resolves the connected client for an instance or throws.
108
+ * @param {{ host?: string, path?: string }} options
109
+ * @returns {import('iovalkey').default}
112
110
  */
113
- const selectDtoFactory = (payload, select) => {
114
- const result = {};
115
- for (const key of Object.keys(select)) {
116
- if (select[key] === 1 && key in payload) result[key] = payload[key];
111
+ const _client = (options) => {
112
+ const k = _instanceKey(options);
113
+ const client = ValkeyInstances[k];
114
+ if (!client || ValkeyStatus[k] !== 'connected') {
115
+ throw new Error(`Valkey instance not connected: ${k}`);
117
116
  }
118
- return result;
117
+ return client;
119
118
  };
120
119
 
121
- /**
122
- * Factory function to create a new Valkey client instance.
123
- * @param {object} options - Connection options for the iovalkey client.
124
- * @returns {Promise<Valkey>} A promise that resolves to a new Valkey client.
125
- * @memberof ValkeyService
126
- */
127
- const valkeyClientFactory = async (options) => {
128
- const valkey = new Valkey({
129
- port: options?.port ? options.port : undefined,
130
- host: options?.host ? options.host : undefined,
131
- // Keep retry strategy minimal; state handled in createValkeyConnection
132
- retryStrategy: (attempt) => {
133
- if (attempt === 1) return undefined; // stop aggressive retries early
134
- return 1000; // retry interval if library continues
135
- },
136
- }); // Connect to 127.0.0.1:6379
137
- // new Valkey(6380); // 127.0.0.1:6380
138
- // new Valkey(6379, '192.168.1.1'); // 192.168.1.1:6379
139
- // new Valkey('/tmp/redis.sock');
140
- // new Valkey({
141
- // port: 6379, // Valkey port
142
- // host: '127.0.0.1', // Valkey host
143
- // username: 'default', // needs Valkey >= 6
144
- // password: 'my-top-secret',
145
- // db: 0, // Defaults to 0
146
- // });
147
- return valkey;
148
- };
120
+ // ─── CRUD ─────────────────────────────────────────────────────────────────────
149
121
 
150
122
  /**
151
- * Retrieves an object from Valkey by key for a specific instance.
152
- * If the Valkey client is not connected or an error occurs, it falls back to the dummy in-memory store.
153
- * It automatically parses JSON strings.
154
- * @param {object} [options={ host: '', path: '' }] - The instance identifier.
155
- * @param {string} [key=''] - The key of the object to retrieve.
156
- * @returns {Promise<object|string|null>} A promise that resolves to the retrieved object, string, or null if not found.
123
+ * Retrieves and JSON-parses a value by key.
124
+ * Returns null when the key does not exist.
125
+ *
126
+ * @param {{ host?: string, path?: string }} options
127
+ * @param {string} key
128
+ * @returns {Promise<object | string | null>}
157
129
  * @memberof ValkeyService
158
130
  */
159
- const getValkeyObject = async (options = { host: '', path: '' }, key = '') => {
160
- const k = _instanceKey(options);
161
- const status = ValkeyStatus[k];
131
+ const get = async (options, key) => {
132
+ const raw = await _client(options).get(key);
133
+ if (raw == null) return null;
162
134
  try {
163
- if (status === 'connected' && ValkeyInstances[k]) {
164
- const value = await ValkeyInstances[k].get(key);
165
- if (value == null) return null;
166
- try {
167
- return JSON.parse(value);
168
- } catch {
169
- // not JSON, return raw string
170
- return value;
171
- }
172
- }
173
- } catch (err) {
174
- logger.warn('Valkey get failed, using dummy', { key, err: err?.message });
135
+ return JSON.parse(raw);
136
+ } catch {
137
+ return raw;
175
138
  }
176
- // Dummy fallback returns stored value as-is (string or object)
177
- return DummyStores[k]?.get(key) ?? null;
178
139
  };
179
140
 
180
141
  /**
181
- * Sets an object or string in Valkey for a specific instance.
182
- * If the Valkey client is not connected, it writes to the in-memory dummy store instead.
183
- * Objects are automatically stringified.
184
- * @param {object} [options={ host: '', path: '' }] - The instance identifier.
185
- * @param {string} [key=''] - The key under which to store the payload.
186
- * @param {object|string} [payload={}] - The data to store.
187
- * @returns {Promise<string>} A promise that resolves to 'OK' on success.
142
+ * Serialises and stores a value by key.
143
+ * Pass `ttlMs` to set an expiry in milliseconds.
144
+ *
145
+ * @param {{ host?: string, path?: string }} options
146
+ * @param {string} key
147
+ * @param {object | string} payload
148
+ * @param {number} [ttlMs]
149
+ * @returns {Promise<string>} Resolves to 'OK'.
188
150
  * @memberof ValkeyService
189
151
  */
190
- const setValkeyObject = async (options = { host: '', path: '' }, key = '', payload = {}) => {
191
- const k = _instanceKey(options);
192
- const isString = typeof payload === 'string';
193
- const value = isString ? payload : JSON.stringify(payload);
194
- try {
195
- if (ValkeyStatus[k] === 'connected' && ValkeyInstances[k]) {
196
- return await ValkeyInstances[k].set(key, value);
197
- }
198
- } catch (err) {
199
- logger.warn('Valkey set failed, writing to dummy', { key, err: err?.message });
200
- }
201
- if (!DummyStores[k]) DummyStores[k] = new Map();
202
- // Store raw string or object accordingly
203
- DummyStores[k].set(key, isString ? payload : payload);
204
- return 'OK';
152
+ const set = async (options, key, payload, ttlMs) => {
153
+ const value = typeof payload === 'string' ? payload : JSON.stringify(payload);
154
+ if (ttlMs) return _client(options).set(key, value, 'PX', ttlMs);
155
+ return _client(options).set(key, value);
205
156
  };
206
157
 
207
158
  /**
208
- * Updates an existing object in Valkey by merging it with a new payload.
209
- * It retrieves the current object, merges it with the new payload, and sets the updated object back.
210
- * It also updates the `updatedAt` timestamp.
211
- * @param {object} [options={ host: '', path: '' }] - The instance identifier.
212
- * @param {string} [key=''] - The key of the object to update.
213
- * @param {object} [payload={}] - The new data to merge into the object.
214
- * @returns {Promise<string>} A promise that resolves to the result of the set operation.
159
+ * Deletes a key.
160
+ *
161
+ * @param {{ host?: string, path?: string }} options
162
+ * @param {string} key
163
+ * @returns {Promise<number>}
215
164
  * @memberof ValkeyService
216
165
  */
217
- const updateValkeyObject = async (options = { host: '', path: '' }, key = '', payload = {}) => {
218
- let base = await getValkeyObject(options, key);
219
- if (typeof base !== 'object' || base === null) base = {};
220
- base.updatedAt = new Date().toISOString();
221
- return await setValkeyObject(options, key, { ...base, ...payload });
222
- };
166
+ const del = async (options, key) => _client(options).del(key);
223
167
 
224
168
  /**
225
- * Factory function to create a new object based on a model schema.
226
- * It generates a new object with default properties like `_id`, `createdAt`, and `updatedAt`,
227
- * and model-specific properties.
228
- * @param {object} [options={ host: 'localhost', path: '', object: {} }] - Options for object creation.
229
- * @param {string} [options.host='localhost'] - The host context for the object.
230
- * @param {object} [options.object={}] - An initial object to extend.
231
- * @param {string} [model=''] - The name of the model schema to use (e.g., 'user').
232
- * @returns {Promise<object>} A promise that resolves to the newly created object.
169
+ * Shallow-merges `payload` into the existing object stored at `key`
170
+ * and persists the result. The `updatedAt` timestamp is refreshed automatically.
171
+ *
172
+ * @param {{ host?: string, path?: string }} options
173
+ * @param {string} key
174
+ * @param {object} payload
175
+ * @returns {Promise<string>} Resolves to 'OK'.
233
176
  * @memberof ValkeyService
234
177
  */
235
- const valkeyObjectFactory = async (options = { host: 'localhost', path: '', object: {} }, model = '') => {
236
- const idoDate = new Date().toISOString();
237
- options.object = options.object || {};
238
- const { object } = options;
239
- const _id = new mongoose.Types.ObjectId().toString();
240
- object._id = _id;
241
- object.createdAt = idoDate;
242
- object.updatedAt = idoDate;
243
- switch (model) {
244
- case 'user': {
245
- const role = 'guest';
246
- object._id = `${role}${_id}`;
247
- return {
248
- ...object,
249
- username: `${role}${_id.slice(-5)}`,
250
- email: `${_id}@${options.host}`,
251
- password: hashPassword(process.env.JWT_SECRET),
252
- role,
253
- failedLoginAttempts: 0,
254
- phoneNumbers: [],
255
- publicKey: [],
256
- profileImageId: null,
257
- emailConfirmed: false,
258
- recoverTimeOut: null,
259
- lastLoginDate: null,
260
- activeSessions: [],
261
- };
262
- }
263
- default:
264
- throw new Error(`model schema not found: ${model}`);
265
- }
178
+ const update = async (options, key, payload) => {
179
+ const base = (await get(options, key)) ?? {};
180
+ return set(options, key, { ...base, ...payload, updatedAt: new Date().toISOString() });
266
181
  };
267
182
 
183
+ // ─── Public API class ─────────────────────────────────────────────────────────
184
+
268
185
  /**
269
- * A collection of Valkey-related API functions.
270
- * @type {object}
271
- * @memberof ValkeyServiceService
186
+ * Namespace grouping all Valkey operations.
187
+ * @memberof ValkeyService
272
188
  */
273
- const ValkeyAPI = {
274
- valkeyClientFactory,
275
- selectDtoFactory,
276
- getValkeyObject,
277
- setValkeyObject,
278
- valkeyObjectFactory,
279
- updateValkeyObject,
280
- createValkeyConnection,
281
- };
282
-
283
- export {
284
- valkeyClientFactory,
285
- selectDtoFactory,
286
- getValkeyObject,
287
- setValkeyObject,
288
- valkeyObjectFactory,
289
- updateValkeyObject,
290
- isValkeyEnable,
291
- createValkeyConnection,
292
- ValkeyAPI,
293
- };
189
+ class ValkeyAPI {
190
+ /** @param {{ host?: string, path?: string }} options */
191
+ static isConnected = (options) => ValkeyStatus[_instanceKey(options)] === 'connected';
192
+ static get = get;
193
+ static set = set;
194
+ static del = del;
195
+ static update = update;
196
+ static createValkeyConnection = createValkeyConnection;
197
+ }
198
+
199
+ export { isValkeyEnable, createValkeyConnection, get, set, del, update, ValkeyAPI };