@underpostnet/cyberia 3.2.90 → 3.3.73

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 (490) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +16 -0
  3. package/.github/workflows/coverall.cyberia.ci.yml +107 -0
  4. package/.github/workflows/cyberia-client.cd.yml +6 -18
  5. package/.github/workflows/cyberia-server.cd.yml +6 -18
  6. package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
  7. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
  8. package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
  9. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
  10. package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
  11. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
  12. package/.github/workflows/engine-cyberia.cd.yml +6 -78
  13. package/.github/workflows/engine-cyberia.ci.yml +4 -5
  14. package/.github/workflows/ghpkg.ci.yml +42 -21
  15. package/.github/workflows/hardhat.ci.yml +12 -11
  16. package/.github/workflows/npmpkg.ci.yml +17 -15
  17. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
  18. package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
  19. package/.github/workflows/release.cd.yml +2 -9
  20. package/.prettierignore +1 -0
  21. package/AGENTS.md +47 -0
  22. package/CHANGELOG.md +581 -2417
  23. package/CLI-HELP.md +416 -127
  24. package/Dockerfile +25 -9
  25. package/Dockerfile.dev +25 -9
  26. package/Dockerfile.test +4 -4
  27. package/README.md +21 -1
  28. package/bin/build.js +70 -43
  29. package/bin/build.template.js +8 -3
  30. package/bin/cyberia.js +372 -135
  31. package/bin/deploy.js +18 -104
  32. package/bin/index.js +372 -135
  33. package/compose.env +16 -0
  34. package/conf.js +93 -4
  35. package/deploy/cyberia-client/deploy.sh +47 -0
  36. package/deploy/cyberia-client/package.sh +18 -0
  37. package/deploy/cyberia-client/state.sh +14 -0
  38. package/deploy/cyberia-server/deploy.sh +47 -0
  39. package/deploy/cyberia-server/package.sh +18 -0
  40. package/deploy/cyberia-server/state.sh +14 -0
  41. package/deploy/dd-cyberia/deploy.sh +22 -0
  42. package/deploy/dd-cyberia/init.sh +55 -0
  43. package/deploy/dd-cyberia/package.sh +17 -0
  44. package/deploy/dd-cyberia/state.sh +14 -0
  45. package/deploy/dd-cyberia/sync-deploy.sh +116 -0
  46. package/deploy/lib/github-actions-logging.sh +594 -0
  47. package/deploy/lib/host.sh +185 -0
  48. package/deploy/lib/state.sh +62 -0
  49. package/deploy/pwa-microservices-template/deploy.sh +45 -0
  50. package/deploy/release/deploy.sh +32 -0
  51. package/deployment.yaml +7 -2
  52. package/docker-compose.yml +31 -37
  53. package/examples/static-page/README.md +19 -19
  54. package/examples/static-page/ssr-components/CustomPage.js +2 -2
  55. package/hardhat/hardhat.config.js +1 -6
  56. package/hardhat/package-lock.json +104 -43
  57. package/hardhat/package.json +3 -3
  58. package/manifests/alertmanager/deployment.yaml +81 -0
  59. package/manifests/blackbox-exporter/deployment.yaml +75 -0
  60. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
  61. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
  62. package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
  63. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  64. package/manifests/grafana/deployment.yaml +26 -7
  65. package/manifests/grafana/kustomization.yaml +1 -0
  66. package/manifests/grafana/service.yaml +6 -1
  67. package/manifests/mariadb/pv.yaml +1 -0
  68. package/manifests/mongodb/statefulset.yaml +9 -2
  69. package/manifests/mysql/pv-pvc.yaml +14 -1
  70. package/manifests/postgresql/pv.yaml +12 -1
  71. package/manifests/postgresql/pvc.yaml +1 -0
  72. package/manifests/prometheus/deployment.yaml +18 -22
  73. package/package.json +83 -10
  74. package/scripts/audit-selinux.sh +64 -0
  75. package/scripts/event-monitor.sh +56 -0
  76. package/scripts/gpu-diag.sh +0 -0
  77. package/scripts/ip-info.sh +0 -0
  78. package/scripts/k3s-node-setup.sh +30 -14
  79. package/scripts/kubeadm-node-setup.sh +40 -31
  80. package/scripts/lxd-vm-setup.sh +0 -0
  81. package/scripts/maas-nat-firewalld.sh +0 -0
  82. package/scripts/maas-setup.sh +8 -8
  83. package/scripts/nat-iptables.sh +2 -0
  84. package/scripts/rhel-grpc-setup.sh +0 -0
  85. package/scripts/rocky-kickstart.sh +25 -9
  86. package/scripts/selinux-normalize.sh +907 -0
  87. package/scripts/shutdown-machine.sh +843 -0
  88. package/scripts/test-monitor.sh +3 -3
  89. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
  90. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
  91. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
  92. package/src/api/core/core.controller.js +1 -1
  93. package/src/api/core/core.router.js +2 -2
  94. package/src/api/core/core.service.js +2 -2
  95. package/src/api/crypto/crypto.controller.js +1 -1
  96. package/src/api/crypto/crypto.service.js +1 -1
  97. package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
  98. package/src/api/cyberia-action/cyberia-action.router.js +1 -1
  99. package/src/api/cyberia-action/cyberia-action.service.js +2 -2
  100. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
  101. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
  102. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
  103. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
  104. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  105. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
  106. package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
  107. package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
  108. package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
  109. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
  110. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
  111. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
  112. package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
  113. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
  114. package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
  115. package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
  116. package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
  117. package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
  118. package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
  119. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
  120. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
  121. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
  122. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
  123. package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
  124. package/src/api/cyberia-map/cyberia-map.router.js +1 -1
  125. package/src/api/cyberia-map/cyberia-map.service.js +2 -2
  126. package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
  127. package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
  128. package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
  129. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
  130. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
  131. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
  132. package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
  133. package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
  134. package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
  135. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
  136. package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
  137. package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
  138. package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
  139. package/src/api/default/default.controller.js +1 -1
  140. package/src/api/default/default.router.js +1 -1
  141. package/src/api/default/default.service.js +2 -2
  142. package/src/api/document/document.controller.js +1 -1
  143. package/src/api/document/document.router.js +1 -1
  144. package/src/api/document/document.service.js +2 -2
  145. package/src/api/file/file.controller.js +1 -1
  146. package/src/api/file/file.router.js +1 -1
  147. package/src/api/file/file.service.js +2 -2
  148. package/src/api/instance/instance.controller.js +1 -1
  149. package/src/api/instance/instance.router.js +1 -1
  150. package/src/api/instance/instance.service.js +2 -2
  151. package/src/api/ipfs/ipfs.controller.js +1 -1
  152. package/src/api/ipfs/ipfs.router.js +2 -2
  153. package/src/api/ipfs/ipfs.service.js +2 -2
  154. package/src/api/object-layer/object-layer.controller.js +1 -1
  155. package/src/api/object-layer/object-layer.model.js +204 -3
  156. package/src/api/object-layer/object-layer.router.js +2 -2
  157. package/src/api/object-layer/object-layer.service.js +4 -17
  158. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
  159. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
  160. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
  161. package/src/api/test/test.controller.js +1 -1
  162. package/src/api/test/test.service.js +1 -1
  163. package/src/api/user/guest.service.js +3 -3
  164. package/src/api/user/user.controller.js +1 -1
  165. package/src/api/user/user.router.js +2 -2
  166. package/src/api/user/user.service.js +4 -4
  167. package/src/api.js +5 -9
  168. package/src/cli/app.js +391 -0
  169. package/src/cli/baremetal.js +30 -36
  170. package/src/cli/client.js +306 -0
  171. package/src/cli/cloud-init.js +3 -3
  172. package/src/cli/cluster.js +242 -135
  173. package/src/cli/db.js +126 -67
  174. package/src/cli/deploy.js +158 -60
  175. package/src/cli/docker-compose.js +5 -5
  176. package/src/cli/domains.js +184 -0
  177. package/src/cli/dotenv-store.js +143 -0
  178. package/src/cli/event.js +2281 -0
  179. package/src/cli/fs.js +3 -3
  180. package/src/cli/host.js +672 -0
  181. package/src/cli/image.js +4 -7
  182. package/src/cli/index.js +426 -134
  183. package/src/cli/ipfs.js +34 -30
  184. package/src/cli/kickstart.js +1 -1
  185. package/src/cli/kubectl.js +218 -41
  186. package/src/cli/lxd.js +3 -3
  187. package/src/cli/monitor.js +1359 -26
  188. package/src/cli/package.js +90 -0
  189. package/src/cli/release.js +73 -34
  190. package/src/cli/repository.js +564 -367
  191. package/src/cli/run.js +362 -654
  192. package/src/cli/secrets.js +2158 -964
  193. package/src/cli/ssh.js +651 -331
  194. package/src/cli/state.js +394 -0
  195. package/src/cli/static.js +2 -2
  196. package/src/cli/system.js +26 -13
  197. package/src/cli/test.js +199 -125
  198. package/src/cli/vultr.js +623 -0
  199. package/src/cli/wireguard.js +2930 -0
  200. package/src/client/components/core/CalendarCore.js +53 -96
  201. package/src/client/components/core/Docs.js +258 -211
  202. package/src/client/components/core/FileExplorer.js +0 -21
  203. package/src/client/components/core/PanelForm.js +4 -4
  204. package/src/client/components/core/Repository.js +56 -0
  205. package/src/client/components/core/Translate.js +7 -0
  206. package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
  207. package/src/client/components/core/Wallet.js +0 -11
  208. package/src/client/components/core/Worker.js +7 -1
  209. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
  210. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
  211. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
  212. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
  213. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
  214. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
  215. package/src/client/components/default/AppShellDefault.js +1 -1
  216. package/src/client/components/default/SettingsDefault.js +2 -2
  217. package/src/client/components/itemledger/SettingsItemledger.js +2 -2
  218. package/src/client/components/underpost/AppShellUnderpost.js +3 -2
  219. package/src/client/components/underpost/SettingsUnderpost.js +2 -2
  220. package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
  221. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
  222. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
  223. package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
  224. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
  225. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  226. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  227. package/src/client/public/default/android-chrome-144x144.png +0 -0
  228. package/src/client/public/default/android-chrome-192x192.png +0 -0
  229. package/src/client/public/default/android-chrome-256x256.png +0 -0
  230. package/src/client/public/default/android-chrome-36x36.png +0 -0
  231. package/src/client/public/default/android-chrome-384x384.png +0 -0
  232. package/src/client/public/default/android-chrome-48x48.png +0 -0
  233. package/src/client/public/default/android-chrome-512x512.png +0 -0
  234. package/src/client/public/default/android-chrome-72x72.png +0 -0
  235. package/src/client/public/default/android-chrome-96x96.png +0 -0
  236. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  237. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  238. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  239. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  240. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  241. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  242. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  243. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  244. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  245. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  246. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  247. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  248. package/src/client/public/default/apple-touch-icon.png +0 -0
  249. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  250. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  251. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  252. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  253. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  254. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  255. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  256. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  257. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  258. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  259. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  260. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  261. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  262. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  263. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  264. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  265. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  266. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  267. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  268. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  269. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  270. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  271. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  272. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  273. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  274. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  275. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  276. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  277. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  278. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  279. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  280. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  281. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  282. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  283. package/src/client/public/default/assets/background/white.jpg +0 -0
  284. package/src/client/public/default/browserconfig.xml +1 -1
  285. package/src/client/public/default/favicon-16x16.png +0 -0
  286. package/src/client/public/default/favicon-32x32.png +0 -0
  287. package/src/client/public/default/favicon-48x48.png +0 -0
  288. package/src/client/public/default/favicon.ico +0 -0
  289. package/src/client/public/default/manifest.webmanifest +5 -5
  290. package/src/client/public/default/mstile-144x144.png +0 -0
  291. package/src/client/public/default/mstile-150x150.png +0 -0
  292. package/src/client/public/default/mstile-310x150.png +0 -0
  293. package/src/client/public/default/mstile-310x310.png +0 -0
  294. package/src/client/public/default/mstile-70x70.png +0 -0
  295. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  296. package/src/client/public/default/yandex-browser-manifest.json +1 -1
  297. package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
  298. package/src/client/services/object-layer/object-layer.management.js +4 -4
  299. package/src/client/ssr/RootDocument.js +1 -1
  300. package/src/client/ssr/body/404.js +1 -1
  301. package/src/client/ssr/body/500.js +1 -1
  302. package/src/client/ssr/body/CacheControl.js +1 -1
  303. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
  304. package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
  305. package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
  306. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
  307. package/src/client/ssr/head/CryptokoynScripts.js +1 -1
  308. package/src/client/ssr/head/Css.js +1 -1
  309. package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
  310. package/src/client/ssr/head/DefaultScripts.js +1 -1
  311. package/src/client/ssr/head/ItemledgerScripts.js +1 -1
  312. package/src/client/ssr/head/Microdata.js +1 -1
  313. package/src/client/ssr/head/Production.js +1 -1
  314. package/src/client/ssr/head/Pwa.js +1 -1
  315. package/src/client/ssr/head/PwaItemledger.js +1 -1
  316. package/src/client/ssr/head/Seo.js +1 -1
  317. package/src/client/ssr/head/UnderpostScripts.js +1 -1
  318. package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
  319. package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
  320. package/src/client/ssr/views/Cyberia404.js +7 -5
  321. package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
  322. package/src/client/ssr/views/Maintenance.js +1 -1
  323. package/src/client/ssr/views/NoNetworkConnection.js +1 -1
  324. package/src/client/ssr/views/Test.js +1 -1
  325. package/src/client/sw/core.sw.js +20 -14
  326. package/src/client-builder/client-build-docs.js +61 -46
  327. package/src/client-builder/client-build-live.js +2 -2
  328. package/src/client-builder/client-build.js +58 -44
  329. package/src/client-builder/client-dev-server.js +3 -3
  330. package/src/client-builder/client-icons.js +2 -2
  331. package/src/client-builder/ssr.js +3 -3
  332. package/src/client.build.js +3 -6
  333. package/src/client.dev.js +3 -6
  334. package/src/db/DataBaseProvider.js +186 -3
  335. package/src/db/mariadb/MariaDB.js +3 -2
  336. package/src/db/mongo/MongoBootstrap.js +273 -101
  337. package/src/db/mongo/MongooseDB.js +11 -8
  338. package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
  339. package/src/grpc/cyberia/grpc-server.js +1 -1
  340. package/src/index.js +103 -23
  341. package/src/mailer/EmailRender.js +2 -2
  342. package/src/mailer/MailerInterceptor.js +87 -0
  343. package/src/mailer/MailerProvider.js +50 -6
  344. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
  345. package/src/projects/cyberia/besu-genesis-generator.js +3 -3
  346. package/src/projects/cyberia/catalog-cyberia.js +54 -6
  347. package/src/projects/cyberia/gemini-client.js +1 -1
  348. package/src/projects/cyberia/generate-saga.js +15 -24
  349. package/src/projects/cyberia/hot-reload-trigger.js +1 -1
  350. package/src/projects/cyberia/instance-data.js +22 -3
  351. package/src/projects/cyberia/ipfs-client.js +4 -4
  352. package/src/projects/cyberia/map-preview-generator.js +1 -1
  353. package/src/projects/cyberia/object-layer.js +12 -22
  354. package/src/projects/cyberia/semantic-layer-generator.js +1 -1
  355. package/src/projects/underpost/catalog-underpost.js +13 -2
  356. package/src/proxy.js +4 -7
  357. package/src/runtime/cyberia-client/Dockerfile +9 -4
  358. package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
  359. package/src/runtime/cyberia-server/Dockerfile +9 -4
  360. package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
  361. package/src/runtime/engine-cyberia/Dockerfile +25 -9
  362. package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
  363. package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
  364. package/src/runtime/engine-cyberia/compose.env +16 -0
  365. package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
  366. package/src/runtime/express/Express.js +32 -27
  367. package/src/runtime/lampp/Lampp.js +22 -70
  368. package/src/runtime/nginx/Nginx.js +1 -1
  369. package/src/runtime/wp/Wp.js +16 -48
  370. package/src/server/{catalog.js → build/catalog.js} +15 -5
  371. package/src/server/build/coverage.js +117 -0
  372. package/src/server/build/execution.js +402 -0
  373. package/src/server/build/package.js +465 -0
  374. package/src/server/build/testing.js +528 -0
  375. package/src/server/{dns.js → network/dns.js} +241 -14
  376. package/src/server/network/forward-proxy.js +541 -0
  377. package/src/server/{middlewares.js → network/middlewares.js} +59 -4
  378. package/src/server/network/node-capability.js +98 -0
  379. package/src/server/{peer.js → network/peer.js} +3 -3
  380. package/src/server/{proxy.js → network/proxy.js} +7 -13
  381. package/src/server/network/router.js +356 -0
  382. package/src/server/{tls.js → network/tls.js} +2 -2
  383. package/src/server/network/underpost-compression.js +186 -0
  384. package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
  385. package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
  386. package/src/server/{cri.js → ops/cri.js} +2 -2
  387. package/src/server/ops/cron.js +949 -0
  388. package/src/server/ops/event-notification.js +284 -0
  389. package/src/server/{logger.js → ops/logger.js} +108 -23
  390. package/src/server/ops/monitoring.js +1724 -0
  391. package/src/server/ops/systemd.js +259 -0
  392. package/src/server/{conf.js → runtime/conf.js} +521 -520
  393. package/src/server/runtime/config-scope.js +215 -0
  394. package/src/server/runtime/environment.js +149 -0
  395. package/src/server/{process.js → runtime/process.js} +153 -13
  396. package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
  397. package/src/server/{runtime.js → runtime/runtime.js} +12 -8
  398. package/src/server/{start.js → runtime/start.js} +128 -39
  399. package/src/server/{auth.js → security/auth.js} +7 -8
  400. package/src/server/security/container-storage.js +382 -0
  401. package/src/server/{crypto.js → security/crypto.js} +1 -1
  402. package/src/server/security/selinux.js +185 -0
  403. package/src/server/{backup.js → storage/backup.js} +17 -8
  404. package/src/server/{data-query.js → storage/data-query.js} +1 -1
  405. package/src/server/{downloader.js → storage/downloader.js} +2 -2
  406. package/src/server/storage/repository.js +68 -0
  407. package/src/server.js +4 -7
  408. package/src/ws/IoInterface.js +1 -1
  409. package/src/ws/IoServer.js +1 -1
  410. package/src/ws/core/core.ws.connection.js +1 -1
  411. package/src/ws/core/core.ws.emit.js +1 -1
  412. package/src/ws/core/core.ws.server.js +1 -1
  413. package/src/ws/default/default.ws.connection.js +1 -1
  414. package/src/ws/default/default.ws.emit.js +1 -1
  415. package/src/ws/default/default.ws.server.js +1 -1
  416. package/test/e2e/event-e2e-public-ingress-down.js +45 -0
  417. package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
  418. package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
  419. package/test/{api.test.js → integration/app/api.test.js} +33 -14
  420. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
  421. package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
  422. package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
  423. package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
  424. package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
  425. package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
  426. package/test/integration/infra/1-security/config-scope.test.js +305 -0
  427. package/test/integration/infra/1-security/container-storage.test.js +356 -0
  428. package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
  429. package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
  430. package/test/integration/infra/1-security/selinux.test.js +69 -0
  431. package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
  432. package/test/integration/infra/1-security/systemd-service.test.js +70 -0
  433. package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
  434. package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
  435. package/test/integration/infra/2-network/node-capability.test.js +182 -0
  436. package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
  437. package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
  438. package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
  439. package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
  440. package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
  441. package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
  442. package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
  443. package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
  444. package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
  445. package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
  446. package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
  447. package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
  448. package/test/integration/infra/5-observability/event-notification.test.js +197 -0
  449. package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
  450. package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
  451. package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
  452. package/test/support/shell-harness.js +73 -0
  453. package/test/unit/build-template.test.js +97 -0
  454. package/test/unit/build-workflow-offline.test.js +132 -0
  455. package/test/unit/catalog.test.js +71 -0
  456. package/test/unit/client-build-docs.test.js +334 -0
  457. package/test/unit/conf-loading.test.js +303 -0
  458. package/test/unit/conf-resolution.test.js +979 -0
  459. package/test/unit/coverage-artifact.test.js +130 -0
  460. package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
  461. package/test/unit/deploy-env-resolution.test.js +38 -0
  462. package/test/unit/deploy-log-table.test.js +447 -0
  463. package/test/unit/execution-profiles.test.js +219 -0
  464. package/test/unit/fleet-sync-source.test.js +149 -0
  465. package/test/unit/logger-redaction.test.js +112 -0
  466. package/test/unit/package.test.js +403 -0
  467. package/test/unit/prepare-host.test.js +299 -0
  468. package/test/unit/process-environment.test.js +18 -0
  469. package/test/unit/propagation-message.test.js +78 -0
  470. package/test/unit/redeploy-plan.test.js +24 -0
  471. package/test/unit/release-bump.test.js +474 -0
  472. package/test/unit/ssh-output-redaction.test.js +28 -0
  473. package/test/unit/start-options.test.js +46 -0
  474. package/test/unit/test-tiers.test.js +193 -0
  475. package/vitest.config.js +58 -0
  476. package/.nycrc +0 -9
  477. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
  478. package/manifests/mongodb/pv-pvc.yaml +0 -59
  479. package/scripts/link-local-underpost-cli.sh +0 -6
  480. package/src/api/user/user.build.js +0 -16
  481. package/src/cli/env.js +0 -177
  482. package/src/client/components/core/Blockchain.js +0 -41
  483. package/src/client/components/core/Blog.js +0 -9
  484. package/src/client/components/core/KeyboardAvoidance.js +0 -145
  485. package/src/client/public/default/assets/background/dark.jpg +0 -0
  486. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  487. package/src/client/public/default/assets/background/white0.jpg +0 -0
  488. package/src/client/public/doc/favicon.ico +0 -0
  489. package/src/client/public/doc/sitemap +0 -148
  490. package/src/server/cron.js +0 -476
@@ -0,0 +1,465 @@
1
+ /**
2
+ * Package manifest and archive build utilities.
3
+ *
4
+ * @module src/server/build/package.js
5
+ * @namespace PackageBuilder
6
+ */
7
+
8
+ import fs from 'fs-extra';
9
+ import os from 'node:os';
10
+ import nodePath from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { loggerFactory } from '../ops/logger.js';
13
+ import { shellArgumentFactory, shellExec } from '../runtime/process.js';
14
+ import { loadDeployCatalog } from './catalog.js';
15
+
16
+ const logger = loggerFactory(import.meta);
17
+ const ENGINE_PACKAGE_PATH = fileURLToPath(new URL('../../../', import.meta.url));
18
+ const STAGED_CLI_PACKAGE = 'underpost-cli.tgz';
19
+ const DEPLOY_CONF_ROOT = './engine-private/conf';
20
+ const DEPLOY_MANIFEST_INDENT = 4;
21
+
22
+ /**
23
+ * Packs an npm package into a build context under a stable file name.
24
+ *
25
+ * @param {object} params
26
+ * @param {string} params.stagedFileName
27
+ * @param {string} [params.outputPath]
28
+ * @param {string} [params.packagePath]
29
+ * @returns {string} Absolute path to the staged archive.
30
+ * @memberof PackageBuilder
31
+ */
32
+ const stagePackageArchive = ({ stagedFileName, outputPath = '.', packagePath = '.' } = {}) => {
33
+ if (!stagedFileName || nodePath.basename(stagedFileName) !== stagedFileName)
34
+ throw new TypeError('stagePackageArchive requires a file name without a directory');
35
+
36
+ const sourcePath = nodePath.resolve(packagePath);
37
+ const destinationPath = nodePath.resolve(outputPath);
38
+ if (!fs.existsSync(nodePath.join(sourcePath, 'package.json')))
39
+ throw new Error(`Package manifest not found: ${nodePath.join(sourcePath, 'package.json')}`);
40
+
41
+ fs.ensureDirSync(destinationPath);
42
+ const temporaryPath = fs.mkdtempSync(nodePath.join(os.tmpdir(), 'underpost-package-'));
43
+
44
+ try {
45
+ shellExec(
46
+ `npm pack --ignore-scripts --pack-destination ${shellArgumentFactory(temporaryPath)} ${shellArgumentFactory(sourcePath)}`,
47
+ { silent: true },
48
+ );
49
+ const archives = fs.readdirSync(temporaryPath).filter((entry) => entry.endsWith('.tgz'));
50
+ if (archives.length !== 1)
51
+ throw new Error(
52
+ `Expected exactly one package archive for ${sourcePath}, found ${archives.length}: ${archives.join(', ')}`,
53
+ );
54
+
55
+ const stagedPath = nodePath.join(destinationPath, stagedFileName);
56
+ fs.moveSync(nodePath.join(temporaryPath, archives[0]), stagedPath, { overwrite: true });
57
+ logger.info('Staged npm package archive', { source: archives[0], staged: stagedPath });
58
+ return stagedPath;
59
+ } finally {
60
+ fs.removeSync(temporaryPath);
61
+ }
62
+ };
63
+
64
+ /**
65
+ * Stages this engine checkout as the CLI archive consumed by runtime images.
66
+ *
67
+ * @param {string} [outputPath]
68
+ * @returns {string} Absolute path to the staged archive.
69
+ * @memberof PackageBuilder
70
+ */
71
+ const stageCliPackage = (outputPath = '.') =>
72
+ stagePackageArchive({
73
+ stagedFileName: STAGED_CLI_PACKAGE,
74
+ outputPath,
75
+ packagePath: ENGINE_PACKAGE_PATH,
76
+ });
77
+
78
+ const replaceTemplateReferences = (value, templateRepositoryName, repositoryName) => {
79
+ if (!templateRepositoryName || !repositoryName) return value;
80
+ if (typeof value === 'string') return value.replaceAll(templateRepositoryName, repositoryName);
81
+ if (Array.isArray(value))
82
+ return value.map((entry) => replaceTemplateReferences(entry, templateRepositoryName, repositoryName));
83
+ if (value && typeof value === 'object')
84
+ return Object.fromEntries(
85
+ Object.entries(value).map(([key, entry]) => [
86
+ key,
87
+ replaceTemplateReferences(entry, templateRepositoryName, repositoryName),
88
+ ]),
89
+ );
90
+ return value;
91
+ };
92
+
93
+ /**
94
+ * Builds the development dependency set for a generated product repository.
95
+ *
96
+ * Product packages replace the engine's broad runtime dependency set with a
97
+ * deliberately small product-specific one. The generated repository still
98
+ * contains the engine source, build scripts, Vitest configuration and tests,
99
+ * though, so those engine dependencies remain necessary when developing or
100
+ * testing the checkout. Keeping them as dev dependencies makes CI complete
101
+ * without adding them to installations of the published product package.
102
+ *
103
+ * @param {object} [params]
104
+ * @param {Record<string, string>} [params.engineDependencies]
105
+ * @param {Record<string, string>} [params.engineDevDependencies]
106
+ * @param {Record<string, string>} [params.productDependencies]
107
+ * @param {Record<string, string>} [params.productDevDependencies]
108
+ * @returns {Record<string, string>}
109
+ * @memberof PackageBuilder
110
+ */
111
+ const productDevDependenciesFactory = ({
112
+ engineDependencies = {},
113
+ engineDevDependencies = {},
114
+ productDependencies = {},
115
+ productDevDependencies = {},
116
+ } = {}) => {
117
+ const developmentDependencies = {
118
+ ...engineDependencies,
119
+ ...engineDevDependencies,
120
+ ...productDevDependencies,
121
+ };
122
+
123
+ for (const dependency of Object.keys(productDependencies)) delete developmentDependencies[dependency];
124
+
125
+ return developmentDependencies;
126
+ };
127
+
128
+ /**
129
+ * Returns a generated product manifest without mutating its inputs.
130
+ *
131
+ * @param {object} params
132
+ * @param {object} params.basePackageJson
133
+ * @param {object} [params.sourcePackageJson]
134
+ * @param {object} [params.catalog]
135
+ * @param {string} params.confName
136
+ * @param {Record<string, string>} [params.customDependencies]
137
+ * @param {Record<string, string>} [params.customScripts]
138
+ * @param {Record<string, string>} [params.customBin]
139
+ * @param {string} [params.templateRepositoryName]
140
+ * @param {string} [params.repositoryName]
141
+ * @returns {object}
142
+ * @memberof PackageBuilder
143
+ */
144
+ const buildProductPackageJson = ({
145
+ basePackageJson,
146
+ sourcePackageJson = basePackageJson,
147
+ catalog = {},
148
+ confName,
149
+ customDependencies,
150
+ customScripts = {},
151
+ customBin,
152
+ templateRepositoryName = 'pwa-microservices-template',
153
+ repositoryName = `engine-${confName?.replace(/^dd-/, '')}`,
154
+ } = {}) => {
155
+ if (!basePackageJson || typeof basePackageJson !== 'object')
156
+ throw new TypeError('buildProductPackageJson requires basePackageJson');
157
+ if (!confName) throw new TypeError('buildProductPackageJson requires confName');
158
+
159
+ const base = replaceTemplateReferences(basePackageJson, templateRepositoryName, repositoryName);
160
+ const { devDependencies: baseDevDependencies, ...baseManifest } = base;
161
+ const dependencies = customDependencies === undefined ? { ...base.dependencies } : { ...customDependencies };
162
+ const devDependencies =
163
+ customDependencies === undefined
164
+ ? { ...baseDevDependencies }
165
+ : productDevDependenciesFactory({
166
+ engineDependencies: sourcePackageJson?.dependencies,
167
+ engineDevDependencies: sourcePackageJson?.devDependencies,
168
+ productDependencies: dependencies,
169
+ productDevDependencies: baseDevDependencies,
170
+ });
171
+
172
+ return {
173
+ ...baseManifest,
174
+ name: confName.replace(/^dd-/, ''),
175
+ ...(catalog.description ? { description: catalog.description } : {}),
176
+ ...(catalog.keywords?.length ? { keywords: [...catalog.keywords] } : {}),
177
+ dependencies,
178
+ ...(Object.keys(devDependencies).length ? { devDependencies } : {}),
179
+ scripts: { ...base.scripts, ...customScripts },
180
+ ...(customBin === undefined ? {} : { bin: { ...customBin } }),
181
+ };
182
+ };
183
+
184
+ /**
185
+ * Where a deploy id's package manifest lives.
186
+ *
187
+ * A deploy's manifest is part of its configuration, next to `conf.server.json` and its env
188
+ * files, so it is versioned with them rather than derived on the node.
189
+ * @param {string} deployId - Deploy id (e.g. `dd-cyberia`).
190
+ * @param {string} [confRoot] - Root of the private configuration tree.
191
+ * @returns {string} Path to that deploy's `package.json`.
192
+ * @memberof PackageBuilder
193
+ */
194
+ const deployPackagePathFactory = (deployId, confRoot = DEPLOY_CONF_ROOT) => `${confRoot}/${deployId}/package.json`;
195
+
196
+ /**
197
+ * The npm name a deploy id publishes under.
198
+ *
199
+ * A catalog names its own package; every other deploy id is its own identity without the `dd-`
200
+ * prefix. One rule, so a manifest cannot be renamed by whichever command generated it.
201
+ * @param {string} deployId - Deploy id.
202
+ * @param {object} [catalog] - That deploy's product catalog.
203
+ * @returns {string} Package name.
204
+ * @memberof PackageBuilder
205
+ */
206
+ const deployPackageNameFactory = (deployId, catalog = {}) =>
207
+ `${catalog.packageName || `${deployId ?? ''}`.replace(/^dd-/, '')}`;
208
+
209
+ /**
210
+ * The `start` script a deploy runs under.
211
+ *
212
+ * A catalog may declare its own, and an existing manifest's is preserved — a deploy that starts
213
+ * something other than the engine server (a cron applier, say) keeps saying so across a
214
+ * regeneration. Only a manifest that declares nothing gets the engine default.
215
+ * @param {string} deployId - Deploy id.
216
+ * @param {object} [catalog] - That deploy's product catalog.
217
+ * @param {object} [currentPackageJson] - The manifest being regenerated, when one exists.
218
+ * @returns {string} Start script.
219
+ * @memberof PackageBuilder
220
+ */
221
+ const deployStartScriptFactory = (deployId, catalog = {}, currentPackageJson = {}) =>
222
+ catalog.packageScripts?.start ||
223
+ currentPackageJson?.scripts?.start ||
224
+ `node --max-old-space-size=8192 src/server ${deployId}`;
225
+
226
+ /**
227
+ * Builds a deploy id's package manifest from the engine's, without mutating either input.
228
+ *
229
+ * One generator for every deploy manifest in the project. The engine manifest is the base —
230
+ * its dependencies, overrides and toolchain scripts are what the checkout actually runs on —
231
+ * and the deploy owns only its identity, its `start`, and whatever its catalog adds. A deploy
232
+ * id without a catalog is therefore the engine manifest under its own name, which is the whole
233
+ * default: nothing has to be declared for a new deploy to have a correct manifest.
234
+ *
235
+ * `productIdentity` selects the standalone CLI's bin map over the engine's. It is off for a
236
+ * deploy's own manifest on purpose: that manifest is installed over the engine checkout on
237
+ * hosts and in pods, where `npm link` must keep publishing the engine's command.
238
+ * @param {object} params
239
+ * @param {string} params.deployId - Deploy id the manifest belongs to.
240
+ * @param {object} params.enginePackageJson - The engine's own manifest.
241
+ * @param {object} [params.catalog] - That deploy's product catalog.
242
+ * @param {object} [params.currentPackageJson] - The manifest being regenerated, when one exists.
243
+ * @param {boolean} [params.productIdentity] - Use the catalog's bin map instead of the engine's.
244
+ * @returns {object} The generated manifest.
245
+ * @memberof PackageBuilder
246
+ */
247
+ const buildDeployPackageJson = ({
248
+ deployId,
249
+ enginePackageJson,
250
+ catalog = {},
251
+ currentPackageJson = {},
252
+ productIdentity = false,
253
+ } = {}) => {
254
+ if (!deployId) throw new TypeError('buildDeployPackageJson requires deployId');
255
+ if (!enginePackageJson || typeof enginePackageJson !== 'object')
256
+ throw new TypeError('buildDeployPackageJson requires enginePackageJson');
257
+
258
+ const catalogBin = catalog.packageBin && Object.keys(catalog.packageBin).length ? { ...catalog.packageBin } : null;
259
+ const bin = productIdentity && catalogBin ? catalogBin : enginePackageJson.bin;
260
+
261
+ return {
262
+ ...enginePackageJson,
263
+ name: deployPackageNameFactory(deployId, catalog),
264
+ ...(catalog.description ? { description: catalog.description } : {}),
265
+ ...(catalog.keywords?.length ? { keywords: [...catalog.keywords] } : {}),
266
+ scripts: {
267
+ ...enginePackageJson.scripts,
268
+ ...catalog.packageScripts,
269
+ start: deployStartScriptFactory(deployId, catalog, currentPackageJson),
270
+ },
271
+ dependencies: { ...enginePackageJson.dependencies, ...catalog.packageDependencies },
272
+ ...(bin === undefined ? {} : { bin: { ...bin } }),
273
+ };
274
+ };
275
+
276
+ /**
277
+ * The product-CLI manifest overrides a catalog declares, for {@link buildProductPackageJson}.
278
+ *
279
+ * A product package replaces the engine's runtime dependency set with its own, so it always
280
+ * carries the published `underpost` alongside whatever the catalog pins. A catalog that
281
+ * declares no package contract returns nothing, leaving the base template's manifest as it is.
282
+ * @param {object} params
283
+ * @param {object} params.catalog - The deploy's product catalog.
284
+ * @param {string} params.underpostVersion - Version of the engine CLI the product depends on.
285
+ * @returns {{customDependencies?: object, customScripts?: object, customBin?: object}} Overrides.
286
+ * @memberof PackageBuilder
287
+ */
288
+ const productPackageOptionsFactory = ({ catalog = {}, underpostVersion = '' } = {}) => {
289
+ const dependencies = catalog.packageDependencies ?? {};
290
+ const bin = catalog.packageBin ?? {};
291
+ if (Object.keys(dependencies).length === 0 && Object.keys(bin).length === 0) return {};
292
+
293
+ return {
294
+ customDependencies: { underpost: `^${`${underpostVersion}`.replace(/^v/, '')}`, ...dependencies },
295
+ customScripts: { ...catalog.packageScripts },
296
+ ...(Object.keys(bin).length ? { customBin: { ...bin } } : {}),
297
+ };
298
+ };
299
+
300
+ /**
301
+ * Regenerates the package manifest of every deploy id that has one.
302
+ *
303
+ * The engine's manifest is the source: a dependency added there reaches every deploy from here,
304
+ * which is what keeps a node's install from pruning packages the CLI imports. Deploy ids are
305
+ * discovered from the configuration tree rather than listed, so a new deploy is covered by
306
+ * existing.
307
+ * @param {object} [params]
308
+ * @param {string[]} [params.deployIds] - Deploy ids to regenerate; every one that has a manifest otherwise.
309
+ * @param {string} [params.confRoot] - Root of the private configuration tree.
310
+ * @param {object} [params.enginePackageJson] - The engine's own manifest.
311
+ * @param {boolean} [params.dryRun] - Resolve the manifests without writing them.
312
+ * @returns {Promise<Array<{deployId: string, path: string, name: string}>>} What was regenerated.
313
+ * @memberof PackageBuilder
314
+ */
315
+ const syncDeployPackages = async ({
316
+ deployIds = [],
317
+ confRoot = DEPLOY_CONF_ROOT,
318
+ enginePackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8')),
319
+ dryRun = false,
320
+ } = {}) => {
321
+ if (!fs.existsSync(confRoot)) {
322
+ logger.warn('No private configuration tree to sync deploy manifests into', { confRoot });
323
+ return [];
324
+ }
325
+
326
+ const selected = deployIds.length > 0 ? deployIds : fs.readdirSync(confRoot).sort();
327
+ const synced = [];
328
+ for (const deployId of selected) {
329
+ const manifestPath = deployPackagePathFactory(deployId, confRoot);
330
+ if (!fs.existsSync(manifestPath)) {
331
+ // A deploy id named explicitly is a request, not a discovery: say which one has no
332
+ // manifest instead of reporting a silent no-op.
333
+ if (deployIds.length > 0) logger.warn('Deploy has no package manifest to sync', { deployId, manifestPath });
334
+ continue;
335
+ }
336
+
337
+ const currentPackageJson = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
338
+ const packageJson = buildDeployPackageJson({
339
+ deployId,
340
+ enginePackageJson,
341
+ catalog: await loadDeployCatalog(deployId),
342
+ currentPackageJson,
343
+ });
344
+ if (!dryRun)
345
+ fs.writeFileSync(manifestPath, `${JSON.stringify(packageJson, null, DEPLOY_MANIFEST_INDENT)}\n`, 'utf8');
346
+ synced.push({ deployId, path: manifestPath, name: packageJson.name });
347
+ }
348
+
349
+ logger.info('Deploy package manifests synced', { count: synced.length, dryRun, confRoot });
350
+ return synced;
351
+ };
352
+
353
+ /**
354
+ * The `repository` field a package points at.
355
+ *
356
+ * @param {string} slug - Repository `owner/repo` slug.
357
+ * @returns {{type: string, url: string}} Manifest repository entry.
358
+ * @memberof PackageBuilder
359
+ */
360
+ const packageRepositoryFactory = (slug) => ({ type: 'git', url: `git+https://github.com/${slug}.git` });
361
+
362
+ const readManifest = (path) => JSON.parse(fs.readFileSync(path, 'utf8'));
363
+ const writeManifest = (path, manifest) =>
364
+ fs.writeFileSync(path, `${JSON.stringify(manifest, null, DEPLOY_MANIFEST_INDENT)}\n`, 'utf8');
365
+
366
+ /**
367
+ * Renames a checkout's package, in its manifest and its lockfile.
368
+ *
369
+ * Both carry the name, and npm rejects an install where they disagree, so they are one
370
+ * operation. A checkout with no lockfile is renamed just as well.
371
+ * @param {object} params
372
+ * @param {string} params.name - New package name.
373
+ * @param {string} [params.packagePath] - Manifest to rename.
374
+ * @param {string} [params.lockPath] - Lockfile to rename alongside it.
375
+ * @returns {{name: string, files: string[]}} The name applied and where.
376
+ * @memberof PackageBuilder
377
+ */
378
+ const renamePackage = ({ name, packagePath = './package.json', lockPath = './package-lock.json' } = {}) => {
379
+ if (!name) throw new TypeError('renamePackage requires name');
380
+
381
+ writeManifest(packagePath, { ...readManifest(packagePath), name });
382
+ const files = [packagePath];
383
+
384
+ if (fs.existsSync(lockPath)) {
385
+ const lock = readManifest(lockPath);
386
+ writeManifest(lockPath, {
387
+ ...lock,
388
+ name,
389
+ ...(lock.packages?.[''] ? { packages: { ...lock.packages, '': { ...lock.packages[''], name } } } : {}),
390
+ });
391
+ files.push(lockPath);
392
+ }
393
+
394
+ logger.info('Package renamed', { name, files });
395
+ return { name, files };
396
+ };
397
+
398
+ /**
399
+ * Points a checkout's package at a repository.
400
+ *
401
+ * @param {object} params
402
+ * @param {string} params.slug - Repository `owner/repo` slug.
403
+ * @param {string} [params.packagePath] - Manifest to update.
404
+ * @returns {{repository: object}} The repository entry applied.
405
+ * @memberof PackageBuilder
406
+ */
407
+ const setPackageRepository = ({ slug, packagePath = './package.json' } = {}) => {
408
+ if (!slug) throw new TypeError('setPackageRepository requires slug');
409
+
410
+ const repository = packageRepositoryFactory(slug);
411
+ writeManifest(packagePath, { ...readManifest(packagePath), repository });
412
+ logger.info('Package repository set', { slug, packagePath });
413
+ return { repository };
414
+ };
415
+
416
+ /**
417
+ * The install specifiers a deploy's catalog pins, as `name@version`.
418
+ *
419
+ * The pins are the catalog's, so an install and a generated manifest cannot disagree about a
420
+ * version.
421
+ * @param {object} [catalog] - The deploy's product catalog.
422
+ * @returns {string[]} Specifiers, in declaration order.
423
+ * @memberof PackageBuilder
424
+ */
425
+ const deployDependencySpecsFactory = (catalog = {}) =>
426
+ Object.entries(catalog.packageDependencies ?? {}).map(([name, version]) => `${name}@${version}`);
427
+
428
+ /**
429
+ * Installs a deploy's catalog dependencies into the current checkout, at their pinned versions.
430
+ *
431
+ * @param {string} deployId - Deploy id whose catalog dependencies are installed.
432
+ * @param {object} [catalog] - Pre-loaded catalog; loaded from the deploy id otherwise.
433
+ * @returns {Promise<string[]>} The dependencies installed, as `name@version`.
434
+ * @memberof PackageBuilder
435
+ */
436
+ const installDeployDependencies = async (deployId, catalog) => {
437
+ const specs = deployDependencySpecsFactory(catalog ?? (await loadDeployCatalog(deployId)));
438
+ if (specs.length === 0) {
439
+ logger.warn('Deploy declares no catalog dependencies', { deployId });
440
+ return specs;
441
+ }
442
+ shellExec(`npm install ${specs.join(' ')}`);
443
+ return specs;
444
+ };
445
+
446
+ export {
447
+ DEPLOY_CONF_ROOT,
448
+ DEPLOY_MANIFEST_INDENT,
449
+ STAGED_CLI_PACKAGE,
450
+ buildDeployPackageJson,
451
+ buildProductPackageJson,
452
+ deployDependencySpecsFactory,
453
+ deployPackageNameFactory,
454
+ deployPackagePathFactory,
455
+ deployStartScriptFactory,
456
+ installDeployDependencies,
457
+ packageRepositoryFactory,
458
+ productDevDependenciesFactory,
459
+ productPackageOptionsFactory,
460
+ renamePackage,
461
+ setPackageRepository,
462
+ stageCliPackage,
463
+ stagePackageArchive,
464
+ syncDeployPackages,
465
+ };