@underpostnet/cyberia 3.2.80

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 (821) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.example +144 -0
  3. package/.github/workflows/cyberia-client.cd.yml +40 -0
  4. package/.github/workflows/cyberia-server.cd.yml +40 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +71 -0
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +70 -0
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +71 -0
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +71 -0
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +53 -0
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +53 -0
  11. package/.github/workflows/engine-cyberia.cd.yml +157 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +125 -0
  13. package/.github/workflows/ghpkg.ci.yml +160 -0
  14. package/.github/workflows/gitlab.ci.yml +20 -0
  15. package/.github/workflows/hardhat.ci.yml +82 -0
  16. package/.github/workflows/npmpkg.ci.yml +126 -0
  17. package/.github/workflows/publish.ci.yml +87 -0
  18. package/.github/workflows/publish.cyberia.ci.yml +79 -0
  19. package/.github/workflows/pwa-microservices-template-page.cd.yml +65 -0
  20. package/.github/workflows/pwa-microservices-template-test.ci.yml +33 -0
  21. package/.github/workflows/release.cd.yml +46 -0
  22. package/.nycrc +9 -0
  23. package/.prettierignore +12 -0
  24. package/.prettierrc +9 -0
  25. package/.vscode/extensions.json +10 -0
  26. package/.vscode/settings.json +26 -0
  27. package/CHANGELOG.md +2516 -0
  28. package/CLI-HELP.md +1099 -0
  29. package/Dockerfile +161 -0
  30. package/Dockerfile.dev +161 -0
  31. package/Dockerfile.test +165 -0
  32. package/LICENSE +21 -0
  33. package/README.md +259 -0
  34. package/baremetal/commission-workflows.json +211 -0
  35. package/baremetal/packer-workflows.json +24 -0
  36. package/bin/build.js +261 -0
  37. package/bin/build.template.js +33 -0
  38. package/bin/cyberia.js +5627 -0
  39. package/bin/deploy.js +1547 -0
  40. package/bin/index.js +5627 -0
  41. package/bump.config.js +27 -0
  42. package/compose.env +144 -0
  43. package/conf.js +952 -0
  44. package/deployment.yaml +418 -0
  45. package/docker-compose.yml +434 -0
  46. package/examples/static-page/README.md +150 -0
  47. package/examples/static-page/ssr-components/CustomPage.js +554 -0
  48. package/examples/static-page/static-config-example.json +57 -0
  49. package/hardhat/.env.example +31 -0
  50. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  51. package/hardhat/deployments/.gitkeep +0 -0
  52. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  53. package/hardhat/hardhat.config.js +136 -0
  54. package/hardhat/ignition/modules/.gitkeep +0 -0
  55. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  56. package/hardhat/networks/besu-object-layer.network.json +138 -0
  57. package/hardhat/package-lock.json +2871 -0
  58. package/hardhat/package.json +43 -0
  59. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  60. package/hardhat/test/ObjectLayerToken.js +696 -0
  61. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  62. package/hardhat/types/ethers-contracts/common.ts +92 -0
  63. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  64. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  65. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  66. package/hardhat/types/ethers-contracts/index.ts +6 -0
  67. package/ipfs/configure-ipfs.sh +13 -0
  68. package/jsconfig.json +9 -0
  69. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +48 -0
  70. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +48 -0
  71. package/manifests/deployment/adminer/deployment.yaml +32 -0
  72. package/manifests/deployment/adminer/kustomization.yaml +7 -0
  73. package/manifests/deployment/adminer/service.yaml +13 -0
  74. package/manifests/deployment/dd-cyberia-development/deployment.yaml +418 -0
  75. package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
  76. package/manifests/deployment/dd-cyberia-development/proxy.yaml +189 -0
  77. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +164 -0
  78. package/manifests/deployment/dd-default-development/deployment.yaml +163 -0
  79. package/manifests/deployment/dd-default-development/proxy.yaml +46 -0
  80. package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
  81. package/manifests/deployment/fastapi/backend-service.yml +19 -0
  82. package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
  83. package/manifests/deployment/fastapi/frontend-service.yml +15 -0
  84. package/manifests/deployment/fastapi/initial_data.sh +8 -0
  85. package/manifests/deployment/kafka/deployment.yaml +67 -0
  86. package/manifests/deployment/mongo-express/deployment.yaml +62 -0
  87. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  88. package/manifests/deployment/playwright/deployment.yaml +52 -0
  89. package/manifests/deployment/spark/spark-pi-py.yaml +20 -0
  90. package/manifests/deployment/tensorflow/tf-gpu-test.yaml +63 -0
  91. package/manifests/envoy-service-nodeport.yaml +22 -0
  92. package/manifests/grafana/deployment.yaml +64 -0
  93. package/manifests/grafana/kustomization.yaml +7 -0
  94. package/manifests/grafana/pvc.yaml +12 -0
  95. package/manifests/grafana/service.yaml +14 -0
  96. package/manifests/grafana/storage-class.yaml +9 -0
  97. package/manifests/ipfs/configmap.yaml +64 -0
  98. package/manifests/ipfs/headless-service.yaml +35 -0
  99. package/manifests/ipfs/kustomization.yaml +8 -0
  100. package/manifests/ipfs/statefulset.yaml +149 -0
  101. package/manifests/ipfs/storage-class.yaml +9 -0
  102. package/manifests/kind-config-dev.yaml +20 -0
  103. package/manifests/kind-config.yaml +12 -0
  104. package/manifests/kubeadm-calico-config.yaml +14 -0
  105. package/manifests/letsencrypt-prod.yaml +14 -0
  106. package/manifests/lxd/lxd-admin-profile.yaml +26 -0
  107. package/manifests/lxd/lxd-preseed.yaml +30 -0
  108. package/manifests/mariadb/kustomization.yaml +9 -0
  109. package/manifests/mariadb/pv.yaml +12 -0
  110. package/manifests/mariadb/pvc.yaml +10 -0
  111. package/manifests/mariadb/service.yaml +10 -0
  112. package/manifests/mariadb/statefulset.yaml +56 -0
  113. package/manifests/mariadb/storage-class.yaml +10 -0
  114. package/manifests/mongodb/headless-service.yaml +10 -0
  115. package/manifests/mongodb/kustomization.yaml +11 -0
  116. package/manifests/mongodb/pv-pvc.yaml +59 -0
  117. package/manifests/mongodb/statefulset.yaml +113 -0
  118. package/manifests/mongodb/storage-class.yaml +9 -0
  119. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  120. package/manifests/mongodb-4.4/kustomization.yaml +9 -0
  121. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  122. package/manifests/mongodb-4.4/pv-pvc.yaml +19 -0
  123. package/manifests/mongodb-4.4/service-deployment.yaml +61 -0
  124. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  125. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  126. package/manifests/mysql/kustomization.yaml +7 -0
  127. package/manifests/mysql/pv-pvc.yaml +27 -0
  128. package/manifests/mysql/statefulset.yaml +55 -0
  129. package/manifests/postgresql/configmap.yaml +9 -0
  130. package/manifests/postgresql/kustomization.yaml +10 -0
  131. package/manifests/postgresql/pv.yaml +15 -0
  132. package/manifests/postgresql/pvc.yaml +13 -0
  133. package/manifests/postgresql/service.yaml +10 -0
  134. package/manifests/postgresql/statefulset.yaml +37 -0
  135. package/manifests/prometheus/deployment.yaml +82 -0
  136. package/manifests/pv-pvc-dd.yaml +34 -0
  137. package/manifests/valkey/kustomization.yaml +7 -0
  138. package/manifests/valkey/service.yaml +10 -0
  139. package/manifests/valkey/statefulset.yaml +37 -0
  140. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  141. package/mongodb/entrypoint.sh +76 -0
  142. package/nginx.conf +128 -0
  143. package/nodemon.json +6 -0
  144. package/package.json +101 -0
  145. package/packer/images/Rocky9Amd64/Makefile +62 -0
  146. package/packer/images/Rocky9Amd64/QUICKSTART.md +113 -0
  147. package/packer/images/Rocky9Amd64/README.md +122 -0
  148. package/packer/images/Rocky9Amd64/http/rocky9.ks.pkrtpl.hcl +114 -0
  149. package/packer/images/Rocky9Amd64/rocky9.pkr.hcl +164 -0
  150. package/packer/images/Rocky9Arm64/Makefile +69 -0
  151. package/packer/images/Rocky9Arm64/README.md +122 -0
  152. package/packer/images/Rocky9Arm64/http/rocky9.ks.pkrtpl.hcl +114 -0
  153. package/packer/images/Rocky9Arm64/rocky9.pkr.hcl +171 -0
  154. package/packer/scripts/fuse-nbd +64 -0
  155. package/packer/scripts/fuse-tar-root +63 -0
  156. package/proxy.yaml +189 -0
  157. package/pv-pvc.yaml +164 -0
  158. package/scripts/device-scan.sh +65 -0
  159. package/scripts/disk-clean.sh +182 -0
  160. package/scripts/disk-devices.sh +13 -0
  161. package/scripts/gen-fqdns.sh +14 -0
  162. package/scripts/gpu-diag.sh +19 -0
  163. package/scripts/ip-info.sh +118 -0
  164. package/scripts/ipxe-setup.sh +200 -0
  165. package/scripts/k3s-node-setup.sh +124 -0
  166. package/scripts/kubeadm-node-setup.sh +317 -0
  167. package/scripts/link-local-underpost-cli.sh +6 -0
  168. package/scripts/lxd-vm-setup.sh +208 -0
  169. package/scripts/maas-nat-firewalld.sh +145 -0
  170. package/scripts/maas-setup.sh +135 -0
  171. package/scripts/maas-upload-boot-resource.sh +183 -0
  172. package/scripts/nat-iptables.sh +111 -0
  173. package/scripts/nvim.sh +91 -0
  174. package/scripts/packer-init-vars-file.sh +40 -0
  175. package/scripts/packer-setup.sh +289 -0
  176. package/scripts/ports-ls.sh +33 -0
  177. package/scripts/quick-tftp.sh +19 -0
  178. package/scripts/rhel-grpc-setup.sh +56 -0
  179. package/scripts/rocky-kickstart.sh +986 -0
  180. package/scripts/rocky-pwa.sh +200 -0
  181. package/scripts/rocky-setup.sh +106 -0
  182. package/scripts/rpmfusion-ffmpeg-setup.sh +32 -0
  183. package/scripts/ssl.sh +170 -0
  184. package/scripts/test-monitor.sh +248 -0
  185. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +30 -0
  186. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +155 -0
  187. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +39 -0
  188. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +382 -0
  189. package/src/api/core/core.controller.js +8 -0
  190. package/src/api/core/core.model.js +11 -0
  191. package/src/api/core/core.router.js +23 -0
  192. package/src/api/core/core.service.js +30 -0
  193. package/src/api/crypto/crypto.controller.js +10 -0
  194. package/src/api/crypto/crypto.model.js +23 -0
  195. package/src/api/crypto/crypto.router.js +23 -0
  196. package/src/api/crypto/crypto.service.js +64 -0
  197. package/src/api/cyberia-action/cyberia-action.controller.js +8 -0
  198. package/src/api/cyberia-action/cyberia-action.model.js +79 -0
  199. package/src/api/cyberia-action/cyberia-action.router.js +21 -0
  200. package/src/api/cyberia-action/cyberia-action.service.js +58 -0
  201. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +27 -0
  202. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +100 -0
  203. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +70 -0
  204. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  205. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +8 -0
  206. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  207. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +20 -0
  208. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +57 -0
  209. package/src/api/cyberia-entity/cyberia-entity.controller.js +6 -0
  210. package/src/api/cyberia-entity/cyberia-entity.model.js +25 -0
  211. package/src/api/cyberia-entity/cyberia-entity.router.js +17 -0
  212. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  213. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +6 -0
  214. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
  215. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -0
  216. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
  217. package/src/api/cyberia-instance/cyberia-fallback-world.js +337 -0
  218. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +57 -0
  219. package/src/api/cyberia-instance/cyberia-instance-map.service.js +583 -0
  220. package/src/api/cyberia-instance/cyberia-instance.controller.js +42 -0
  221. package/src/api/cyberia-instance/cyberia-instance.model.js +117 -0
  222. package/src/api/cyberia-instance/cyberia-instance.router.js +75 -0
  223. package/src/api/cyberia-instance/cyberia-instance.service.js +190 -0
  224. package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
  225. package/src/api/cyberia-instance/cyberia-world-generator.js +618 -0
  226. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +6 -0
  227. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +200 -0
  228. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +17 -0
  229. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
  230. package/src/api/cyberia-map/cyberia-map.controller.js +6 -0
  231. package/src/api/cyberia-map/cyberia-map.model.js +33 -0
  232. package/src/api/cyberia-map/cyberia-map.router.js +19 -0
  233. package/src/api/cyberia-map/cyberia-map.service.js +76 -0
  234. package/src/api/cyberia-quest/cyberia-quest.controller.js +9 -0
  235. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  236. package/src/api/cyberia-quest/cyberia-quest.router.js +26 -0
  237. package/src/api/cyberia-quest/cyberia-quest.service.js +97 -0
  238. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +6 -0
  239. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  240. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +21 -0
  241. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  242. package/src/api/cyberia-saga/cyberia-saga.controller.js +6 -0
  243. package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
  244. package/src/api/cyberia-saga/cyberia-saga.router.js +17 -0
  245. package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
  246. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +1076 -0
  247. package/src/api/cyberia-skill/cyberia-skill.controller.js +6 -0
  248. package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
  249. package/src/api/cyberia-skill/cyberia-skill.router.js +17 -0
  250. package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
  251. package/src/api/default/default.controller.js +6 -0
  252. package/src/api/default/default.model.js +20 -0
  253. package/src/api/default/default.router.js +21 -0
  254. package/src/api/default/default.service.js +42 -0
  255. package/src/api/document/document.controller.js +9 -0
  256. package/src/api/document/document.model.js +95 -0
  257. package/src/api/document/document.router.js +32 -0
  258. package/src/api/document/document.service.js +633 -0
  259. package/src/api/file/file.controller.js +15 -0
  260. package/src/api/file/file.model.js +127 -0
  261. package/src/api/file/file.ref.json +39 -0
  262. package/src/api/file/file.router.js +36 -0
  263. package/src/api/file/file.service.js +499 -0
  264. package/src/api/instance/instance.controller.js +8 -0
  265. package/src/api/instance/instance.model.js +34 -0
  266. package/src/api/instance/instance.router.js +27 -0
  267. package/src/api/instance/instance.service.js +75 -0
  268. package/src/api/ipfs/ipfs.controller.js +8 -0
  269. package/src/api/ipfs/ipfs.model.js +77 -0
  270. package/src/api/ipfs/ipfs.router.js +26 -0
  271. package/src/api/ipfs/ipfs.service.js +145 -0
  272. package/src/api/object-layer/object-layer.controller.js +18 -0
  273. package/src/api/object-layer/object-layer.model.js +200 -0
  274. package/src/api/object-layer/object-layer.router.js +729 -0
  275. package/src/api/object-layer/object-layer.service.js +894 -0
  276. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +6 -0
  277. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +93 -0
  278. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +17 -0
  279. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +46 -0
  280. package/src/api/test/test.controller.js +14 -0
  281. package/src/api/test/test.model.js +14 -0
  282. package/src/api/test/test.router.js +23 -0
  283. package/src/api/test/test.service.js +35 -0
  284. package/src/api/types.js +24 -0
  285. package/src/api/user/guest.service.js +100 -0
  286. package/src/api/user/postman_collection.json +216 -0
  287. package/src/api/user/user.build.js +16 -0
  288. package/src/api/user/user.controller.js +35 -0
  289. package/src/api/user/user.model.js +142 -0
  290. package/src/api/user/user.router.js +367 -0
  291. package/src/api/user/user.service.js +582 -0
  292. package/src/api.js +23 -0
  293. package/src/cli/baremetal.js +3947 -0
  294. package/src/cli/cloud-init.js +673 -0
  295. package/src/cli/cluster.js +1395 -0
  296. package/src/cli/db.js +1533 -0
  297. package/src/cli/deploy.js +1542 -0
  298. package/src/cli/docker-compose.js +802 -0
  299. package/src/cli/env.js +177 -0
  300. package/src/cli/fs.js +380 -0
  301. package/src/cli/image.js +389 -0
  302. package/src/cli/index.js +1059 -0
  303. package/src/cli/ipfs.js +182 -0
  304. package/src/cli/kickstart.js +271 -0
  305. package/src/cli/kubectl.js +214 -0
  306. package/src/cli/lxd.js +1232 -0
  307. package/src/cli/monitor.js +659 -0
  308. package/src/cli/release.js +595 -0
  309. package/src/cli/repository.js +1969 -0
  310. package/src/cli/run.js +3326 -0
  311. package/src/cli/secrets.js +151 -0
  312. package/src/cli/ssh.js +975 -0
  313. package/src/cli/static.js +653 -0
  314. package/src/cli/system.js +332 -0
  315. package/src/cli/test.js +176 -0
  316. package/src/client/Cryptokoyn.index.js +30 -0
  317. package/src/client/CyberiaPortal.index.js +31 -0
  318. package/src/client/Default.index.js +77 -0
  319. package/src/client/Itemledger.index.js +35 -0
  320. package/src/client/Underpost.index.js +31 -0
  321. package/src/client/components/core/404.js +20 -0
  322. package/src/client/components/core/500.js +20 -0
  323. package/src/client/components/core/Account.js +630 -0
  324. package/src/client/components/core/AgGrid.js +238 -0
  325. package/src/client/components/core/Alert.js +76 -0
  326. package/src/client/components/core/AppStore.js +69 -0
  327. package/src/client/components/core/Auth.js +353 -0
  328. package/src/client/components/core/Badge.js +26 -0
  329. package/src/client/components/core/Blockchain.js +41 -0
  330. package/src/client/components/core/Blog.js +9 -0
  331. package/src/client/components/core/BtnIcon.js +109 -0
  332. package/src/client/components/core/CalendarCore.js +437 -0
  333. package/src/client/components/core/Chat.js +62 -0
  334. package/src/client/components/core/ClientEvents.js +163 -0
  335. package/src/client/components/core/ColorPaletteElement.js +309 -0
  336. package/src/client/components/core/CommonJs.js +1014 -0
  337. package/src/client/components/core/Content.js +349 -0
  338. package/src/client/components/core/Css.js +1134 -0
  339. package/src/client/components/core/CssCore.js +881 -0
  340. package/src/client/components/core/D3Chart.js +44 -0
  341. package/src/client/components/core/Docs.js +478 -0
  342. package/src/client/components/core/DropDown.js +321 -0
  343. package/src/client/components/core/EventBus.js +96 -0
  344. package/src/client/components/core/EventsUI.js +130 -0
  345. package/src/client/components/core/FileExplorer.js +1406 -0
  346. package/src/client/components/core/FullScreen.js +201 -0
  347. package/src/client/components/core/Input.js +537 -0
  348. package/src/client/components/core/Keyboard.js +80 -0
  349. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  350. package/src/client/components/core/LoadingAnimation.js +152 -0
  351. package/src/client/components/core/LogIn.js +212 -0
  352. package/src/client/components/core/LogOut.js +72 -0
  353. package/src/client/components/core/Logger.js +22 -0
  354. package/src/client/components/core/Modal.js +2956 -0
  355. package/src/client/components/core/NotificationManager.js +80 -0
  356. package/src/client/components/core/Pagination.js +252 -0
  357. package/src/client/components/core/Panel.js +1308 -0
  358. package/src/client/components/core/PanelForm.js +915 -0
  359. package/src/client/components/core/Polyhedron.js +947 -0
  360. package/src/client/components/core/PublicProfile.js +895 -0
  361. package/src/client/components/core/Recover.js +211 -0
  362. package/src/client/components/core/Responsive.js +146 -0
  363. package/src/client/components/core/RichText.js +33 -0
  364. package/src/client/components/core/Router.js +523 -0
  365. package/src/client/components/core/Scroll.js +76 -0
  366. package/src/client/components/core/SearchBox.js +1007 -0
  367. package/src/client/components/core/SignUp.js +153 -0
  368. package/src/client/components/core/SocketIo.js +163 -0
  369. package/src/client/components/core/SocketIoHandler.js +75 -0
  370. package/src/client/components/core/Stream.js +161 -0
  371. package/src/client/components/core/ToggleSwitch.js +89 -0
  372. package/src/client/components/core/ToolTip.js +78 -0
  373. package/src/client/components/core/Translate.js +694 -0
  374. package/src/client/components/core/Validator.js +140 -0
  375. package/src/client/components/core/VanillaJs.js +485 -0
  376. package/src/client/components/core/Wallet.js +95 -0
  377. package/src/client/components/core/WebComponent.js +44 -0
  378. package/src/client/components/core/Webhook.js +58 -0
  379. package/src/client/components/core/Worker.js +313 -0
  380. package/src/client/components/core/windowGetDimensions.js +269 -0
  381. package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +352 -0
  382. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  383. package/src/client/components/cryptokoyn/CssCryptokoyn.js +212 -0
  384. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +16 -0
  385. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +12 -0
  386. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  387. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +16 -0
  388. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +11 -0
  389. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +6 -0
  390. package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
  391. package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
  392. package/src/client/components/cyberia/InstanceEngineCyberia.js +1088 -0
  393. package/src/client/components/cyberia/InstanceSelectionView.js +900 -0
  394. package/src/client/components/cyberia/MapEngineCyberia.js +1976 -0
  395. package/src/client/components/cyberia/ObjectLayerEngine.js +1540 -0
  396. package/src/client/components/cyberia/ObjectLayerEngineModal.js +2420 -0
  397. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +1522 -0
  398. package/src/client/components/cyberia/SharedDefaultsCyberia.js +528 -0
  399. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +772 -0
  400. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  401. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +254 -0
  402. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +21 -0
  403. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +16 -0
  404. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +518 -0
  405. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +72 -0
  406. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +16 -0
  407. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +13 -0
  408. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +6 -0
  409. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +48 -0
  410. package/src/client/components/default/AppShellDefault.js +765 -0
  411. package/src/client/components/default/AppStoreDefault.js +5 -0
  412. package/src/client/components/default/CommonDefault.js +29 -0
  413. package/src/client/components/default/CssDefault.js +27 -0
  414. package/src/client/components/default/LogInDefault.js +16 -0
  415. package/src/client/components/default/LogOutDefault.js +12 -0
  416. package/src/client/components/default/RouterDefault.js +47 -0
  417. package/src/client/components/default/SettingsDefault.js +16 -0
  418. package/src/client/components/default/SignUpDefault.js +11 -0
  419. package/src/client/components/default/SocketIoDefault.js +6 -0
  420. package/src/client/components/default/TranslateDefault.js +7 -0
  421. package/src/client/components/itemledger/AppShellItemledger.js +353 -0
  422. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  423. package/src/client/components/itemledger/CssItemledger.js +212 -0
  424. package/src/client/components/itemledger/LogInItemledger.js +17 -0
  425. package/src/client/components/itemledger/LogOutItemledger.js +12 -0
  426. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  427. package/src/client/components/itemledger/SettingsItemledger.js +16 -0
  428. package/src/client/components/itemledger/SignUpItemledger.js +11 -0
  429. package/src/client/components/itemledger/SocketIoItemledger.js +6 -0
  430. package/src/client/components/itemledger/TranslateItemledger.js +7 -0
  431. package/src/client/components/underpost/AppShellUnderpost.js +691 -0
  432. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  433. package/src/client/components/underpost/CssUnderpost.js +281 -0
  434. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  435. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  436. package/src/client/components/underpost/LabGalleryUnderpost.js +79 -0
  437. package/src/client/components/underpost/LogInUnderpost.js +25 -0
  438. package/src/client/components/underpost/LogOutUnderpost.js +17 -0
  439. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  440. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  441. package/src/client/components/underpost/SignUpUnderpost.js +11 -0
  442. package/src/client/components/underpost/SocketIoUnderpost.js +6 -0
  443. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  444. package/src/client/public/cryptokoyn/assets/banner/koyn-social.png +0 -0
  445. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  446. package/src/client/public/cryptokoyn/assets/logo/cryptokoyn.png +0 -0
  447. package/src/client/public/cryptokoyn/assets/splash/android-chrome-144x144.png +0 -0
  448. package/src/client/public/cryptokoyn/assets/splash/android-chrome-192x192.png +0 -0
  449. package/src/client/public/cryptokoyn/assets/splash/android-chrome-256x256.png +0 -0
  450. package/src/client/public/cryptokoyn/assets/splash/android-chrome-36x36.png +0 -0
  451. package/src/client/public/cryptokoyn/assets/splash/android-chrome-48x48.png +0 -0
  452. package/src/client/public/cryptokoyn/assets/splash/android-chrome-72x72.png +0 -0
  453. package/src/client/public/cryptokoyn/assets/splash/android-chrome-96x96.png +0 -0
  454. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114-precomposed.png +0 -0
  455. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114.png +0 -0
  456. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120-precomposed.png +0 -0
  457. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120.png +0 -0
  458. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144-precomposed.png +0 -0
  459. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144.png +0 -0
  460. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152-precomposed.png +0 -0
  461. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152.png +0 -0
  462. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180-precomposed.png +0 -0
  463. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180.png +0 -0
  464. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57-precomposed.png +0 -0
  465. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57.png +0 -0
  466. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60-precomposed.png +0 -0
  467. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60.png +0 -0
  468. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72-precomposed.png +0 -0
  469. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72.png +0 -0
  470. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76-precomposed.png +0 -0
  471. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76.png +0 -0
  472. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-precomposed.png +0 -0
  473. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon.png +0 -0
  474. package/src/client/public/cryptokoyn/assets/splash/favicon-16x16.png +0 -0
  475. package/src/client/public/cryptokoyn/assets/splash/favicon-32x32.png +0 -0
  476. package/src/client/public/cryptokoyn/assets/splash/mstile-144x144.png +0 -0
  477. package/src/client/public/cryptokoyn/assets/splash/mstile-150x150.png +0 -0
  478. package/src/client/public/cryptokoyn/assets/splash/mstile-310x150.png +0 -0
  479. package/src/client/public/cryptokoyn/assets/splash/mstile-310x310.png +0 -0
  480. package/src/client/public/cryptokoyn/assets/splash/mstile-70x70.png +0 -0
  481. package/src/client/public/cryptokoyn/assets/splash/safari-pinned-tab.svg +42 -0
  482. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  483. package/src/client/public/cryptokoyn/favicon.ico +0 -0
  484. package/src/client/public/cryptokoyn/microdata.json +85 -0
  485. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  486. package/src/client/public/cryptokoyn/sitemap +148 -0
  487. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +307 -0
  488. package/src/client/public/cyberia-docs/ARCHITECTURE.md +309 -0
  489. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
  490. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +341 -0
  491. package/src/client/public/cyberia-docs/CYBERIA-LORE.md +84 -0
  492. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
  493. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +294 -0
  494. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  495. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +242 -0
  496. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  497. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +309 -0
  498. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +228 -0
  499. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  500. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  501. package/src/client/public/cyberia-docs/WHITE-PAPER.md +740 -0
  502. package/src/client/public/default/android-chrome-144x144.png +0 -0
  503. package/src/client/public/default/android-chrome-192x192.png +0 -0
  504. package/src/client/public/default/android-chrome-256x256.png +0 -0
  505. package/src/client/public/default/android-chrome-36x36.png +0 -0
  506. package/src/client/public/default/android-chrome-384x384.png +0 -0
  507. package/src/client/public/default/android-chrome-48x48.png +0 -0
  508. package/src/client/public/default/android-chrome-512x512.png +0 -0
  509. package/src/client/public/default/android-chrome-72x72.png +0 -0
  510. package/src/client/public/default/android-chrome-96x96.png +0 -0
  511. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  512. package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
  513. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  514. package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
  515. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  516. package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
  517. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  518. package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
  519. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  520. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  521. package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
  522. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  523. package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
  524. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  525. package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
  526. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  527. package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
  528. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  529. package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
  530. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  531. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  532. package/src/client/public/default/apple-touch-icon.png +0 -0
  533. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  534. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  535. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  536. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  537. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  538. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  539. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  540. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  541. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  542. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  543. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  544. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  545. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  546. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  547. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  548. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  549. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  550. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  551. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  552. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  553. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  554. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  555. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  556. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  557. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  558. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  559. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  560. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  561. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  562. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  563. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  564. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  565. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  566. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  567. package/src/client/public/default/assets/background/dark.jpg +0 -0
  568. package/src/client/public/default/assets/background/dark.svg +557 -0
  569. package/src/client/public/default/assets/background/white.jpg +0 -0
  570. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  571. package/src/client/public/default/assets/background/white0.jpg +0 -0
  572. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  573. package/src/client/public/default/assets/logo/underpost.gif +0 -0
  574. package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
  575. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  576. package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
  577. package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
  578. package/src/client/public/default/browserconfig.xml +12 -0
  579. package/src/client/public/default/favicon-16x16.png +0 -0
  580. package/src/client/public/default/favicon-32x32.png +0 -0
  581. package/src/client/public/default/favicon-48x48.png +0 -0
  582. package/src/client/public/default/favicon.ico +0 -0
  583. package/src/client/public/default/manifest.webmanifest +69 -0
  584. package/src/client/public/default/mstile-144x144.png +0 -0
  585. package/src/client/public/default/mstile-150x150.png +0 -0
  586. package/src/client/public/default/mstile-310x150.png +0 -0
  587. package/src/client/public/default/mstile-310x310.png +0 -0
  588. package/src/client/public/default/mstile-70x70.png +0 -0
  589. package/src/client/public/default/safari-pinned-tab.svg +24 -0
  590. package/src/client/public/default/site.webmanifest +69 -0
  591. package/src/client/public/default/sitemap +148 -0
  592. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  593. package/src/client/public/default/yandex-browser-manifest.json +9 -0
  594. package/src/client/public/doc/favicon.ico +0 -0
  595. package/src/client/public/doc/sitemap +148 -0
  596. package/src/client/public/itemledger/android-chrome-144x144.png +0 -0
  597. package/src/client/public/itemledger/android-chrome-192x192.png +0 -0
  598. package/src/client/public/itemledger/android-chrome-256x256.png +0 -0
  599. package/src/client/public/itemledger/android-chrome-36x36.png +0 -0
  600. package/src/client/public/itemledger/android-chrome-384x384.png +0 -0
  601. package/src/client/public/itemledger/android-chrome-48x48.png +0 -0
  602. package/src/client/public/itemledger/android-chrome-512x512.png +0 -0
  603. package/src/client/public/itemledger/android-chrome-72x72.png +0 -0
  604. package/src/client/public/itemledger/android-chrome-96x96.png +0 -0
  605. package/src/client/public/itemledger/apple-touch-icon-1024x1024.png +0 -0
  606. package/src/client/public/itemledger/apple-touch-icon-114x114.png +0 -0
  607. package/src/client/public/itemledger/apple-touch-icon-120x120.png +0 -0
  608. package/src/client/public/itemledger/apple-touch-icon-144x144.png +0 -0
  609. package/src/client/public/itemledger/apple-touch-icon-152x152.png +0 -0
  610. package/src/client/public/itemledger/apple-touch-icon-167x167.png +0 -0
  611. package/src/client/public/itemledger/apple-touch-icon-180x180.png +0 -0
  612. package/src/client/public/itemledger/apple-touch-icon-57x57.png +0 -0
  613. package/src/client/public/itemledger/apple-touch-icon-60x60.png +0 -0
  614. package/src/client/public/itemledger/apple-touch-icon-72x72.png +0 -0
  615. package/src/client/public/itemledger/apple-touch-icon-76x76.png +0 -0
  616. package/src/client/public/itemledger/apple-touch-icon-precomposed.png +0 -0
  617. package/src/client/public/itemledger/apple-touch-icon.png +0 -0
  618. package/src/client/public/itemledger/apple-touch-startup-image-1125x2436.png +0 -0
  619. package/src/client/public/itemledger/apple-touch-startup-image-1136x640.png +0 -0
  620. package/src/client/public/itemledger/apple-touch-startup-image-1170x2532.png +0 -0
  621. package/src/client/public/itemledger/apple-touch-startup-image-1179x2556.png +0 -0
  622. package/src/client/public/itemledger/apple-touch-startup-image-1242x2208.png +0 -0
  623. package/src/client/public/itemledger/apple-touch-startup-image-1242x2688.png +0 -0
  624. package/src/client/public/itemledger/apple-touch-startup-image-1284x2778.png +0 -0
  625. package/src/client/public/itemledger/apple-touch-startup-image-1290x2796.png +0 -0
  626. package/src/client/public/itemledger/apple-touch-startup-image-1334x750.png +0 -0
  627. package/src/client/public/itemledger/apple-touch-startup-image-1488x2266.png +0 -0
  628. package/src/client/public/itemledger/apple-touch-startup-image-1536x2048.png +0 -0
  629. package/src/client/public/itemledger/apple-touch-startup-image-1620x2160.png +0 -0
  630. package/src/client/public/itemledger/apple-touch-startup-image-1640x2160.png +0 -0
  631. package/src/client/public/itemledger/apple-touch-startup-image-1668x2224.png +0 -0
  632. package/src/client/public/itemledger/apple-touch-startup-image-1668x2388.png +0 -0
  633. package/src/client/public/itemledger/apple-touch-startup-image-1792x828.png +0 -0
  634. package/src/client/public/itemledger/apple-touch-startup-image-2048x1536.png +0 -0
  635. package/src/client/public/itemledger/apple-touch-startup-image-2048x2732.png +0 -0
  636. package/src/client/public/itemledger/apple-touch-startup-image-2160x1620.png +0 -0
  637. package/src/client/public/itemledger/apple-touch-startup-image-2160x1640.png +0 -0
  638. package/src/client/public/itemledger/apple-touch-startup-image-2208x1242.png +0 -0
  639. package/src/client/public/itemledger/apple-touch-startup-image-2224x1668.png +0 -0
  640. package/src/client/public/itemledger/apple-touch-startup-image-2266x1488.png +0 -0
  641. package/src/client/public/itemledger/apple-touch-startup-image-2388x1668.png +0 -0
  642. package/src/client/public/itemledger/apple-touch-startup-image-2436x1125.png +0 -0
  643. package/src/client/public/itemledger/apple-touch-startup-image-2532x1170.png +0 -0
  644. package/src/client/public/itemledger/apple-touch-startup-image-2556x1179.png +0 -0
  645. package/src/client/public/itemledger/apple-touch-startup-image-2688x1242.png +0 -0
  646. package/src/client/public/itemledger/apple-touch-startup-image-2732x2048.png +0 -0
  647. package/src/client/public/itemledger/apple-touch-startup-image-2778x1284.png +0 -0
  648. package/src/client/public/itemledger/apple-touch-startup-image-2796x1290.png +0 -0
  649. package/src/client/public/itemledger/apple-touch-startup-image-640x1136.png +0 -0
  650. package/src/client/public/itemledger/apple-touch-startup-image-750x1334.png +0 -0
  651. package/src/client/public/itemledger/apple-touch-startup-image-828x1792.png +0 -0
  652. package/src/client/public/itemledger/assets/logo/base-icon.png +0 -0
  653. package/src/client/public/itemledger/browserconfig.xml +12 -0
  654. package/src/client/public/itemledger/favicon-16x16.png +0 -0
  655. package/src/client/public/itemledger/favicon-32x32.png +0 -0
  656. package/src/client/public/itemledger/favicon-48x48.png +0 -0
  657. package/src/client/public/itemledger/favicon.ico +0 -0
  658. package/src/client/public/itemledger/manifest.webmanifest +69 -0
  659. package/src/client/public/itemledger/microdata.json +71 -0
  660. package/src/client/public/itemledger/mstile-144x144.png +0 -0
  661. package/src/client/public/itemledger/mstile-150x150.png +0 -0
  662. package/src/client/public/itemledger/mstile-310x150.png +0 -0
  663. package/src/client/public/itemledger/mstile-310x310.png +0 -0
  664. package/src/client/public/itemledger/mstile-70x70.png +0 -0
  665. package/src/client/public/itemledger/sitemap +148 -0
  666. package/src/client/public/itemledger/yandex-browser-50x50.png +0 -0
  667. package/src/client/public/itemledger/yandex-browser-manifest.json +9 -0
  668. package/src/client/public/test/favicon.ico +0 -0
  669. package/src/client/public/test/sitemap +148 -0
  670. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +137 -0
  671. package/src/client/services/core/core.service.js +309 -0
  672. package/src/client/services/crypto/crypto.service.js +68 -0
  673. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  674. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  675. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
  676. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  677. package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
  678. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
  679. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  680. package/src/client/services/cyberia-instance/cyberia-instance.service.js +137 -0
  681. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
  682. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  683. package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
  684. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  685. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  686. package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
  687. package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
  688. package/src/client/services/default/default.management.js +1015 -0
  689. package/src/client/services/default/default.service.js +99 -0
  690. package/src/client/services/document/document.service.js +134 -0
  691. package/src/client/services/file/file.service.js +94 -0
  692. package/src/client/services/instance/instance.management.js +78 -0
  693. package/src/client/services/instance/instance.service.js +107 -0
  694. package/src/client/services/ipfs/ipfs.service.js +118 -0
  695. package/src/client/services/object-layer/object-layer.management.js +414 -0
  696. package/src/client/services/object-layer/object-layer.service.js +208 -0
  697. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +99 -0
  698. package/src/client/services/test/test.service.js +68 -0
  699. package/src/client/services/user/guest.service.js +86 -0
  700. package/src/client/services/user/user.management.js +51 -0
  701. package/src/client/services/user/user.service.js +106 -0
  702. package/src/client/ssr/RootDocument.js +237 -0
  703. package/src/client/ssr/body/404.js +77 -0
  704. package/src/client/ssr/body/500.js +76 -0
  705. package/src/client/ssr/body/CacheControl.js +117 -0
  706. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +97 -0
  707. package/src/client/ssr/body/DefaultSplashScreen.js +97 -0
  708. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  709. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +90 -0
  710. package/src/client/ssr/head/CryptokoynScripts.js +4 -0
  711. package/src/client/ssr/head/Css.js +241 -0
  712. package/src/client/ssr/head/CyberiaPortalScripts.js +6 -0
  713. package/src/client/ssr/head/DefaultScripts.js +6 -0
  714. package/src/client/ssr/head/ItemledgerScripts.js +4 -0
  715. package/src/client/ssr/head/Microdata.js +11 -0
  716. package/src/client/ssr/head/Production.js +1 -0
  717. package/src/client/ssr/head/Pwa.js +146 -0
  718. package/src/client/ssr/head/PwaItemledger.js +197 -0
  719. package/src/client/ssr/head/Seo.js +15 -0
  720. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  721. package/src/client/ssr/mailer/DefaultRecoverEmail.js +20 -0
  722. package/src/client/ssr/mailer/DefaultVerifyEmail.js +16 -0
  723. package/src/client/ssr/views/Cyberia404.js +328 -0
  724. package/src/client/ssr/views/CyberiaServerMetrics.js +1070 -0
  725. package/src/client/ssr/views/Maintenance.js +64 -0
  726. package/src/client/ssr/views/NoNetworkConnection.js +68 -0
  727. package/src/client/ssr/views/Test.js +199 -0
  728. package/src/client/sw/core.sw.js +274 -0
  729. package/src/client-builder/client-build-docs.js +493 -0
  730. package/src/client-builder/client-build-live.js +100 -0
  731. package/src/client-builder/client-build.js +1092 -0
  732. package/src/client-builder/client-dev-server.js +88 -0
  733. package/src/client-builder/client-formatted.js +170 -0
  734. package/src/client-builder/client-icons.js +108 -0
  735. package/src/client-builder/ssr.js +124 -0
  736. package/src/client.build.js +17 -0
  737. package/src/client.dev.js +21 -0
  738. package/src/db/DataBaseProvider.js +213 -0
  739. package/src/db/mariadb/MariaDB.js +72 -0
  740. package/src/db/mongo/MongoBootstrap.js +657 -0
  741. package/src/db/mongo/MongooseDB.js +199 -0
  742. package/src/grpc/cyberia/grpc-server.js +162 -0
  743. package/src/index.js +357 -0
  744. package/src/mailer/EmailRender.js +116 -0
  745. package/src/mailer/MailerProvider.js +213 -0
  746. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +413 -0
  747. package/src/projects/cyberia/besu-genesis-generator.js +1630 -0
  748. package/src/projects/cyberia/catalog-cyberia.js +90 -0
  749. package/src/projects/cyberia/gemini-client.js +175 -0
  750. package/src/projects/cyberia/generate-saga.js +2137 -0
  751. package/src/projects/cyberia/hot-reload-trigger.js +163 -0
  752. package/src/projects/cyberia/instance-data.js +719 -0
  753. package/src/projects/cyberia/ipfs-client.js +599 -0
  754. package/src/projects/cyberia/map-preview-generator.js +304 -0
  755. package/src/projects/cyberia/object-layer.js +978 -0
  756. package/src/projects/cyberia/semantic-layer-generator-floor.js +319 -0
  757. package/src/projects/cyberia/semantic-layer-generator-resource.js +259 -0
  758. package/src/projects/cyberia/semantic-layer-generator-skin.js +1164 -0
  759. package/src/projects/cyberia/semantic-layer-generator.js +753 -0
  760. package/src/projects/cyberia/shape-generator.js +1060 -0
  761. package/src/projects/underpost/catalog-underpost.js +60 -0
  762. package/src/proxy.js +19 -0
  763. package/src/runtime/cyberia-client/Dockerfile +49 -0
  764. package/src/runtime/cyberia-client/Dockerfile.dev +75 -0
  765. package/src/runtime/cyberia-server/Dockerfile +43 -0
  766. package/src/runtime/cyberia-server/Dockerfile.dev +56 -0
  767. package/src/runtime/engine-cyberia/Dockerfile +161 -0
  768. package/src/runtime/engine-cyberia/Dockerfile.dev +161 -0
  769. package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
  770. package/src/runtime/engine-cyberia/compose.env +144 -0
  771. package/src/runtime/engine-cyberia/docker-compose.yml +434 -0
  772. package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
  773. package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
  774. package/src/runtime/engine-cyberia/nginx.conf +128 -0
  775. package/src/runtime/express/Dockerfile +45 -0
  776. package/src/runtime/express/Express.js +285 -0
  777. package/src/runtime/lampp/Dockerfile +62 -0
  778. package/src/runtime/lampp/Lampp.js +359 -0
  779. package/src/runtime/nginx/Nginx.js +250 -0
  780. package/src/runtime/wp/Dockerfile +62 -0
  781. package/src/runtime/wp/Wp.js +642 -0
  782. package/src/server/auth.js +713 -0
  783. package/src/server/backup.js +102 -0
  784. package/src/server/catalog.js +72 -0
  785. package/src/server/conf.js +2316 -0
  786. package/src/server/cron.js +476 -0
  787. package/src/server/crypto.js +210 -0
  788. package/src/server/data-query.js +461 -0
  789. package/src/server/dns.js +553 -0
  790. package/src/server/downloader.js +73 -0
  791. package/src/server/logger.js +229 -0
  792. package/src/server/middlewares.js +152 -0
  793. package/src/server/peer.js +75 -0
  794. package/src/server/process.js +299 -0
  795. package/src/server/proxy.js +139 -0
  796. package/src/server/runtime-status.js +252 -0
  797. package/src/server/runtime.js +183 -0
  798. package/src/server/start.js +272 -0
  799. package/src/server/tls.js +254 -0
  800. package/src/server/valkey.js +201 -0
  801. package/src/server.js +25 -0
  802. package/src/ws/IoInterface.js +129 -0
  803. package/src/ws/IoServer.js +68 -0
  804. package/src/ws/core/channels/core.ws.chat.js +68 -0
  805. package/src/ws/core/channels/core.ws.mailer.js +116 -0
  806. package/src/ws/core/channels/core.ws.stream.js +90 -0
  807. package/src/ws/core/core.ws.connection.js +41 -0
  808. package/src/ws/core/core.ws.emit.js +37 -0
  809. package/src/ws/core/core.ws.server.js +44 -0
  810. package/src/ws/default/channels/default.ws.main.js +57 -0
  811. package/src/ws/default/default.ws.connection.js +35 -0
  812. package/src/ws/default/default.ws.emit.js +14 -0
  813. package/src/ws/default/default.ws.server.js +39 -0
  814. package/test/api.test.js +53 -0
  815. package/test/crypto.test.js +117 -0
  816. package/test/cyberia-instance-conf-defaults.test.js +140 -0
  817. package/test/deploy-monitor.test.js +267 -0
  818. package/test/shape-generator.test.js +463 -0
  819. package/tsconfig.docs.json +15 -0
  820. package/typedoc.dd-cyberia.json +31 -0
  821. package/typedoc.json +31 -0
package/bin/deploy.js ADDED
@@ -0,0 +1,1547 @@
1
+ import fs from 'fs-extra';
2
+ import axios from 'axios';
3
+
4
+ import dotenv from 'dotenv';
5
+
6
+ import { pbcopy, shellExec } from '../src/server/process.js';
7
+ import { loggerFactory } from '../src/server/logger.js';
8
+ import {
9
+ addApiConf,
10
+ addClientConf,
11
+ buildApiSrc,
12
+ buildClientSrc,
13
+ cloneConf,
14
+ addWsConf,
15
+ buildWsSrc,
16
+ cloneSrcComponents,
17
+ writeEnv,
18
+ buildCliDoc,
19
+ loadConf,
20
+ } from '../src/server/conf.js';
21
+ import colors from 'colors';
22
+ import { program } from '../src/cli/index.js';
23
+ import { timer, getCapVariableName } from '../src/client/components/core/CommonJs.js';
24
+ import Underpost from '../src/index.js';
25
+
26
+ colors.enable();
27
+
28
+ const logger = loggerFactory(import.meta);
29
+
30
+ logger.info('argv', process.argv);
31
+
32
+ const [exe, dir, operator] = process.argv;
33
+
34
+ try {
35
+ switch (operator) {
36
+ case 'add-nodejs-app-client-conf':
37
+ {
38
+ const toOptions = {
39
+ deployId: process.argv[3],
40
+ clientId: process.argv[4],
41
+ host: process.argv[5],
42
+ path: process.argv[6],
43
+ };
44
+ const fromOptions = { deployId: process.argv[7], clientId: process.argv[8] };
45
+ addClientConf({ toOptions, fromOptions });
46
+ }
47
+ break;
48
+ case 'build-nodejs-conf-app':
49
+ {
50
+ const toOptions = { deployId: process.argv[3], clientId: process.argv[4] };
51
+ const fromOptions = { deployId: process.argv[5], clientId: process.argv[6] };
52
+ cloneConf({ toOptions, fromOptions });
53
+ }
54
+ break;
55
+ case 'clone-nodejs-src-client-components':
56
+ {
57
+ const fromOptions = { componentsFolder: process.argv[3] };
58
+ const toOptions = { componentsFolder: process.argv[4] };
59
+ cloneSrcComponents({ toOptions, fromOptions });
60
+ }
61
+ break;
62
+ case 'build-nodejs-src-app':
63
+ {
64
+ const toOptions = { deployId: process.argv[3], clientId: process.argv[4] };
65
+ const fromOptions = { deployId: process.argv[5], clientId: process.argv[6] };
66
+ buildClientSrc({ toOptions, fromOptions });
67
+ }
68
+ break;
69
+ case 'build-nodejs-conf-api':
70
+ {
71
+ const toOptions = { apiId: process.argv[3], deployId: process.argv[4], clientId: process.argv[5] };
72
+ const fromOptions = { apiId: process.argv[6], deployId: process.argv[7], clientId: process.argv[8] };
73
+ addApiConf({ toOptions, fromOptions });
74
+ }
75
+ break;
76
+ case 'build-nodejs-src-api':
77
+ {
78
+ const toOptions = { apiId: process.argv[3], deployId: process.argv[4], clientId: process.argv[5] };
79
+ const fromOptions = { apiId: process.argv[6], deployId: process.argv[7], clientId: process.argv[8] };
80
+ buildApiSrc({ toOptions, fromOptions });
81
+ }
82
+ break;
83
+ case 'build-nodejs-conf-ws':
84
+ {
85
+ const toOptions = {
86
+ wsId: process.argv[3],
87
+ deployId: process.argv[4],
88
+ host: process.argv[5],
89
+ paths: process.argv[6],
90
+ };
91
+ const fromOptions = {
92
+ wsId: process.argv[7],
93
+ deployId: process.argv[8],
94
+ host: process.argv[9],
95
+ paths: process.argv[10],
96
+ };
97
+ addWsConf({ toOptions, fromOptions });
98
+ }
99
+ break;
100
+ case 'build-nodejs-src-ws':
101
+ {
102
+ const toOptions = {
103
+ wsId: process.argv[3],
104
+ deployId: process.argv[4],
105
+ host: process.argv[5],
106
+ paths: process.argv[6],
107
+ };
108
+ const fromOptions = {
109
+ wsId: process.argv[7],
110
+ deployId: process.argv[8],
111
+ host: process.argv[9],
112
+ paths: process.argv[10],
113
+ };
114
+ buildWsSrc({ toOptions, fromOptions });
115
+ }
116
+ break;
117
+
118
+ case 'new-nodejs-app':
119
+ {
120
+ const deployId = process.argv[3];
121
+ const clientId = process.argv[4];
122
+
123
+ shellExec(`node bin/deploy build-nodejs-conf-app ${deployId} ${clientId}`);
124
+
125
+ shellExec(`node bin/deploy build-nodejs-src-app ${deployId} ${clientId}`);
126
+
127
+ await Underpost.repo.client(deployId);
128
+
129
+ shellExec(`npm run dev ${deployId}`);
130
+ }
131
+ break;
132
+ case 'test-new-api':
133
+ {
134
+ const port = process.argv[3];
135
+ const apiId = process.argv[4];
136
+ let url = `http://localhost:${port}/api/${apiId}`;
137
+ {
138
+ logger.info(`POST REQUEST`, url);
139
+ const result = await axios.post(url, {});
140
+ url += '/' + result.data.data._id;
141
+ logger.info(`POST RESULT ${url}`, result.data);
142
+ }
143
+ {
144
+ logger.info(`GET REQUEST`, url);
145
+ const result = await axios.get(url);
146
+ logger.info(`GET RESULT ${url}`, result.data);
147
+ }
148
+ {
149
+ logger.info(`DELETE REQUEST`, url);
150
+ const result = await axios.delete(url);
151
+ logger.info(`DELETE RESULT ${url}`, result.data);
152
+ }
153
+ }
154
+ break;
155
+ case 'new-nodejs-api':
156
+ {
157
+ const apiId = process.argv[3];
158
+ const deployId = process.argv[4];
159
+ const clientId = process.argv[5];
160
+
161
+ shellExec(`node bin/deploy build-nodejs-conf-api ${apiId} ${deployId} ${clientId}`);
162
+
163
+ shellExec(`node bin/deploy build-nodejs-src-api ${apiId} ${deployId} ${clientId}`);
164
+ }
165
+ break;
166
+ case 'new-nodejs-ws':
167
+ {
168
+ const wsId = process.argv[3];
169
+ const deployId = process.argv[4];
170
+ const host = process.argv[5];
171
+ const paths = process.argv[6];
172
+
173
+ shellExec(`node bin/deploy build-nodejs-conf-ws ${wsId} ${deployId} ${host} ${paths}`);
174
+
175
+ shellExec(`node bin/deploy build-nodejs-src-ws ${wsId} ${deployId} ${host} ${paths}`);
176
+
177
+ shellExec(`npm run dev ${deployId}`);
178
+ }
179
+ break;
180
+
181
+ case 'update-dependencies':
182
+ const files = await fs.readdir(`./engine-private/conf`, { recursive: true });
183
+ const originPackage = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
184
+ for (const relativePath of files) {
185
+ const filePah = `./engine-private/conf/${relativePath.replaceAll(`\\`, '/')}`;
186
+ if (filePah.split('/').pop() === 'package.json') {
187
+ const deployPackage = JSON.parse(fs.readFileSync(filePah, 'utf8'));
188
+ deployPackage.dependencies = originPackage.dependencies;
189
+ deployPackage.devDependencies = originPackage.devDependencies;
190
+ deployPackage.overrides = originPackage.overrides;
191
+ fs.writeFileSync(filePah, JSON.stringify(deployPackage, null, 4), 'utf8');
192
+ }
193
+ }
194
+ break;
195
+
196
+ case 'rename-package': {
197
+ const name = process.argv[3];
198
+ const originPackage = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
199
+ originPackage.name = name;
200
+ fs.writeFileSync(`./package.json`, JSON.stringify(originPackage, null, 4), 'utf8');
201
+
202
+ const originPackageLockJson = JSON.parse(fs.readFileSync(`./package-lock.json`, 'utf8'));
203
+ originPackageLockJson.name = name;
204
+ originPackageLockJson.packages[''].name = name;
205
+ fs.writeFileSync(`./package-lock.json`, JSON.stringify(originPackageLockJson, null, 4), 'utf8');
206
+
207
+ break;
208
+ }
209
+
210
+ case 'set-repo': {
211
+ const originPackage = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
212
+ originPackage.repository = {
213
+ type: 'git',
214
+ url: `git+https://github.com/${process.argv[3]}.git`,
215
+ };
216
+ fs.writeFileSync(`./package.json`, JSON.stringify(originPackage, null, 4), 'utf8');
217
+
218
+ break;
219
+ }
220
+
221
+ case 'build-default-confs': {
222
+ for (const deployId of fs
223
+ .readFileSync(`./engine-private/deploy/dd.router`, 'utf8')
224
+ .split(`,`)
225
+ .concat(['dd-cron'])) {
226
+ if (fs.existsSync(`./engine-private/conf/${deployId}/build/development/deployment.yaml`))
227
+ fs.copySync(
228
+ `./engine-private/conf/${deployId}/build/development/deployment.yaml`,
229
+ `./manifests/deployment/${deployId}-development/deployment.yaml`,
230
+ );
231
+ if (fs.existsSync(`./engine-private/conf/${deployId}/build/development/proxy.yaml`))
232
+ fs.copySync(
233
+ `./engine-private/conf/${deployId}/build/development/proxy.yaml`,
234
+ `./manifests/deployment/${deployId}-development/proxy.yaml`,
235
+ );
236
+ if (fs.existsSync(`./engine-private/conf/${deployId}/build/development/pv-pvc.yaml`))
237
+ fs.copySync(
238
+ `./engine-private/conf/${deployId}/build/development/pv-pvc.yaml`,
239
+ `./manifests/deployment/${deployId}-development/pv-pvc.yaml`,
240
+ );
241
+ shellExec(`node bin new --dev --default-conf --deploy-id ${deployId}`);
242
+ }
243
+ break;
244
+ }
245
+
246
+ case 'update-authors': {
247
+ // #### Ordered by first contribution.
248
+ fs.writeFileSync(
249
+ './AUTHORS.md',
250
+ `# Authors
251
+
252
+
253
+ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).join(`\n\n\n`)}
254
+
255
+ #### Generated by [underpost.net](https://underpost.net)`,
256
+ 'utf8',
257
+ );
258
+
259
+ break;
260
+ }
261
+
262
+ case 'maas-db': {
263
+ // DROP, ALTER, CREATE, WITH ENCRYPTED
264
+ // sudo -u <user> -h <host> psql <db-name>
265
+ shellExec(`DB_PG_MAAS_NAME=${process.env.DB_PG_MAAS_NAME}`);
266
+ shellExec(`DB_PG_MAAS_PASS=${process.env.DB_PG_MAAS_PASS}`);
267
+ shellExec(`DB_PG_MAAS_USER=${process.env.DB_PG_MAAS_USER}`);
268
+ shellExec(`DB_PG_MAAS_HOST=${process.env.DB_PG_MAAS_HOST}`);
269
+ shellExec(
270
+ `sudo -i -u postgres psql -c "CREATE USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
271
+ );
272
+ shellExec(
273
+ `sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
274
+ );
275
+ const actions = ['LOGIN', 'SUPERUSER', 'INHERIT', 'CREATEDB', 'CREATEROLE', 'REPLICATION'];
276
+ shellExec(`sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ${actions.join(' ')}"`);
277
+ shellExec(`sudo -i -u postgres psql -c "\\du"`);
278
+
279
+ shellExec(`sudo -i -u postgres createdb -O "$DB_PG_MAAS_USER" "$DB_PG_MAAS_NAME"`);
280
+
281
+ shellExec(`sudo -i -u postgres psql -c "\\l"`);
282
+ break;
283
+ }
284
+
285
+ case 'cli-docs': {
286
+ const version = Underpost.version;
287
+ const newVersion =
288
+ process.argv[4] && !process.argv[4].startsWith('v') ? `v${process.argv[4]}` : process.argv[4] || version;
289
+ buildCliDoc(program, process.argv[3] || version, newVersion);
290
+ break;
291
+ }
292
+
293
+ case 'postgresql-17': {
294
+ if (process.argv.includes('install')) {
295
+ shellExec(`sudo dnf module reset postgresql -y`);
296
+ shellExec(`sudo dnf -qy module disable postgresql`);
297
+ shellExec(
298
+ `sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm`,
299
+ );
300
+ shellExec(`sudo dnf -qy module disable postgresql`);
301
+ shellExec(`sudo dnf install -y postgresql17 postgresql17-server postgresql17-contrib`);
302
+
303
+ shellExec(`sudo /usr/pgsql-17/bin/postgresql-17-setup initdb`);
304
+ }
305
+ if (process.argv.includes('uninstall')) {
306
+ shellExec(`sudo systemctl stop postgresql-17`);
307
+ shellExec(`sudo systemctl disable postgresql-17`);
308
+
309
+ // Remove PostgreSQL 17 packages and repo
310
+ shellExec(`sudo dnf remove -y postgresql17 postgresql17-server postgresql17-contrib`);
311
+ shellExec(`sudo rpm -e pgdg-redhat-repo-$(rpm -q pgdg-redhat-repo --qf '%{VERSION}-%{RELEASE}')`);
312
+ shellExec(`sudo rm -f /etc/yum.repos.d/pgdg-redhat-*.repo`);
313
+
314
+ // Clean up data, logs, config, and the postgres user
315
+ shellExec(`sudo rm -rf /var/lib/pgsql/17 /var/log/pgsql`);
316
+ shellExec(`sudo rm -rf /etc/postgresql`);
317
+ } else {
318
+ shellExec(`sudo systemctl enable postgresql-17`);
319
+ shellExec(`sudo systemctl start postgresql-17`);
320
+ }
321
+ break;
322
+ }
323
+
324
+ case 'pg-list-db': {
325
+ shellExec(`sudo -i -u postgres psql -c "\\l"`);
326
+ break;
327
+ }
328
+
329
+ case 'pg-list-table': {
330
+ shellExec(`sudo -i -u postgres psql -c "\\dt *.*"`);
331
+ // schema_name.*
332
+ break;
333
+ }
334
+ case 'pg-drop-db': {
335
+ shellExec(`sudo -i -u postgres psql -c "DROP DATABASE ${process.argv[3]} WITH (FORCE)"`);
336
+ shellExec(`sudo -i -u postgres psql -c "DROP USER ${process.argv[4]}"`);
337
+ break;
338
+ }
339
+
340
+ case 'maas-stop': {
341
+ shellExec(`sudo snap stop maas`);
342
+ break;
343
+ }
344
+
345
+ case 'fastapi-models': {
346
+ shellExec(`chmod +x ../full-stack-fastapi-template/backend/initial_data.sh`);
347
+ shellExec(`../full-stack-fastapi-template/backend/initial_data.sh`);
348
+ shellExec(`../full-stack-fastapi-template/backend/initial_data.sh`);
349
+ break;
350
+ }
351
+
352
+ case 'fastapi': {
353
+ // node bin/deploy fastapi reset
354
+ // node bin/deploy fastapi reset build-back build-front secret run-back run-front
355
+ // https://github.com/NonsoEchendu/full-stack-fastapi-project
356
+ // https://github.com/fastapi/full-stack-fastapi-template
357
+ const path = `../full-stack-fastapi-template`;
358
+ const VITE_API_URL = `http://localhost:8000`;
359
+
360
+ if (process.argv.includes('reset')) shellExec(`sudo rm -rf ${path}`);
361
+
362
+ if (!fs.existsSync(path))
363
+ shellExec(`cd .. && git clone https://github.com/fastapi/full-stack-fastapi-template.git`);
364
+
365
+ shellExec(`cd ${path} && git checkout . && git clean -f -d`);
366
+ const password = fs.readFileSync(`/home/dd/engine/engine-private/postgresql-password`, 'utf8');
367
+
368
+ fs.writeFileSync(
369
+ `${path}/.env`,
370
+ fs
371
+ .readFileSync(`${path}/.env`, 'utf8')
372
+ .replace(
373
+ `FIRST_SUPERUSER=admin@example.com`,
374
+ `FIRST_SUPERUSER=${process.env.GITHUB_EMAIL || 'development@underpost.net'}`,
375
+ )
376
+ .replace(`FIRST_SUPERUSER_PASSWORD=changethis`, `FIRST_SUPERUSER_PASSWORD=${password}`)
377
+ .replace(`SECRET_KEY=changethis`, `SECRET_KEY=${password}`)
378
+ .replace(`POSTGRES_DB=app`, `POSTGRES_DB=postgresdb`)
379
+ .replace(`POSTGRES_USER=postgres`, `POSTGRES_USER=admin`)
380
+ .replace(`POSTGRES_PASSWORD=changethis`, `POSTGRES_PASSWORD=${password}`),
381
+ 'utf8',
382
+ );
383
+ fs.writeFileSync(
384
+ `${path}/backend/app/core/db.py`,
385
+ fs
386
+ .readFileSync(`${path}/backend/app/core/db.py`, 'utf8')
387
+ .replace(` # from sqlmodel import SQLModel`, ` from sqlmodel import SQLModel`)
388
+ .replace(` # SQLModel.metadata.create_all(engine)`, ` SQLModel.metadata.create_all(engine)`),
389
+
390
+ 'utf8',
391
+ );
392
+
393
+ fs.copySync(`./manifests/deployment/fastapi/initial_data.sh`, `${path}/backend/initial_data.sh`);
394
+
395
+ fs.writeFileSync(
396
+ `${path}/frontend/Dockerfile`,
397
+ fs
398
+ .readFileSync(`${path}/frontend/Dockerfile`, 'utf8')
399
+ .replace('ARG VITE_API_URL=${VITE_API_URL}', `ARG VITE_API_URL='${VITE_API_URL}'`),
400
+ 'utf8',
401
+ );
402
+
403
+ fs.writeFileSync(
404
+ `${path}/frontend/.env`,
405
+ fs
406
+ .readFileSync(`${path}/frontend/.env`, 'utf8')
407
+ .replace(`VITE_API_URL=http://localhost:8000`, `VITE_API_URL=${VITE_API_URL}`)
408
+ .replace(`MAILCATCHER_HOST=http://localhost:1080`, `MAILCATCHER_HOST=http://localhost:1081`),
409
+
410
+ 'utf8',
411
+ );
412
+
413
+ if (process.argv.includes('models')) {
414
+ shellExec(`node bin/deploy fastapi-models`);
415
+ break;
416
+ }
417
+
418
+ if (process.argv.includes('build-back')) {
419
+ const imageName = `fastapi-backend:latest`;
420
+ shellExec(`sudo podman pull docker.io/library/python:3.10`);
421
+ shellExec(`sudo podman pull ghcr.io/astral-sh/uv:0.5.11`);
422
+ shellExec(`sudo rm -rf ${path}/${imageName.replace(':', '_')}.tar`);
423
+ const args = [
424
+ `node bin image --build --path ${path}/backend/`,
425
+ `--image-name=${imageName} --image-out-path=${path}`,
426
+ `--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'} --reset`,
427
+ ];
428
+ shellExec(args.join(' '));
429
+ }
430
+ if (process.argv.includes('build-front')) {
431
+ const imageName = `fastapi-frontend:latest`;
432
+ shellExec(`sudo podman pull docker.io/library/node:20`);
433
+ shellExec(`sudo podman pull docker.io/library/nginx:1`);
434
+ shellExec(`sudo rm -rf ${path}/${imageName.replace(':', '_')}.tar`);
435
+ const args = [
436
+ `node bin image --build --path ${path}/frontend/`,
437
+ `--image-name=${imageName} --image-out-path=${path}`,
438
+ `--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'} --reset`,
439
+ ];
440
+ shellExec(args.join(' '));
441
+ }
442
+ if (process.argv.includes('secret')) {
443
+ const namespace = process.argv.find((arg) => arg.startsWith('--namespace='))?.split('=')[1] || 'default';
444
+ {
445
+ const secretSelector = `fastapi-postgres-credentials`;
446
+ shellExec(`sudo kubectl delete secret ${secretSelector} -n ${namespace} --ignore-not-found`);
447
+ shellExec(
448
+ `sudo kubectl create secret generic ${secretSelector}` +
449
+ ` --from-literal=POSTGRES_DB=postgresdb` +
450
+ ` --from-literal=POSTGRES_USER=admin` +
451
+ ` --from-file=POSTGRES_PASSWORD=/home/dd/engine/engine-private/postgresql-password` +
452
+ ` --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
453
+ );
454
+ }
455
+ {
456
+ const secretSelector = `fastapi-backend-config-secret`;
457
+ shellExec(`sudo kubectl delete secret ${secretSelector} -n ${namespace} --ignore-not-found`);
458
+ shellExec(
459
+ `sudo kubectl create secret generic ${secretSelector}` +
460
+ ` --from-file=SECRET_KEY=/home/dd/engine/engine-private/postgresql-password` +
461
+ ` --from-literal=FIRST_SUPERUSER=${process.env.GITHUB_EMAIL || 'development@underpost.net'}` +
462
+ ` --from-file=FIRST_SUPERUSER_PASSWORD=/home/dd/engine/engine-private/postgresql-password` +
463
+ ` --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
464
+ );
465
+ }
466
+ }
467
+ if (process.argv.includes('run-back')) {
468
+ const namespace = process.argv.find((arg) => arg.startsWith('--namespace='))?.split('=')[1] || 'default';
469
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/fastapi/backend-deployment.yml -n ${namespace}`);
470
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/fastapi/backend-service.yml -n ${namespace}`);
471
+ }
472
+ if (process.argv.includes('run-front')) {
473
+ const namespace = process.argv.find((arg) => arg.startsWith('--namespace='))?.split('=')[1] || 'default';
474
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/fastapi/frontend-deployment.yml -n ${namespace}`);
475
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/fastapi/frontend-service.yml -n ${namespace}`);
476
+ }
477
+ break;
478
+ }
479
+
480
+ case 'conda': {
481
+ // set -e
482
+ // ENV_NAME="${1:-cuda_env}"
483
+ // eval "$(conda shell.bash hook)"
484
+ // conda activate "${ENV_NAME}"
485
+ shellExec(
486
+ `export PATH="/root/miniconda3/bin:$PATH" && conda init && conda config --set auto_activate_base false`,
487
+ );
488
+ shellExec(`conda env list`);
489
+ break;
490
+ }
491
+
492
+ case 'kafka': {
493
+ // https://medium.com/@martin.hodges/deploying-kafka-on-a-kind-kubernetes-cluster-for-development-and-testing-purposes-ed7adefe03cb
494
+ const namespace = process.argv.find((arg) => arg.startsWith('--namespace='))?.split('=')[1] || 'kafka';
495
+ const imageName = `doughgle/kafka-kraft`;
496
+ shellExec(`docker pull ${imageName}`);
497
+ if (!process.argv.includes('kubeadm'))
498
+ shellExec(
499
+ `${process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`} ${imageName}`,
500
+ );
501
+ shellExec(`kubectl create namespace ${namespace} --dry-run=client -o yaml | kubectl apply -f -`);
502
+ shellExec(`kubectl apply -f ./manifests/deployment/kafka/deployment.yaml -n ${namespace}`);
503
+ // kubectl logs kafka-0 -n kafka | grep STARTED
504
+ // kubectl logs kafka-1 -n kafka | grep STARTED
505
+ // kubectl logs kafka-2 -n kafka | grep STARTED
506
+
507
+ // kafka-topics.sh --create --topic my-topic --bootstrap-server kafka-svc:9092
508
+ // kafka-topics.sh --list --topic my-topic --bootstrap-server kafka-svc:9092
509
+ // kafka-topics.sh --delete --topic my-topic --bootstrap-server kafka-svc:9092
510
+
511
+ // kafka-console-producer.sh --bootstrap-server kafka-svc:9092 --topic my-topic
512
+ // kafka-console-consumer.sh --bootstrap-server kafka-svc:9092 --topic my-topic
513
+ break;
514
+ }
515
+
516
+ case 'nvidia-gpu-operator': {
517
+ // https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
518
+ shellExec(`curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
519
+ sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo`);
520
+
521
+ const NVIDIA_CONTAINER_TOOLKIT_VERSION = '1.17.8-1';
522
+
523
+ shellExec(`sudo dnf install -y \
524
+ nvidia-container-toolkit-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
525
+ nvidia-container-toolkit-base-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
526
+ libnvidia-container-tools-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
527
+ libnvidia-container1-${NVIDIA_CONTAINER_TOOLKIT_VERSION}`);
528
+
529
+ // https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html
530
+ const namespace = 'gpu-operator';
531
+ shellExec(`kubectl create ns ${namespace} --dry-run=client -o yaml | kubectl apply -f -`);
532
+ shellExec(`kubectl label --overwrite ns ${namespace} pod-security.kubernetes.io/enforce=privileged`);
533
+
534
+ shellExec(`helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
535
+ && helm repo update`);
536
+
537
+ // shellExec(`helm install --wait --generate-name \
538
+ // -n gpu-operator --create-namespace \
539
+ // nvidia/gpu-operator \
540
+ // --version=v25.3.1 \
541
+ // --set toolkit.version=v1.16.1-ubi8`);
542
+
543
+ shellExec(`helm install --wait --generate-name \
544
+ -n gpu-operator --create-namespace \
545
+ nvidia/gpu-operator \
546
+ --version=v25.3.1 \
547
+ --set driver.enabled=false \
548
+ --set driver.repository=nvcr.io/nvidia \
549
+ --set cdi.enabled=true \
550
+ --set cdi.default=true \
551
+ --set toolkit.env[0].name=CONTAINERD_CONFIG \
552
+ --set toolkit.env[0].value=/etc/containerd/config.toml \
553
+ --set toolkit.env[1].name=CONTAINERD_SOCKET \
554
+ --set toolkit.env[1].value=/run/containerd/containerd.sock \
555
+ --set toolkit.env[2].name=CONTAINERD_RUNTIME_CLASS \
556
+ --set toolkit.env[2].value=nvidia \
557
+ --set-string toolkit.env[3].name=CONTAINERD_SET_AS_DEFAULT \
558
+ --set-string toolkit.env[3].value=true`);
559
+
560
+ // Check gpu drivers
561
+ shellExec(
562
+ `break;kubectl get nodes -o json | jq '.items[].metadata.labels | keys | any(startswith("feature.node.kubernetes.io"))'`,
563
+ );
564
+ break;
565
+ }
566
+
567
+ case 'kubeflow-spark-operator': {
568
+ // Use case:
569
+ // Data Processing Pipelines: Used for ETL tasks where Spark can handle large data volumes efficiently.
570
+ // Real-Time Analytics: Processing data from streaming sources (e.g., Kafka) for real-time analytics.
571
+ // Machine Learning and Data Science: Training and deploying machine learning models at scale using Spark MLlib.
572
+
573
+ shellExec(`helm repo add spark-operator https://kubeflow.github.io/spark-operator`);
574
+ shellExec(`helm install spark-operator spark-operator/spark-operator \
575
+ --namespace spark-operator \
576
+ --create-namespace \
577
+ --wait`);
578
+
579
+ const image = `spark:3.5.5`;
580
+ shellExec(`sudo docker pull ${image}`);
581
+ if (!process.argv.includes('kubeadm'))
582
+ shellExec(
583
+ `sudo ${
584
+ process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`
585
+ } ${image}`,
586
+ );
587
+ const namespace = process.argv.find((arg) => arg.startsWith('--namespace='))?.split('=')[1] || 'default';
588
+ shellExec(`kubectl apply -f ./manifests/deployment/spark/spark-pi-py.yaml -n ${namespace}`);
589
+
590
+ // Check the status of the Spark job:
591
+ // kubectl get sparkapplications.sparkoperator.k8s.io -n default
592
+ // kubectl get sparkapplication
593
+
594
+ // Check case log:
595
+ // kubectl logs -f spark-pi-python-driver
596
+ // kubectl logs -f spark-pi-python-driver | grep Pi
597
+ // kubectl describe sparkapplication spark-gpu-test
598
+
599
+ // Uninstall:
600
+ // kubectl delete sparkapplications.sparkoperator.k8s.io spark-pi-python -n default
601
+ // helm delete spark-operator -n spark-operator
602
+
603
+ // Gpu plugins:
604
+ // https://github.com/NVIDIA/spark-rapids
605
+ // RAPIDS Accelerator
606
+ break;
607
+ }
608
+
609
+ case 'tls': {
610
+ fs.mkdirSync(`./engine-private/ssl/localhost`, { recursive: true });
611
+ const targetDir = `./engine-private/ssl/${process.argv[3] ? process.argv[3] : 'localhost'}`;
612
+ const domains = ['localhost', '127.0.0.1', '::1'].concat(process.argv[3] ? process.argv[3] : []);
613
+ shellExec(`chmod +x ./scripts/ssl.sh`);
614
+ shellExec(`./scripts/ssl.sh ${targetDir} "${domains.join(' ')}"`);
615
+ break;
616
+ }
617
+
618
+ case 'build-envs': {
619
+ const buildEnv = (privateEnvPath, originEnv, env) => {
620
+ const privateEnv = dotenv.parse(fs.readFileSync(privateEnvPath, 'utf8'));
621
+ for (const key of Object.keys(privateEnv)) {
622
+ if (key in env) {
623
+ console.warn(`Key ${key} already exists in origin env`);
624
+ continue;
625
+ }
626
+ if (key in originEnv) {
627
+ console.warn(`Key ${key} already exists in origin env`);
628
+ env[key] = originEnv[key];
629
+ continue;
630
+ }
631
+ env[key] =
632
+ `${key}`.toUpperCase().match('API') ||
633
+ `${key}`.toUpperCase().match('KEY') ||
634
+ `${key}`.toUpperCase().match('SECRET') ||
635
+ `${key}`.toUpperCase().match('TOKEN') ||
636
+ `${key}`.toUpperCase().match('PASSWORD') ||
637
+ `${key}`.toUpperCase().match('MAC')
638
+ ? 'changethis'
639
+ : isNaN(parseFloat(privateEnv[key]))
640
+ ? `${privateEnv[key]}`.match(`@`)
641
+ ? 'admin@default.net'
642
+ : 'changethis'
643
+ : privateEnv[key];
644
+ }
645
+ return env;
646
+ };
647
+ for (let envPath of ['.env.development', '.env.production', '.env.test']) {
648
+ const originEnv = dotenv.parse(fs.readFileSync(`./${envPath}`, 'utf8'));
649
+
650
+ let env = {};
651
+ env = buildEnv(`./engine-private/conf/dd-cron/${envPath}`, originEnv, env);
652
+ env = buildEnv(`./engine-private/conf/dd-core/${envPath}`, originEnv, env);
653
+ writeEnv(envPath, env);
654
+ }
655
+ break;
656
+ }
657
+
658
+ case 'sync-start': {
659
+ const targetDeployId = process.argv[3] || 'dd';
660
+ const deployIds =
661
+ targetDeployId === 'dd'
662
+ ? fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',')
663
+ : [targetDeployId];
664
+ const originPackageJson = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
665
+ for (const deployId of deployIds) {
666
+ const packageJsonPath = `./engine-private/conf/${deployId}/package.json`;
667
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
668
+ packageJson.scripts = { start: `${originPackageJson.scripts.start} ${deployId}` };
669
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4), 'utf8');
670
+ logger.info(`sync-start`, { deployId, start: packageJson.scripts.start });
671
+ }
672
+ break;
673
+ }
674
+
675
+ case 'sync-envs': {
676
+ for (const deployId of ['dd-cron'].concat(
677
+ fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(','),
678
+ )) {
679
+ for (const env of ['production', 'development', 'test']) {
680
+ const _envObj = dotenv.parse(fs.readFileSync(`./engine-private/conf/${deployId}/.env.${env}`, 'utf8'));
681
+ for (const env of []) {
682
+ delete _envObj[env];
683
+ }
684
+ writeEnv(`./engine-private/conf/${deployId}/.env.${env}`, _envObj);
685
+ }
686
+ }
687
+ break;
688
+ }
689
+
690
+ case 'sync-conf': {
691
+ const originPackageJson = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
692
+ for (const deployId of ['dd-cron'].concat(
693
+ fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(','),
694
+ )) {
695
+ for (const file of fs.readdirSync(`./engine-private/conf/${deployId}/`)) {
696
+ const deployPackage = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/package.json`, 'utf8'));
697
+ deployPackage.overrides = originPackageJson.overrides;
698
+ deployPackage.dependencies = originPackageJson.dependencies;
699
+ fs.writeFileSync(
700
+ `./engine-private/conf/${deployId}/package.json`,
701
+ JSON.stringify(deployPackage, null, 4),
702
+ 'utf8',
703
+ );
704
+ if (file.startsWith('conf.server') && file.endsWith('.json')) {
705
+ const filePath = `./engine-private/conf/${deployId}/${file}`;
706
+ const confObj = JSON.parse(fs.readFileSync(filePath, 'utf8'));
707
+ for (const host of Object.keys(confObj)) {
708
+ for (const path of Object.keys(confObj[host])) {
709
+ }
710
+ }
711
+ // fs.writeFileSync(filePath, JSON.stringify(confObj, null, 4), 'utf8');
712
+ logger.info(`sync-conf`, { deployId, file });
713
+ }
714
+ }
715
+ }
716
+ break;
717
+ }
718
+
719
+ case 'cyberia': {
720
+ const { CyberiaDependencies } = await import(`../src/api/cyberia-server-defaults/cyberia-server-defaults.js`);
721
+ for (const dep of Object.keys(CyberiaDependencies)) {
722
+ const ver = CyberiaDependencies[dep];
723
+ shellExec(`npm install ${dep}@${ver}`);
724
+ }
725
+ break;
726
+ }
727
+
728
+ case 'pw': {
729
+ const help = `node bin/deploy pw <script-path> <from-path-in-pod> [to-path-on-local]`;
730
+ const scriptPath = process.argv[3];
731
+ const fromPath = process.argv[4];
732
+ const toPath = process.argv[5] ? process.argv[5] : fromPath ? `/tmp/${fromPath.split('/').pop()}` : '';
733
+ if (scriptPath === 'help') {
734
+ logger.info(help);
735
+ break;
736
+ }
737
+ if (fs.existsSync(toPath)) fs.removeSync(toPath);
738
+ shellExec(`node bin/deploy pw-conf ${scriptPath}`);
739
+ shellExec(`kubectl delete deployment playwright-server --ignore-not-found`);
740
+ while (Underpost.kubectl.get('playwright-server').length > 0) {
741
+ logger.info(`Waiting for playwright-server deployment to be deleted...`);
742
+ await timer(1000);
743
+ }
744
+ shellExec(`kubectl apply -f manifests/deployment/playwright/deployment.yaml`);
745
+ const id = 'playwright-server';
746
+ await Underpost.test.statusMonitor(id);
747
+ const nameSpace = 'default';
748
+ const [pod] = Underpost.kubectl.get(id);
749
+ const podName = pod.NAME;
750
+ shellExec(`kubectl logs -f ${podName} -n ${nameSpace}`, {
751
+ async: true,
752
+ });
753
+ (async () => {
754
+ while (!Underpost.kubectl.existsFile({ podName, path: fromPath })) {
755
+ await timer(1000);
756
+ logger.info(`Waiting for file ${fromPath} in pod ${podName}...`);
757
+ }
758
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${fromPath} ${toPath}`);
759
+ if (toPath.match('.png') && fs.existsSync(toPath)) shellExec(`firefox ${toPath}`);
760
+ })();
761
+ break;
762
+ }
763
+
764
+ case 'pw-conf': {
765
+ const scriptPath = process.argv[3];
766
+ shellExec(`kubectl delete configmap playwright-script`);
767
+ shellExec(`kubectl create configmap playwright-script \
768
+ --from-file=script.js=${scriptPath} \
769
+ --dry-run=client -o yaml | kubectl apply -f -
770
+ `);
771
+ break;
772
+ }
773
+
774
+ case 'dependabot': {
775
+ dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
776
+ shellExec(`git fetch origin --prune`);
777
+
778
+ const { stdout: branchOutput } = shellExec(`git branch -r`, { silent: true });
779
+ const dependabotBranches = branchOutput
780
+ .split('\n')
781
+ .map((b) => b.trim())
782
+ .filter((b) => b.startsWith('remotes/origin/dependabot/') || b.startsWith('origin/dependabot/'))
783
+ .map((b) => b.replace(/^remotes\//, '').replace(/^origin\//, ''));
784
+
785
+ if (dependabotBranches.length === 0) {
786
+ logger.info('No remote dependabot branches found');
787
+ break;
788
+ }
789
+
790
+ logger.info('Found dependabot branches:', dependabotBranches);
791
+
792
+ // Stash local changes to prevent checkout/merge conflicts
793
+ const stashResult = shellExec(`git stash --include-untracked`, { silent: true });
794
+ const hasStash = !stashResult.stdout.includes('No local changes to save');
795
+
796
+ // Checkout master
797
+ const checkoutResult = shellExec(`git checkout master`);
798
+ if (checkoutResult.code !== 0) {
799
+ logger.error('Failed to checkout master');
800
+ if (hasStash) shellExec(`git stash pop`);
801
+ break;
802
+ }
803
+
804
+ // Pull latest master
805
+ shellExec(`git pull origin master`);
806
+
807
+ // Get repo URI from remote
808
+ const remoteUrl = shellExec(`git config --get remote.origin.url`, { stdout: true, silent: true }).trim();
809
+ const gitUri = remoteUrl.replace(/.*github\.com[:/]/, '').replace(/\.git$/, '');
810
+
811
+ const mergedBranches = [];
812
+ const failedBranches = [];
813
+
814
+ for (const branch of dependabotBranches) {
815
+ logger.info(`Merging branch: ${branch}`);
816
+ const mergeResult = shellExec(`git merge origin/${branch}`);
817
+ if (mergeResult.code === 0) {
818
+ const isAlreadyMerged = mergeResult.stdout && mergeResult.stdout.includes('Already up to date');
819
+ mergedBranches.push({ branch, isAlreadyMerged });
820
+ } else {
821
+ logger.error(`Failed to merge branch: ${branch}`);
822
+ shellExec(`git merge --abort`, { silent: true });
823
+ failedBranches.push(branch);
824
+ }
825
+ }
826
+
827
+ // Delete merged local and remote branches
828
+ for (const { branch, isAlreadyMerged } of mergedBranches) {
829
+ shellExec(`git branch -D ${branch}`, { silent: true, silentOnError: true });
830
+ // logger.info(`Deleting remote branch: ${branch}${isAlreadyMerged ? ' (already merged)' : ''}`);
831
+ // shellExec(`git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}.git --delete ${branch}`, {
832
+ // disableLog: true,
833
+ // });
834
+ }
835
+
836
+ // Restore stashed changes
837
+ if (hasStash) shellExec(`git stash pop`);
838
+
839
+ logger.info(
840
+ 'Merged branches:',
841
+ mergedBranches.map((m) => m.branch),
842
+ );
843
+ if (failedBranches.length > 0) logger.warn('Failed branches:', failedBranches);
844
+ logger.info('Dependabot merge completed');
845
+ break;
846
+ }
847
+
848
+ case 'add-server-client': {
849
+ // node bin/deploy add-server-client <clientId> <deployId> <host> <path>
850
+ // Example: node bin/deploy add-server-client cecinasmarcelina dd-core cecinasmarcelina.com /
851
+ // Example: node bin/deploy add-server-client cecinasmarcelina dd-core www.cecinasmarcelina.com /
852
+ const clientId = process.argv[3];
853
+ const deployId = process.argv[4];
854
+ const rawHost = process.argv[5];
855
+ const path = process.argv[6];
856
+
857
+ // Normalize: strip www. prefix to get the base host
858
+ const baseHost = rawHost.startsWith('www.') ? rawHost.slice(4) : rawHost;
859
+ const mainHost = `www.${baseHost}`;
860
+ const redirectHost = baseHost;
861
+
862
+ loadConf('clean');
863
+ loadConf();
864
+ shellExec(`node bin/deploy clone-client default ${clientId} dd-default ${deployId}`);
865
+ // default.net has the main client entry → maps to www.<host> (main)
866
+ shellExec(`node bin/deploy clone-server default.net / ${mainHost} ${path} dd-default ${deployId} ${clientId}`);
867
+ // www.default.net has the redirect/empty entry → maps to <host> (redirect)
868
+ shellExec(`node bin/deploy clone-server www.default.net / ${redirectHost} ${path} dd-default ${deployId}`);
869
+ fs.removeSync(`./engine-private/conf/dd-default`);
870
+ break;
871
+ }
872
+
873
+ case 'clone-client': {
874
+ // node bin/deploy clone-client <fromClientId> <toClientId> <fromDeployId> [toDeployId]
875
+ // Example: node bin/deploy clone-client dogmadual mynewclient dd-core
876
+ // Example: node bin/deploy clone-client dogmadual mynewclient dd-core dd-other
877
+ //
878
+ // Clones a client configuration and its src/ files with a new name.
879
+ // If toDeployId is omitted, it defaults to fromDeployId (same deploy).
880
+ // Steps:
881
+ // - conf.client.json: clones the fromClientId entry as toClientId (renames identifiers)
882
+ // - conf.ssr.json: clones the SSR entry under the new PascalCase name
883
+ // - conf.server.json + dev variants: duplicates paths referencing fromClientId for toClientId
884
+ // - src/client/components/<fromClientId>/ → src/client/components/<toClientId>/ (renames identifiers)
885
+ // - src/client/services/<fromClientId>/ → src/client/services/<toClientId>/ (renames identifiers)
886
+ // - src/client/ssr/head/<From>Scripts.js → <To>Scripts.js
887
+ // - src/client/ssr/body/<From>*.js → <To>*.js (SplashScreen, etc.)
888
+ // - src/client/ssr/mailer/<From>*.js → <To>*.js (VerifyEmail, RecoverEmail, etc.)
889
+ // - src/client/<From>.index.js → <To>.index.js
890
+ // - src/client/public/<fromClientId>/ → src/client/public/<toClientId>/
891
+
892
+ const fromClientId = process.argv[3];
893
+ const toClientId = process.argv[4];
894
+ const fromDeployId = process.argv[5];
895
+ const toDeployId = process.argv[6] || fromDeployId;
896
+
897
+ if (!fromClientId || !toClientId || !fromDeployId) {
898
+ logger.error('Usage: node bin/deploy clone-client <fromClientId> <toClientId> <fromDeployId> [toDeployId]');
899
+ logger.error('Example: node bin/deploy clone-client dogmadual mynewclient dd-core');
900
+ process.exit(1);
901
+ }
902
+
903
+ const fromCapName = getCapVariableName(fromClientId);
904
+ const toCapName = getCapVariableName(toClientId);
905
+
906
+ const confFromFolder = `./engine-private/conf/${fromDeployId}`;
907
+ const confToFolder = `./engine-private/conf/${toDeployId}`;
908
+
909
+ if (!fs.existsSync(confFromFolder)) {
910
+ logger.error(`Source config folder not found: ${confFromFolder}`);
911
+ process.exit(1);
912
+ }
913
+ if (!fs.existsSync(confToFolder)) {
914
+ logger.error(`Target config folder not found: ${confToFolder}`);
915
+ process.exit(1);
916
+ }
917
+
918
+ const formattedSrc = (src) => src.replaceAll(fromCapName, toCapName).replaceAll(fromClientId, toClientId);
919
+
920
+ // 1. Clone conf.client.json entry
921
+ {
922
+ const clientConf = JSON.parse(fs.readFileSync(`${confToFolder}/conf.client.json`, 'utf8'));
923
+ if (clientConf[toClientId]) {
924
+ logger.warn(`conf.client.json: "${toClientId}" already exists, skipping`);
925
+ } else {
926
+ const fromClientConf = JSON.parse(fs.readFileSync(`${confFromFolder}/conf.client.json`, 'utf8'));
927
+ if (!fromClientConf[fromClientId]) {
928
+ logger.error(`conf.client.json: "${fromClientId}" not found in ${confFromFolder}`);
929
+ process.exit(1);
930
+ }
931
+ clientConf[toClientId] = JSON.parse(formattedSrc(JSON.stringify(fromClientConf[fromClientId])));
932
+ fs.writeFileSync(`${confToFolder}/conf.client.json`, JSON.stringify(clientConf, null, 4), 'utf8');
933
+ logger.info(`conf.client.json: cloned "${fromClientId}" → "${toClientId}"`);
934
+ }
935
+ }
936
+
937
+ // 2. Clone conf.ssr.json entry
938
+ {
939
+ const ssrConf = JSON.parse(fs.readFileSync(`${confToFolder}/conf.ssr.json`, 'utf8'));
940
+ if (ssrConf[toCapName]) {
941
+ logger.warn(`conf.ssr.json: "${toCapName}" already exists, skipping`);
942
+ } else {
943
+ const fromSsrConf = JSON.parse(fs.readFileSync(`${confFromFolder}/conf.ssr.json`, 'utf8'));
944
+ if (fromSsrConf[fromCapName]) {
945
+ ssrConf[toCapName] = JSON.parse(formattedSrc(JSON.stringify(fromSsrConf[fromCapName])));
946
+ fs.writeFileSync(`${confToFolder}/conf.ssr.json`, JSON.stringify(ssrConf, null, 4), 'utf8');
947
+ logger.info(`conf.ssr.json: cloned "${fromCapName}" → "${toCapName}"`);
948
+ } else {
949
+ logger.warn(`conf.ssr.json: "${fromCapName}" not found in ${confFromFolder}, skipping`);
950
+ }
951
+ }
952
+ }
953
+
954
+ // 3. Clone server conf entries (conf.server.json + dev variants)
955
+ const cloneServerConfEntries = (filePath, label) => {
956
+ if (!fs.existsSync(filePath)) return;
957
+ const serverConf = JSON.parse(fs.readFileSync(filePath, 'utf8'));
958
+ let count = 0;
959
+ for (const host of Object.keys(serverConf)) {
960
+ for (const path of Object.keys(serverConf[host])) {
961
+ const entry = serverConf[host][path];
962
+ if (entry.client === fromClientId) {
963
+ const newPath = path === '/' ? `/${toClientId}` : path.replace(fromClientId, toClientId);
964
+ if (!serverConf[host][newPath]) {
965
+ serverConf[host][newPath] = JSON.parse(formattedSrc(JSON.stringify(entry)));
966
+ count++;
967
+ }
968
+ }
969
+ }
970
+ }
971
+ if (count > 0) {
972
+ fs.writeFileSync(filePath, JSON.stringify(serverConf, null, 4), 'utf8');
973
+ }
974
+ logger.info(`${label}: cloned ${count} server path(s) for "${toClientId}"`);
975
+ };
976
+
977
+ cloneServerConfEntries(`${confToFolder}/conf.server.json`, 'conf.server.json');
978
+ const devFiles = fs
979
+ .readdirSync(confToFolder)
980
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
981
+ for (const devFile of devFiles) {
982
+ cloneServerConfEntries(`${confToFolder}/${devFile}`, devFile);
983
+ }
984
+
985
+ // 4. Clone src/client/components/<fromClientId>/ → <toClientId>/
986
+ const srcFromFolder = `./src/client/components/${fromClientId}`;
987
+ const srcToFolder = `./src/client/components/${toClientId}`;
988
+
989
+ if (!fs.existsSync(srcFromFolder)) {
990
+ logger.warn(`Source component folder not found: ${srcFromFolder}, skipping src clone`);
991
+ } else if (fs.existsSync(srcToFolder)) {
992
+ logger.warn(`Target component folder already exists: ${srcToFolder}, skipping src clone`);
993
+ } else {
994
+ fs.mkdirSync(srcToFolder, { recursive: true });
995
+ const files = fs.readdirSync(srcFromFolder, { recursive: true });
996
+ for (const relativePath of files) {
997
+ const fromFilePath = `${srcFromFolder}/${relativePath}`;
998
+ if (fs.statSync(fromFilePath).isDirectory()) {
999
+ fs.mkdirSync(`${srcToFolder}/${formattedSrc(relativePath)}`, { recursive: true });
1000
+ continue;
1001
+ }
1002
+ const toFileName = formattedSrc(relativePath);
1003
+ fs.writeFileSync(`${srcToFolder}/${toFileName}`, formattedSrc(fs.readFileSync(fromFilePath, 'utf8')), 'utf8');
1004
+ }
1005
+ logger.info(`src/client/components: cloned ${srcFromFolder} → ${srcToFolder} (${files.length} files)`);
1006
+ }
1007
+
1008
+ // 5. Clone src/client/services/<fromClientId>/ → <toClientId>/
1009
+ {
1010
+ const svcFromFolder = `./src/client/services/${fromClientId}`;
1011
+ const svcToFolder = `./src/client/services/${toClientId}`;
1012
+ if (!fs.existsSync(svcFromFolder)) {
1013
+ logger.warn(`Source services folder not found: ${svcFromFolder}, skipping`);
1014
+ } else if (fs.existsSync(svcToFolder)) {
1015
+ logger.warn(`Target services folder already exists: ${svcToFolder}, skipping`);
1016
+ } else {
1017
+ fs.mkdirSync(svcToFolder, { recursive: true });
1018
+ const svcFiles = fs.readdirSync(svcFromFolder, { recursive: true });
1019
+ for (const relativePath of svcFiles) {
1020
+ const fromFilePath = `${svcFromFolder}/${relativePath}`;
1021
+ if (fs.statSync(fromFilePath).isDirectory()) {
1022
+ fs.mkdirSync(`${svcToFolder}/${formattedSrc(relativePath)}`, { recursive: true });
1023
+ continue;
1024
+ }
1025
+ const toFileName = formattedSrc(relativePath);
1026
+ fs.writeFileSync(
1027
+ `${svcToFolder}/${toFileName}`,
1028
+ formattedSrc(fs.readFileSync(fromFilePath, 'utf8')),
1029
+ 'utf8',
1030
+ );
1031
+ }
1032
+ logger.info(`src/client/services: cloned ${svcFromFolder} → ${svcToFolder} (${svcFiles.length} files)`);
1033
+ }
1034
+ }
1035
+
1036
+ // 6. Clone SSR head scripts
1037
+ const fromScriptsPath = `./src/client/ssr/head/${fromCapName}Scripts.js`;
1038
+ const toScriptsPath = `./src/client/ssr/head/${toCapName}Scripts.js`;
1039
+ if (fs.existsSync(fromScriptsPath) && !fs.existsSync(toScriptsPath)) {
1040
+ fs.writeFileSync(toScriptsPath, formattedSrc(fs.readFileSync(fromScriptsPath, 'utf8')), 'utf8');
1041
+ logger.info(`ssr/head: cloned ${fromCapName}Scripts.js → ${toCapName}Scripts.js`);
1042
+ } else if (fs.existsSync(toScriptsPath)) {
1043
+ logger.warn(`ssr/head: ${toCapName}Scripts.js already exists, skipping`);
1044
+ }
1045
+
1046
+ // 7. Clone SSR body files
1047
+ {
1048
+ const ssrConf = JSON.parse(fs.readFileSync(`${confToFolder}/conf.ssr.json`, 'utf8'));
1049
+ const toSsr = ssrConf[toCapName];
1050
+ if (toSsr && Array.isArray(toSsr.body)) {
1051
+ for (const bodyName of toSsr.body) {
1052
+ if (!bodyName.startsWith(toCapName)) continue;
1053
+ const fromBodyName = bodyName.replace(toCapName, fromCapName);
1054
+ const fromBodyPath = `./src/client/ssr/body/${fromBodyName}.js`;
1055
+ const toBodyPath = `./src/client/ssr/body/${bodyName}.js`;
1056
+ if (fs.existsSync(fromBodyPath) && !fs.existsSync(toBodyPath)) {
1057
+ fs.writeFileSync(toBodyPath, formattedSrc(fs.readFileSync(fromBodyPath, 'utf8')), 'utf8');
1058
+ logger.info(`ssr/body: cloned ${fromBodyName}.js → ${bodyName}.js`);
1059
+ } else if (fs.existsSync(toBodyPath)) {
1060
+ logger.warn(`ssr/body: ${bodyName}.js already exists, skipping`);
1061
+ }
1062
+ }
1063
+ }
1064
+ }
1065
+
1066
+ // 8. Clone SSR mailer files
1067
+ {
1068
+ const ssrConf = JSON.parse(fs.readFileSync(`${confToFolder}/conf.ssr.json`, 'utf8'));
1069
+ const toSsr = ssrConf[toCapName];
1070
+ if (toSsr && toSsr.mailer && typeof toSsr.mailer === 'object') {
1071
+ for (const mailerName of Object.values(toSsr.mailer)) {
1072
+ if (!mailerName.startsWith(toCapName)) continue;
1073
+ const fromMailerName = mailerName.replace(toCapName, fromCapName);
1074
+ const fromMailerPath = `./src/client/ssr/mailer/${fromMailerName}.js`;
1075
+ const toMailerPath = `./src/client/ssr/mailer/${mailerName}.js`;
1076
+ if (fs.existsSync(fromMailerPath) && !fs.existsSync(toMailerPath)) {
1077
+ fs.writeFileSync(toMailerPath, formattedSrc(fs.readFileSync(fromMailerPath, 'utf8')), 'utf8');
1078
+ logger.info(`ssr/mailer: cloned ${fromMailerName}.js → ${mailerName}.js`);
1079
+ } else if (fs.existsSync(toMailerPath)) {
1080
+ logger.warn(`ssr/mailer: ${mailerName}.js already exists, skipping`);
1081
+ }
1082
+ }
1083
+ }
1084
+ }
1085
+
1086
+ // 9. Clone client index
1087
+ const fromIndexPath = `./src/client/${fromCapName}.index.js`;
1088
+ const toIndexPath = `./src/client/${toCapName}.index.js`;
1089
+ if (fs.existsSync(fromIndexPath) && !fs.existsSync(toIndexPath)) {
1090
+ fs.writeFileSync(toIndexPath, formattedSrc(fs.readFileSync(fromIndexPath, 'utf8')), 'utf8');
1091
+ logger.info(`client: cloned ${fromCapName}.index.js → ${toCapName}.index.js`);
1092
+ } else if (fs.existsSync(toIndexPath)) {
1093
+ logger.warn(`client: ${toCapName}.index.js already exists, skipping`);
1094
+ }
1095
+
1096
+ // 10. Clone public assets
1097
+ const fromPublicPath = `./src/client/public/${fromClientId}`;
1098
+ const toPublicPath = `./src/client/public/${toClientId}`;
1099
+ if (fs.existsSync(fromPublicPath) && !fs.existsSync(toPublicPath)) {
1100
+ fs.copySync(fromPublicPath, toPublicPath);
1101
+ logger.info(`public: cloned ${fromPublicPath} → ${toPublicPath}`);
1102
+ } else if (fs.existsSync(toPublicPath)) {
1103
+ logger.warn(`public: ${toPublicPath} already exists, skipping`);
1104
+ }
1105
+
1106
+ // 11. Rebuild default conf
1107
+ shellExec(`node bin new --default-conf --deploy-id ${toDeployId}`);
1108
+ logger.info(`Rebuilt default conf for ${toDeployId}`);
1109
+
1110
+ break;
1111
+ }
1112
+
1113
+ case 'clone-server': {
1114
+ // node bin/deploy clone-server <fromHost> <fromPath> <toHost> <toPath> <fromDeployId> <toDeployId>
1115
+ // Example: node bin/deploy clone-server www.dogmadual.com / www.newsite.com / dd-core dd-other
1116
+ // Example: node bin/deploy clone-server www.nexodev.org / www.newdomain.org /app dd-core dd-core
1117
+ //
1118
+ // Clones a specific server host/path entry from one deploy's conf to another,
1119
+ // optionally renaming the host and path in the target.
1120
+ // - conf.server.json: copies the fromHost/fromPath entry to toHost/toPath
1121
+ // - conf.server.dev.*.json: same treatment for all dev variants
1122
+
1123
+ const fromHost = process.argv[3];
1124
+ const fromPath = process.argv[4];
1125
+ const toHost = process.argv[5];
1126
+ const toPath = process.argv[6];
1127
+ const fromDeployId = process.argv[7];
1128
+ const toDeployId = process.argv[8];
1129
+ const overrideClientId = process.argv[9];
1130
+
1131
+ if (!fromHost || !fromPath || !toHost || !toPath || !fromDeployId || !toDeployId) {
1132
+ logger.error(
1133
+ 'Usage: node bin/deploy clone-server <fromHost> <fromPath> <toHost> <toPath> <fromDeployId> <toDeployId> [clientId]',
1134
+ );
1135
+ logger.error(
1136
+ 'Example: node bin/deploy clone-server www.dogmadual.com / www.newsite.com / dd-core dd-other newsite',
1137
+ );
1138
+ process.exit(1);
1139
+ }
1140
+
1141
+ const confFromFolder = `./engine-private/conf/${fromDeployId}`;
1142
+ const confToFolder = `./engine-private/conf/${toDeployId}`;
1143
+
1144
+ if (!fs.existsSync(confFromFolder)) {
1145
+ logger.error(`Source config folder not found: ${confFromFolder}`);
1146
+ process.exit(1);
1147
+ }
1148
+ if (!fs.existsSync(confToFolder)) {
1149
+ logger.error(`Target config folder not found: ${confToFolder}`);
1150
+ process.exit(1);
1151
+ }
1152
+
1153
+ const cloneServerEntry = (fromFilePath, toFilePath, label) => {
1154
+ if (!fs.existsSync(fromFilePath)) {
1155
+ logger.warn(`${label}: source file not found, skipping`);
1156
+ return;
1157
+ }
1158
+ const fromServerConf = JSON.parse(fs.readFileSync(fromFilePath, 'utf8'));
1159
+ if (!fromServerConf[fromHost] || !fromServerConf[fromHost][fromPath]) {
1160
+ logger.warn(`${label}: "${fromHost}" "${fromPath}" not found in source, skipping`);
1161
+ return;
1162
+ }
1163
+
1164
+ const toServerConf = fs.existsSync(toFilePath) ? JSON.parse(fs.readFileSync(toFilePath, 'utf8')) : {};
1165
+
1166
+ if (!toServerConf[toHost]) toServerConf[toHost] = {};
1167
+
1168
+ if (toServerConf[toHost][toPath]) {
1169
+ logger.warn(`${label}: "${toHost}" "${toPath}" already exists in target, skipping`);
1170
+ return;
1171
+ }
1172
+
1173
+ toServerConf[toHost][toPath] = JSON.parse(JSON.stringify(fromServerConf[fromHost][fromPath]));
1174
+ // Override client field if --client= is provided
1175
+ const entry = toServerConf[toHost][toPath];
1176
+ if (overrideClientId && entry.client) {
1177
+ entry.client = overrideClientId;
1178
+ }
1179
+ // Update db.name to use the client-specific env variable
1180
+ if (entry.client && entry.db && entry.db.name) {
1181
+ const upperClientId = entry.client.replaceAll('-', '_').toUpperCase();
1182
+ entry.db.name = `env:DB_NAME_${upperClientId}`;
1183
+ }
1184
+ fs.writeFileSync(toFilePath, JSON.stringify(toServerConf, null, 4), 'utf8');
1185
+ logger.info(
1186
+ `${label}: cloned "${fromHost}" "${fromPath}" → "${toHost}" "${toPath}" (${fromDeployId} → ${toDeployId})`,
1187
+ );
1188
+ };
1189
+
1190
+ // 1. Main conf.server.json
1191
+ cloneServerEntry(`${confFromFolder}/conf.server.json`, `${confToFolder}/conf.server.json`, 'conf.server.json');
1192
+
1193
+ // 2. Dev variants (clone from source dev files)
1194
+ const devFiles = fs
1195
+ .readdirSync(confFromFolder)
1196
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
1197
+ for (const devFile of devFiles) {
1198
+ cloneServerEntry(`${confFromFolder}/${devFile}`, `${confToFolder}/${devFile}`, devFile);
1199
+ }
1200
+
1201
+ // 3. Create individual dev file for the new entry (conf.server.dev.<clientId>.json)
1202
+ {
1203
+ const mainToPath = `${confToFolder}/conf.server.json`;
1204
+ if (fs.existsSync(mainToPath)) {
1205
+ const toServerConf = JSON.parse(fs.readFileSync(mainToPath, 'utf8'));
1206
+ const entry = toServerConf[toHost] && toServerConf[toHost][toPath];
1207
+ if (entry && entry.client) {
1208
+ const devFileName = `conf.server.dev.${entry.client}.json`;
1209
+ const devFilePath = `${confToFolder}/${devFileName}`;
1210
+ if (!fs.existsSync(devFilePath)) {
1211
+ const devConf = { [toHost]: { [toPath]: entry } };
1212
+ fs.writeFileSync(devFilePath, JSON.stringify(devConf, null, 4), 'utf8');
1213
+ logger.info(`${devFileName}: created dev file for "${toHost}" "${toPath}"`);
1214
+ } else {
1215
+ logger.info(`${devFileName}: already exists, skipping creation`);
1216
+ }
1217
+ }
1218
+ }
1219
+ }
1220
+
1221
+ // 4. Add DB_NAME_<UPPER> env variable to target deploy .env.* files
1222
+ {
1223
+ const mainFromPath = `${confFromFolder}/conf.server.json`;
1224
+ if (fs.existsSync(mainFromPath)) {
1225
+ const fromServerConf = JSON.parse(fs.readFileSync(mainFromPath, 'utf8'));
1226
+ const sourceEntry = fromServerConf[fromHost] && fromServerConf[fromHost][fromPath];
1227
+ if (sourceEntry && sourceEntry.client) {
1228
+ const clientId = overrideClientId || sourceEntry.client;
1229
+ const upperClientId = clientId.replaceAll('-', '_').toUpperCase();
1230
+ const envKey = `DB_NAME_${upperClientId}`;
1231
+ const envValue = `${envKey}=${clientId}`;
1232
+ for (const envFile of ['.env.production', '.env.development', '.env.test']) {
1233
+ const envPath = `${confToFolder}/${envFile}`;
1234
+ if (fs.existsSync(envPath)) {
1235
+ const envContent = fs.readFileSync(envPath, 'utf8');
1236
+ if (!envContent.includes(envKey)) {
1237
+ fs.writeFileSync(envPath, envContent.trimEnd() + '\n' + envValue + '\n', 'utf8');
1238
+ logger.info(`${envFile}: added ${envValue}`);
1239
+ } else {
1240
+ logger.info(`${envFile}: ${envKey} already exists, skipping`);
1241
+ }
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ }
1247
+
1248
+ // 5. Rebuild default conf
1249
+ shellExec(`node bin new --default-conf --deploy-id ${toDeployId}`);
1250
+ logger.info(`Rebuilt default conf for ${toDeployId}`);
1251
+
1252
+ break;
1253
+ }
1254
+
1255
+ case 'add-api': {
1256
+ // node bin/deploy add-api <apiId> <deployId> [clientId] [host]
1257
+ // Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal
1258
+ // Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal underpost.net
1259
+ //
1260
+ // Adds an API to server conf files (main + dev variants) and client conf.
1261
+ // - conf.server.json: adds apiId to every host/path that has an `apis` array
1262
+ // (or only to the specified host if [host] is provided)
1263
+ // - conf.server.dev.*.json: same treatment for all dev variants
1264
+ // - conf.client.json: adds apiId to the specified clientId's `services` array
1265
+ // Idempotent: skips if the API is already present.
1266
+
1267
+ const apiId = process.argv[3];
1268
+ const deployId = process.argv[4];
1269
+ const clientId = process.argv[5];
1270
+ const targetHost = process.argv[6];
1271
+
1272
+ if (!apiId || !deployId) {
1273
+ logger.error('Usage: node bin/deploy add-api <apiId> <deployId> [clientId] [host]');
1274
+ logger.error('Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal');
1275
+ logger.error('Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal underpost.net');
1276
+ process.exit(1);
1277
+ }
1278
+
1279
+ const confFolder = `./engine-private/conf/${deployId}`;
1280
+ if (!fs.existsSync(confFolder)) {
1281
+ logger.error(`Config folder not found: ${confFolder}`);
1282
+ process.exit(1);
1283
+ }
1284
+
1285
+ // Helper: add apiId to apis[] arrays in a server conf file (idempotent)
1286
+ // When targetHost is set, only entries under that host are modified.
1287
+ const addApiToServerConf = (filePath) => {
1288
+ if (!fs.existsSync(filePath)) return 0;
1289
+ const conf = JSON.parse(fs.readFileSync(filePath, 'utf8'));
1290
+ let count = 0;
1291
+ const hosts = targetHost ? (conf[targetHost] ? [targetHost] : []) : Object.keys(conf);
1292
+ for (const host of hosts) {
1293
+ for (const path of Object.keys(conf[host])) {
1294
+ const entry = conf[host][path];
1295
+ if (Array.isArray(entry.apis) && entry.apis.length > 0 && !entry.apis.includes(apiId)) {
1296
+ entry.apis.push(apiId);
1297
+ count++;
1298
+ }
1299
+ }
1300
+ }
1301
+ if (count > 0) {
1302
+ fs.writeFileSync(filePath, JSON.stringify(conf, null, 4), 'utf8');
1303
+ }
1304
+ return count;
1305
+ };
1306
+
1307
+ // 1. Main conf.server.json
1308
+ const mainPath = `${confFolder}/conf.server.json`;
1309
+ const mainCount = addApiToServerConf(mainPath);
1310
+ logger.info(`conf.server.json: added "${apiId}" to ${mainCount} path(s)`);
1311
+
1312
+ // 2. All dev variants: conf.server.dev.*.json
1313
+ const devFiles = fs
1314
+ .readdirSync(confFolder)
1315
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
1316
+ for (const devFile of devFiles) {
1317
+ const devPath = `${confFolder}/${devFile}`;
1318
+ const devCount = addApiToServerConf(devPath);
1319
+ logger.info(`${devFile}: added "${apiId}" to ${devCount} path(s)`);
1320
+ }
1321
+
1322
+ // Helper: add apiId to a client conf file's clientId services (idempotent)
1323
+ const addApiToClientConf = (filePath, label) => {
1324
+ if (!clientId || !fs.existsSync(filePath)) return;
1325
+ const confClient = JSON.parse(fs.readFileSync(filePath, 'utf8'));
1326
+ if (confClient[clientId] && Array.isArray(confClient[clientId].services)) {
1327
+ if (!confClient[clientId].services.includes(apiId)) {
1328
+ confClient[clientId].services.push(apiId);
1329
+ fs.writeFileSync(filePath, JSON.stringify(confClient, null, 4), 'utf8');
1330
+ logger.info(`${label}: added "${apiId}" to "${clientId}" services`);
1331
+ } else {
1332
+ logger.info(`${label}: "${apiId}" already in "${clientId}" services`);
1333
+ }
1334
+ } else {
1335
+ logger.warn(`${label}: clientId "${clientId}" not found or has no services array`);
1336
+ }
1337
+ };
1338
+
1339
+ // 3. Client conf.client.json
1340
+ addApiToClientConf(`${confFolder}/conf.client.json`, 'conf.client.json');
1341
+
1342
+ // 4. Replicas: engine-private/replica/<deployId>-*
1343
+ const replicaBase = './engine-private/replica';
1344
+ if (fs.existsSync(replicaBase)) {
1345
+ const replicaDirs = fs
1346
+ .readdirSync(replicaBase)
1347
+ .filter((d) => d.startsWith(`${deployId}-`) && fs.statSync(`${replicaBase}/${d}`).isDirectory());
1348
+ for (const replicaDir of replicaDirs) {
1349
+ const replicaFolder = `${replicaBase}/${replicaDir}`;
1350
+ // Server conf
1351
+ const rMainCount = addApiToServerConf(`${replicaFolder}/conf.server.json`);
1352
+ logger.info(`replica/${replicaDir}/conf.server.json: added "${apiId}" to ${rMainCount} path(s)`);
1353
+ // Dev variants
1354
+ const rDevFiles = fs
1355
+ .readdirSync(replicaFolder)
1356
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
1357
+ for (const rDevFile of rDevFiles) {
1358
+ const rDevCount = addApiToServerConf(`${replicaFolder}/${rDevFile}`);
1359
+ logger.info(`replica/${replicaDir}/${rDevFile}: added "${apiId}" to ${rDevCount} path(s)`);
1360
+ }
1361
+ // Client conf
1362
+ addApiToClientConf(`${replicaFolder}/conf.client.json`, `replica/${replicaDir}/conf.client.json`);
1363
+ }
1364
+ }
1365
+
1366
+ // 5. Rebuild default conf
1367
+ shellExec(`node bin new --default-conf --deploy-id ${deployId}`);
1368
+ logger.info(`Rebuilt default conf for ${deployId}`);
1369
+
1370
+ break;
1371
+ }
1372
+
1373
+ case 'add-component': {
1374
+ // node bin/deploy add-component <componentId> [deployId] [clientId] [submoduleId]
1375
+ // Example: node bin/deploy add-component ColorPaletteElement dd-cyberia cyberia-portal core
1376
+ // Example: node bin/deploy add-component ColorPaletteElement dd-cyberia
1377
+ // Example: node bin/deploy add-component ColorPaletteElement
1378
+ // Adds a component to client conf.main and related replicas.
1379
+ // - if deployId is omitted: iterates deploys in engine-private/deploy/dd.router
1380
+ // - if clientId is omitted: iterates all clients in each conf.client.json
1381
+ // - if submoduleId is omitted: iterates all available components.<submoduleId> arrays per client
1382
+ // - validates src/client/components/<submoduleId>/<componentId>.js exists before adding
1383
+ // Idempotent: skips if the component is already present.
1384
+
1385
+ const componentId = process.argv[3];
1386
+ const deployIdArg = process.argv[4];
1387
+ const clientIdArg = process.argv[5];
1388
+ const submoduleIdArg = process.argv[6];
1389
+
1390
+ if (!componentId) {
1391
+ logger.error('Usage: node bin/deploy add-component <componentId> [deployId] [clientId] [submoduleId]');
1392
+ logger.error('Example: node bin/deploy add-component ColorPaletteElement dd-cyberia cyberia-portal core');
1393
+ logger.error('Example: node bin/deploy add-component ColorPaletteElement');
1394
+ process.exit(1);
1395
+ }
1396
+
1397
+ const deployIds = deployIdArg
1398
+ ? [deployIdArg]
1399
+ : fs
1400
+ .readFileSync(`./engine-private/deploy/dd.router`, 'utf8')
1401
+ .split(',')
1402
+ .map((d) => d.trim())
1403
+ .filter(Boolean);
1404
+
1405
+ const addComponentToClientConf = ({ filePath, label, targetClientId, targetSubmoduleId }) => {
1406
+ if (!fs.existsSync(filePath)) return { added: 0, checked: 0, hasComponentFile: false };
1407
+
1408
+ const confClient = JSON.parse(fs.readFileSync(filePath, 'utf8'));
1409
+ const clientIds = targetClientId ? [targetClientId] : Object.keys(confClient);
1410
+ let added = 0;
1411
+ let checked = 0;
1412
+ let hasComponentFile = false;
1413
+ let changed = false;
1414
+
1415
+ for (const currentClientId of clientIds) {
1416
+ const clientConf = confClient[currentClientId];
1417
+ if (!clientConf) {
1418
+ logger.warn(`${label}: clientId "${currentClientId}" not found`);
1419
+ continue;
1420
+ }
1421
+
1422
+ const components = clientConf.components || {};
1423
+ const submoduleIds = targetSubmoduleId
1424
+ ? [targetSubmoduleId]
1425
+ : Object.keys(components).filter((key) => Array.isArray(components[key]));
1426
+
1427
+ for (const currentSubmoduleId of submoduleIds) {
1428
+ checked++;
1429
+
1430
+ if (!Array.isArray(components[currentSubmoduleId])) {
1431
+ logger.warn(`${label}: clientId "${currentClientId}" has no components.${currentSubmoduleId} array`);
1432
+ continue;
1433
+ }
1434
+
1435
+ const componentPath = `./src/client/components/${currentSubmoduleId}/${componentId}.js`;
1436
+ if (!fs.existsSync(componentPath)) {
1437
+ continue;
1438
+ }
1439
+ hasComponentFile = true;
1440
+
1441
+ if (components[currentSubmoduleId].includes(componentId)) {
1442
+ logger.info(
1443
+ `${label}: "${componentId}" already in "${currentClientId}" components.${currentSubmoduleId}`,
1444
+ );
1445
+ continue;
1446
+ }
1447
+
1448
+ components[currentSubmoduleId].push(componentId);
1449
+ changed = true;
1450
+ added++;
1451
+ logger.info(`${label}: added "${componentId}" to "${currentClientId}" components.${currentSubmoduleId}`);
1452
+ }
1453
+ }
1454
+
1455
+ if (changed) {
1456
+ fs.writeFileSync(filePath, JSON.stringify(confClient, null, 4), 'utf8');
1457
+ }
1458
+
1459
+ return { added, checked, hasComponentFile };
1460
+ };
1461
+
1462
+ let totalAdded = 0;
1463
+ let totalChecked = 0;
1464
+ let hasAnyComponentFile = false;
1465
+ const processedDeployIds = [];
1466
+
1467
+ for (const deployId of deployIds) {
1468
+ const confFolder = `./engine-private/conf/${deployId}`;
1469
+ if (!fs.existsSync(confFolder)) {
1470
+ logger.warn(`Config folder not found: ${confFolder}`);
1471
+ continue;
1472
+ }
1473
+
1474
+ processedDeployIds.push(deployId);
1475
+
1476
+ const mainResult = addComponentToClientConf({
1477
+ filePath: `${confFolder}/conf.client.json`,
1478
+ label: `conf/${deployId}/conf.client.json`,
1479
+ targetClientId: clientIdArg,
1480
+ targetSubmoduleId: submoduleIdArg,
1481
+ });
1482
+ totalAdded += mainResult.added;
1483
+ totalChecked += mainResult.checked;
1484
+ hasAnyComponentFile = hasAnyComponentFile || mainResult.hasComponentFile;
1485
+
1486
+ const replicaBase = './engine-private/replica';
1487
+ if (fs.existsSync(replicaBase)) {
1488
+ const replicaDirs = fs
1489
+ .readdirSync(replicaBase)
1490
+ .filter((d) => d.startsWith(`${deployId}-`) && fs.statSync(`${replicaBase}/${d}`).isDirectory());
1491
+
1492
+ for (const replicaDir of replicaDirs) {
1493
+ const replicaResult = addComponentToClientConf({
1494
+ filePath: `${replicaBase}/${replicaDir}/conf.client.json`,
1495
+ label: `replica/${replicaDir}/conf.client.json`,
1496
+ targetClientId: clientIdArg,
1497
+ targetSubmoduleId: submoduleIdArg,
1498
+ });
1499
+ totalAdded += replicaResult.added;
1500
+ totalChecked += replicaResult.checked;
1501
+ hasAnyComponentFile = hasAnyComponentFile || replicaResult.hasComponentFile;
1502
+ }
1503
+ }
1504
+ }
1505
+
1506
+ if (totalChecked === 0) {
1507
+ logger.error('No eligible target entries found to add the component');
1508
+ process.exit(1);
1509
+ }
1510
+
1511
+ if (!hasAnyComponentFile) {
1512
+ if (submoduleIdArg) {
1513
+ logger.error(`Component file not found: ./src/client/components/${submoduleIdArg}/${componentId}.js`);
1514
+ } else {
1515
+ logger.error(`Component file not found in available submodules for "${componentId}"`);
1516
+ }
1517
+ process.exit(1);
1518
+ }
1519
+
1520
+ for (const deployId of processedDeployIds) {
1521
+ shellExec(`node bin new --default-conf --deploy-id ${deployId}`);
1522
+ logger.info(`Rebuilt default conf for ${deployId}`);
1523
+ }
1524
+
1525
+ logger.info(`add-component summary`, {
1526
+ componentId,
1527
+ deployIds: processedDeployIds,
1528
+ added: totalAdded,
1529
+ checked: totalChecked,
1530
+ });
1531
+
1532
+ break;
1533
+ }
1534
+
1535
+ case 'k3s-template-env': {
1536
+ if (fs.existsSync('./engine-private/conf/dd-default')) {
1537
+ console.log('Cleaning up existing dd-default config for VM template environment setup');
1538
+ fs.removeSync('./engine-private/conf/dd-default');
1539
+ }
1540
+ shellExec(`node bin env clean`);
1541
+ shellExec(`sed -i "s/127.0.0.1/$(underpost ip --dhcp)/g" .env.example`);
1542
+ break;
1543
+ }
1544
+ }
1545
+ } catch (error) {
1546
+ logger.error(error, error.stack);
1547
+ }