@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.
- package/.dockerignore +1 -0
- package/.env.example +16 -0
- package/.github/workflows/coverall.cyberia.ci.yml +107 -0
- package/.github/workflows/cyberia-client.cd.yml +6 -18
- package/.github/workflows/cyberia-server.cd.yml +6 -18
- package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
- package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
- package/.github/workflows/engine-cyberia.cd.yml +6 -78
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +42 -21
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +2 -9
- package/.prettierignore +1 -0
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +581 -2417
- package/CLI-HELP.md +416 -127
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +4 -4
- package/README.md +21 -1
- package/bin/build.js +70 -43
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +372 -135
- package/bin/deploy.js +18 -104
- package/bin/index.js +372 -135
- package/compose.env +16 -0
- package/conf.js +93 -4
- package/deploy/cyberia-client/deploy.sh +47 -0
- package/deploy/cyberia-client/package.sh +18 -0
- package/deploy/cyberia-client/state.sh +14 -0
- package/deploy/cyberia-server/deploy.sh +47 -0
- package/deploy/cyberia-server/package.sh +18 -0
- package/deploy/cyberia-server/state.sh +14 -0
- package/deploy/dd-cyberia/deploy.sh +22 -0
- package/deploy/dd-cyberia/init.sh +55 -0
- package/deploy/dd-cyberia/package.sh +17 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +116 -0
- package/deploy/lib/github-actions-logging.sh +594 -0
- package/deploy/lib/host.sh +185 -0
- package/deploy/lib/state.sh +62 -0
- package/deploy/pwa-microservices-template/deploy.sh +45 -0
- package/deploy/release/deploy.sh +32 -0
- package/deployment.yaml +7 -2
- package/docker-compose.yml +31 -37
- package/examples/static-page/README.md +19 -19
- package/examples/static-page/ssr-components/CustomPage.js +2 -2
- package/hardhat/hardhat.config.js +1 -6
- package/hardhat/package-lock.json +104 -43
- package/hardhat/package.json +3 -3
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/grafana/deployment.yaml +26 -7
- package/manifests/grafana/kustomization.yaml +1 -0
- package/manifests/grafana/service.yaml +6 -1
- package/manifests/mariadb/pv.yaml +1 -0
- package/manifests/mongodb/statefulset.yaml +9 -2
- package/manifests/mysql/pv-pvc.yaml +14 -1
- package/manifests/postgresql/pv.yaml +12 -1
- package/manifests/postgresql/pvc.yaml +1 -0
- package/manifests/prometheus/deployment.yaml +18 -22
- package/package.json +83 -10
- package/scripts/audit-selinux.sh +64 -0
- package/scripts/event-monitor.sh +56 -0
- package/scripts/gpu-diag.sh +0 -0
- package/scripts/ip-info.sh +0 -0
- package/scripts/k3s-node-setup.sh +30 -14
- package/scripts/kubeadm-node-setup.sh +40 -31
- package/scripts/lxd-vm-setup.sh +0 -0
- package/scripts/maas-nat-firewalld.sh +0 -0
- package/scripts/maas-setup.sh +8 -8
- package/scripts/nat-iptables.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +0 -0
- package/scripts/rocky-kickstart.sh +25 -9
- package/scripts/selinux-normalize.sh +907 -0
- package/scripts/shutdown-machine.sh +843 -0
- package/scripts/test-monitor.sh +3 -3
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
- package/src/api/core/core.controller.js +1 -1
- package/src/api/core/core.router.js +2 -2
- package/src/api/core/core.service.js +2 -2
- package/src/api/crypto/crypto.controller.js +1 -1
- package/src/api/crypto/crypto.service.js +1 -1
- package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +1 -1
- package/src/api/cyberia-action/cyberia-action.service.js +2 -2
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
- package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
- package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
- package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
- package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
- package/src/api/cyberia-map/cyberia-map.router.js +1 -1
- package/src/api/cyberia-map/cyberia-map.service.js +2 -2
- package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
- package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
- package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
- package/src/api/default/default.controller.js +1 -1
- package/src/api/default/default.router.js +1 -1
- package/src/api/default/default.service.js +2 -2
- package/src/api/document/document.controller.js +1 -1
- package/src/api/document/document.router.js +1 -1
- package/src/api/document/document.service.js +2 -2
- package/src/api/file/file.controller.js +1 -1
- package/src/api/file/file.router.js +1 -1
- package/src/api/file/file.service.js +2 -2
- package/src/api/instance/instance.controller.js +1 -1
- package/src/api/instance/instance.router.js +1 -1
- package/src/api/instance/instance.service.js +2 -2
- package/src/api/ipfs/ipfs.controller.js +1 -1
- package/src/api/ipfs/ipfs.router.js +2 -2
- package/src/api/ipfs/ipfs.service.js +2 -2
- package/src/api/object-layer/object-layer.controller.js +1 -1
- package/src/api/object-layer/object-layer.model.js +204 -3
- package/src/api/object-layer/object-layer.router.js +2 -2
- package/src/api/object-layer/object-layer.service.js +4 -17
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
- package/src/api/test/test.controller.js +1 -1
- package/src/api/test/test.service.js +1 -1
- package/src/api/user/guest.service.js +3 -3
- package/src/api/user/user.controller.js +1 -1
- package/src/api/user/user.router.js +2 -2
- package/src/api/user/user.service.js +4 -4
- package/src/api.js +5 -9
- package/src/cli/app.js +391 -0
- package/src/cli/baremetal.js +30 -36
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +242 -135
- package/src/cli/db.js +126 -67
- package/src/cli/deploy.js +158 -60
- package/src/cli/docker-compose.js +5 -5
- package/src/cli/domains.js +184 -0
- package/src/cli/dotenv-store.js +143 -0
- package/src/cli/event.js +2281 -0
- package/src/cli/fs.js +3 -3
- package/src/cli/host.js +672 -0
- package/src/cli/image.js +4 -7
- package/src/cli/index.js +426 -134
- package/src/cli/ipfs.js +34 -30
- package/src/cli/kickstart.js +1 -1
- package/src/cli/kubectl.js +218 -41
- package/src/cli/lxd.js +3 -3
- package/src/cli/monitor.js +1359 -26
- package/src/cli/package.js +90 -0
- package/src/cli/release.js +73 -34
- package/src/cli/repository.js +564 -367
- package/src/cli/run.js +362 -654
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +651 -331
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +26 -13
- package/src/cli/test.js +199 -125
- package/src/cli/vultr.js +623 -0
- package/src/cli/wireguard.js +2930 -0
- package/src/client/components/core/CalendarCore.js +53 -96
- package/src/client/components/core/Docs.js +258 -211
- package/src/client/components/core/FileExplorer.js +0 -21
- package/src/client/components/core/PanelForm.js +4 -4
- package/src/client/components/core/Repository.js +56 -0
- package/src/client/components/core/Translate.js +7 -0
- package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
- package/src/client/components/core/Wallet.js +0 -11
- package/src/client/components/core/Worker.js +7 -1
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
- package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppShellDefault.js +1 -1
- package/src/client/components/default/SettingsDefault.js +2 -2
- package/src/client/components/itemledger/SettingsItemledger.js +2 -2
- package/src/client/components/underpost/AppShellUnderpost.js +3 -2
- package/src/client/components/underpost/SettingsUnderpost.js +2 -2
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
- package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-384x384.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-512x512.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/default/assets/background/white.jpg +0 -0
- package/src/client/public/default/browserconfig.xml +1 -1
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon-48x48.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/manifest.webmanifest +5 -5
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/yandex-browser-50x50.png +0 -0
- package/src/client/public/default/yandex-browser-manifest.json +1 -1
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
- package/src/client/services/object-layer/object-layer.management.js +4 -4
- package/src/client/ssr/RootDocument.js +1 -1
- package/src/client/ssr/body/404.js +1 -1
- package/src/client/ssr/body/500.js +1 -1
- package/src/client/ssr/body/CacheControl.js +1 -1
- package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
- package/src/client/ssr/head/CryptokoynScripts.js +1 -1
- package/src/client/ssr/head/Css.js +1 -1
- package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +1 -1
- package/src/client/ssr/head/ItemledgerScripts.js +1 -1
- package/src/client/ssr/head/Microdata.js +1 -1
- package/src/client/ssr/head/Production.js +1 -1
- package/src/client/ssr/head/Pwa.js +1 -1
- package/src/client/ssr/head/PwaItemledger.js +1 -1
- package/src/client/ssr/head/Seo.js +1 -1
- package/src/client/ssr/head/UnderpostScripts.js +1 -1
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
- package/src/client/ssr/views/Cyberia404.js +7 -5
- package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/views/Maintenance.js +1 -1
- package/src/client/ssr/views/NoNetworkConnection.js +1 -1
- package/src/client/ssr/views/Test.js +1 -1
- package/src/client/sw/core.sw.js +20 -14
- package/src/client-builder/client-build-docs.js +61 -46
- package/src/client-builder/client-build-live.js +2 -2
- package/src/client-builder/client-build.js +58 -44
- package/src/client-builder/client-dev-server.js +3 -3
- package/src/client-builder/client-icons.js +2 -2
- package/src/client-builder/ssr.js +3 -3
- package/src/client.build.js +3 -6
- package/src/client.dev.js +3 -6
- package/src/db/DataBaseProvider.js +186 -3
- package/src/db/mariadb/MariaDB.js +3 -2
- package/src/db/mongo/MongoBootstrap.js +273 -101
- package/src/db/mongo/MongooseDB.js +11 -8
- package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
- package/src/grpc/cyberia/grpc-server.js +1 -1
- package/src/index.js +103 -23
- package/src/mailer/EmailRender.js +2 -2
- package/src/mailer/MailerInterceptor.js +87 -0
- package/src/mailer/MailerProvider.js +50 -6
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
- package/src/projects/cyberia/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +54 -6
- package/src/projects/cyberia/gemini-client.js +1 -1
- package/src/projects/cyberia/generate-saga.js +15 -24
- package/src/projects/cyberia/hot-reload-trigger.js +1 -1
- package/src/projects/cyberia/instance-data.js +22 -3
- package/src/projects/cyberia/ipfs-client.js +4 -4
- package/src/projects/cyberia/map-preview-generator.js +1 -1
- package/src/projects/cyberia/object-layer.js +12 -22
- package/src/projects/cyberia/semantic-layer-generator.js +1 -1
- package/src/projects/underpost/catalog-underpost.js +13 -2
- package/src/proxy.js +4 -7
- package/src/runtime/cyberia-client/Dockerfile +9 -4
- package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
- package/src/runtime/cyberia-server/Dockerfile +9 -4
- package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
- package/src/runtime/engine-cyberia/Dockerfile +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
- package/src/runtime/engine-cyberia/compose.env +16 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
- package/src/runtime/express/Express.js +32 -27
- package/src/runtime/lampp/Lampp.js +22 -70
- package/src/runtime/nginx/Nginx.js +1 -1
- package/src/runtime/wp/Wp.js +16 -48
- package/src/server/{catalog.js → build/catalog.js} +15 -5
- package/src/server/build/coverage.js +117 -0
- package/src/server/build/execution.js +402 -0
- package/src/server/build/package.js +465 -0
- package/src/server/build/testing.js +528 -0
- package/src/server/{dns.js → network/dns.js} +241 -14
- package/src/server/network/forward-proxy.js +541 -0
- package/src/server/{middlewares.js → network/middlewares.js} +59 -4
- package/src/server/network/node-capability.js +98 -0
- package/src/server/{peer.js → network/peer.js} +3 -3
- package/src/server/{proxy.js → network/proxy.js} +7 -13
- package/src/server/network/router.js +356 -0
- package/src/server/{tls.js → network/tls.js} +2 -2
- package/src/server/network/underpost-compression.js +186 -0
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/ops/cron.js +949 -0
- package/src/server/ops/event-notification.js +284 -0
- package/src/server/{logger.js → ops/logger.js} +108 -23
- package/src/server/ops/monitoring.js +1724 -0
- package/src/server/ops/systemd.js +259 -0
- package/src/server/{conf.js → runtime/conf.js} +521 -520
- package/src/server/runtime/config-scope.js +215 -0
- package/src/server/runtime/environment.js +149 -0
- package/src/server/{process.js → runtime/process.js} +153 -13
- package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
- package/src/server/{runtime.js → runtime/runtime.js} +12 -8
- package/src/server/{start.js → runtime/start.js} +128 -39
- package/src/server/{auth.js → security/auth.js} +7 -8
- package/src/server/security/container-storage.js +382 -0
- package/src/server/{crypto.js → security/crypto.js} +1 -1
- package/src/server/security/selinux.js +185 -0
- package/src/server/{backup.js → storage/backup.js} +17 -8
- package/src/server/{data-query.js → storage/data-query.js} +1 -1
- package/src/server/{downloader.js → storage/downloader.js} +2 -2
- package/src/server/storage/repository.js +68 -0
- package/src/server.js +4 -7
- package/src/ws/IoInterface.js +1 -1
- package/src/ws/IoServer.js +1 -1
- package/src/ws/core/core.ws.connection.js +1 -1
- package/src/ws/core/core.ws.emit.js +1 -1
- package/src/ws/core/core.ws.server.js +1 -1
- package/src/ws/default/default.ws.connection.js +1 -1
- package/src/ws/default/default.ws.emit.js +1 -1
- package/src/ws/default/default.ws.server.js +1 -1
- package/test/e2e/event-e2e-public-ingress-down.js +45 -0
- package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
- package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
- package/test/{api.test.js → integration/app/api.test.js} +33 -14
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
- package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
- package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
- package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
- package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
- package/test/integration/infra/1-security/config-scope.test.js +305 -0
- package/test/integration/infra/1-security/container-storage.test.js +356 -0
- package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
- package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
- package/test/integration/infra/1-security/selinux.test.js +69 -0
- package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
- package/test/integration/infra/1-security/systemd-service.test.js +70 -0
- package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
- package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
- package/test/integration/infra/2-network/node-capability.test.js +182 -0
- package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
- package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
- package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
- package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
- package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
- package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
- package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
- package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
- package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
- package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
- package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
- package/test/integration/infra/5-observability/event-notification.test.js +197 -0
- package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
- package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
- package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
- package/test/support/shell-harness.js +73 -0
- package/test/unit/build-template.test.js +97 -0
- package/test/unit/build-workflow-offline.test.js +132 -0
- package/test/unit/catalog.test.js +71 -0
- package/test/unit/client-build-docs.test.js +334 -0
- package/test/unit/conf-loading.test.js +303 -0
- package/test/unit/conf-resolution.test.js +979 -0
- package/test/unit/coverage-artifact.test.js +130 -0
- package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
- package/test/unit/deploy-env-resolution.test.js +38 -0
- package/test/unit/deploy-log-table.test.js +447 -0
- package/test/unit/execution-profiles.test.js +219 -0
- package/test/unit/fleet-sync-source.test.js +149 -0
- package/test/unit/logger-redaction.test.js +112 -0
- package/test/unit/package.test.js +403 -0
- package/test/unit/prepare-host.test.js +299 -0
- package/test/unit/process-environment.test.js +18 -0
- package/test/unit/propagation-message.test.js +78 -0
- package/test/unit/redeploy-plan.test.js +24 -0
- package/test/unit/release-bump.test.js +474 -0
- package/test/unit/ssh-output-redaction.test.js +28 -0
- package/test/unit/start-options.test.js +46 -0
- package/test/unit/test-tiers.test.js +193 -0
- package/vitest.config.js +58 -0
- package/.nycrc +0 -9
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/link-local-underpost-cli.sh +0 -6
- package/src/api/user/user.build.js +0 -16
- package/src/cli/env.js +0 -177
- package/src/client/components/core/Blockchain.js +0 -41
- package/src/client/components/core/Blog.js +0 -9
- package/src/client/components/core/KeyboardAvoidance.js +0 -145
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/white0-min.jpg +0 -0
- package/src/client/public/default/assets/background/white0.jpg +0 -0
- package/src/client/public/doc/favicon.ico +0 -0
- package/src/client/public/doc/sitemap +0 -148
- package/src/server/cron.js +0 -476
|
@@ -8,22 +8,23 @@
|
|
|
8
8
|
|
|
9
9
|
import fs from 'fs-extra';
|
|
10
10
|
import { transformClientJs, JSONweb } from './client-formatted.js';
|
|
11
|
-
import { loggerFactory } from '../server/logger.js';
|
|
11
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
12
12
|
import {
|
|
13
13
|
getCapVariableName,
|
|
14
14
|
newInstance,
|
|
15
15
|
orderArrayFromAttrInt,
|
|
16
16
|
uniqueArray,
|
|
17
17
|
} from '../client/components/core/CommonJs.js';
|
|
18
|
-
import { readConfJson } from '../server/conf.js';
|
|
18
|
+
import { readConfJson } from '../server/runtime/conf.js';
|
|
19
19
|
import { minify } from 'html-minifier-terser';
|
|
20
20
|
import AdmZip from 'adm-zip';
|
|
21
21
|
import * as dir from 'path';
|
|
22
|
-
import { shellExec } from '../server/process.js';
|
|
22
|
+
import { shellExec } from '../server/runtime/process.js';
|
|
23
23
|
import { SitemapStream, streamToPromise } from 'sitemap';
|
|
24
24
|
import { Readable } from 'stream';
|
|
25
25
|
import { buildIcons } from './client-icons.js';
|
|
26
|
-
import { statusPageBuildSegment } from '../server/underpost-gateway.js';
|
|
26
|
+
import { statusPageBuildSegment } from '../server/network/underpost-gateway.js';
|
|
27
|
+
import { repositoryIdentityFactory } from '../server/storage/repository.js';
|
|
27
28
|
import Underpost from '../index.js';
|
|
28
29
|
import { buildDocs } from './client-build-docs.js';
|
|
29
30
|
import { ssrFactory } from './ssr.js';
|
|
@@ -525,6 +526,7 @@ const defaultSitemapXsl = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
525
526
|
* @param {string|number} options.split - Optional zip split size in MB.
|
|
526
527
|
* @param {boolean} options.fullBuild - Whether to perform a full build.
|
|
527
528
|
* @param {boolean} options.iconsBuild - Whether to build icons.
|
|
529
|
+
* @param {boolean} options.ssrOnly - Whether to rebuild only views defined in `conf.ssr.json`.
|
|
528
530
|
* @returns {Promise<void>} - Promise that resolves when the build is complete.
|
|
529
531
|
* @throws {Error} - If the build fails.
|
|
530
532
|
* @memberof clientBuild
|
|
@@ -532,6 +534,7 @@ const defaultSitemapXsl = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
532
534
|
const buildClient = async (
|
|
533
535
|
options = {
|
|
534
536
|
deployId: '',
|
|
537
|
+
subConf: '',
|
|
535
538
|
liveClientBuildPaths: [],
|
|
536
539
|
instances: [],
|
|
537
540
|
buildZip: false,
|
|
@@ -542,12 +545,17 @@ const buildClient = async (
|
|
|
542
545
|
) => {
|
|
543
546
|
const logger = loggerFactory(import.meta);
|
|
544
547
|
const deployId = options.deployId || process.env.DEPLOY_ID;
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
+
// Carried as an argument rather than re-derived from DEPLOY_SUB_CONF: the caller already
|
|
549
|
+
// resolved which sub-configuration this build is for, and a build that reads a different
|
|
550
|
+
// conf.server than the one its caller loaded renders the wrong set of hosts.
|
|
551
|
+
const subConf = `${options.subConf ?? ''}`.trim();
|
|
552
|
+
const confClient = readConfJson(deployId, 'client', { subConf });
|
|
553
|
+
const confServer = readConfJson(deployId, 'server', { subConf, loadReplicas: true });
|
|
554
|
+
const confSSR = readConfJson(deployId, 'ssr', { subConf });
|
|
548
555
|
const packageData = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
|
|
549
556
|
const acmeChallengePath = `/.well-known/acme-challenge`;
|
|
550
557
|
const publicPath = `./public`;
|
|
558
|
+
const ssrOnly = options.ssrOnly === true;
|
|
551
559
|
|
|
552
560
|
/**
|
|
553
561
|
* @async
|
|
@@ -687,15 +695,27 @@ const buildClient = async (
|
|
|
687
695
|
// ''; // process.env.NODE_ENV === 'production' ? `https://${host}` : ``;
|
|
688
696
|
currentPort++;
|
|
689
697
|
|
|
698
|
+
// Every document this instance emits carries the same payload; the SSR
|
|
699
|
+
// views and the client index must never disagree about which repository
|
|
700
|
+
// published them.
|
|
701
|
+
const renderPayload = {
|
|
702
|
+
apiBaseProxyPath,
|
|
703
|
+
apiBaseHost,
|
|
704
|
+
apiBasePath: process.env.BASE_API,
|
|
705
|
+
version: Underpost.version,
|
|
706
|
+
repository: repositoryIdentityFactory(),
|
|
707
|
+
...(isDevelopment ? { dev: true } : undefined),
|
|
708
|
+
};
|
|
709
|
+
|
|
690
710
|
const acmeChallengeFullPath = directory
|
|
691
711
|
? `${directory}${acmeChallengePath}`
|
|
692
712
|
: `${publicPath}/${host}${acmeChallengePath}`;
|
|
693
713
|
|
|
694
|
-
if (!enableLiveRebuild) buildAcmeChallengePath(acmeChallengeFullPath);
|
|
714
|
+
if (!enableLiveRebuild && !ssrOnly) buildAcmeChallengePath(acmeChallengeFullPath);
|
|
695
715
|
|
|
696
716
|
if (redirect || disabledRebuild) continue;
|
|
697
717
|
|
|
698
|
-
if (fullBuildEnabled)
|
|
718
|
+
if (fullBuildEnabled && !ssrOnly)
|
|
699
719
|
await fullBuild({
|
|
700
720
|
path,
|
|
701
721
|
logger,
|
|
@@ -710,7 +730,7 @@ const buildClient = async (
|
|
|
710
730
|
publicCopyNonExistingFiles,
|
|
711
731
|
});
|
|
712
732
|
|
|
713
|
-
if (components)
|
|
733
|
+
if (!ssrOnly && components)
|
|
714
734
|
for (const module of Object.keys(components)) {
|
|
715
735
|
if (!fs.existsSync(`${rootClientPath}/components/${module}`))
|
|
716
736
|
fs.mkdirSync(`${rootClientPath}/components/${module}`, { recursive: true });
|
|
@@ -733,7 +753,7 @@ const buildClient = async (
|
|
|
733
753
|
}
|
|
734
754
|
}
|
|
735
755
|
|
|
736
|
-
if (services) {
|
|
756
|
+
if (!ssrOnly && services) {
|
|
737
757
|
for (const module of services) {
|
|
738
758
|
if (!fs.existsSync(`${rootClientPath}/services/${module}`))
|
|
739
759
|
fs.mkdirSync(`${rootClientPath}/services/${module}`, { recursive: true });
|
|
@@ -796,7 +816,9 @@ const buildClient = async (
|
|
|
796
816
|
const swSrcPath = `./src/client/sw/core.sw.js`;
|
|
797
817
|
const swPublicPath = `${rootClientPath}/sw.js`;
|
|
798
818
|
const swShouldRebuild =
|
|
799
|
-
|
|
819
|
+
!ssrOnly &&
|
|
820
|
+
views &&
|
|
821
|
+
!(enableLiveRebuild && !options.liveClientBuildPaths.find((p) => p.srcBuildPath === swSrcPath));
|
|
800
822
|
// Transformed SW JS is held in memory; it gets prepended with renderPayload
|
|
801
823
|
// and written once below, after PRE_CACHED_RESOURCES are known.
|
|
802
824
|
let swTransformedJs = '';
|
|
@@ -810,13 +832,15 @@ const buildClient = async (
|
|
|
810
832
|
});
|
|
811
833
|
}
|
|
812
834
|
|
|
813
|
-
if (views) {
|
|
814
|
-
if (
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
835
|
+
if (!ssrOnly && views) {
|
|
836
|
+
if (
|
|
837
|
+
!(
|
|
838
|
+
enableLiveRebuild &&
|
|
839
|
+
!options.liveClientBuildPaths.find(
|
|
840
|
+
(p) => p.srcBuildPath.startsWith(`./src/client/ssr`) || p.srcBuildPath.slice(-9) === '.index.js',
|
|
841
|
+
)
|
|
818
842
|
)
|
|
819
|
-
)
|
|
843
|
+
)
|
|
820
844
|
for (const view of views) {
|
|
821
845
|
const buildPath = `${
|
|
822
846
|
rootClientPath[rootClientPath.length - 1] === '/' ? rootClientPath.slice(0, -1) : rootClientPath
|
|
@@ -848,7 +872,7 @@ const buildClient = async (
|
|
|
848
872
|
confSSR[view.ssr].head.unshift('Production');
|
|
849
873
|
|
|
850
874
|
for (const ssrHeadComponent of confSSR[view.ssr].head) {
|
|
851
|
-
const
|
|
875
|
+
const SSRComponent = await ssrFactory(`./src/client/ssr/head/${ssrHeadComponent}.js`);
|
|
852
876
|
|
|
853
877
|
switch (ssrHeadComponent) {
|
|
854
878
|
case 'Pwa':
|
|
@@ -903,11 +927,11 @@ const buildClient = async (
|
|
|
903
927
|
// ],
|
|
904
928
|
// "prefer_related_applications": true
|
|
905
929
|
}
|
|
906
|
-
if (validPwaBuild) ssrHeadComponents +=
|
|
930
|
+
if (validPwaBuild) ssrHeadComponents += SSRComponent({ title, ssrPath, canonicalURL, ...metadata });
|
|
907
931
|
break;
|
|
908
932
|
case 'Seo':
|
|
909
933
|
if (metadata) {
|
|
910
|
-
ssrHeadComponents +=
|
|
934
|
+
ssrHeadComponents += SSRComponent({ title, ssrPath, canonicalURL, ...metadata });
|
|
911
935
|
}
|
|
912
936
|
break;
|
|
913
937
|
case 'Microdata':
|
|
@@ -919,18 +943,18 @@ const buildClient = async (
|
|
|
919
943
|
const microdata = JSON.parse(
|
|
920
944
|
fs.readFileSync(`./src/client/public/${publicClientId}/microdata.json`, 'utf8'),
|
|
921
945
|
);
|
|
922
|
-
ssrHeadComponents +=
|
|
946
|
+
ssrHeadComponents += SSRComponent({ microdata });
|
|
923
947
|
}
|
|
924
948
|
break;
|
|
925
949
|
default:
|
|
926
|
-
ssrHeadComponents +=
|
|
950
|
+
ssrHeadComponents += SSRComponent({ ssrPath, host, path });
|
|
927
951
|
break;
|
|
928
952
|
}
|
|
929
953
|
}
|
|
930
954
|
|
|
931
955
|
for (const ssrBodyComponent of confSSR[view.ssr].body) {
|
|
932
|
-
const
|
|
933
|
-
ssrBodyComponents +=
|
|
956
|
+
const SSRComponent = await ssrFactory(`./src/client/ssr/body/${ssrBodyComponent}.js`);
|
|
957
|
+
ssrBodyComponents += SSRComponent({
|
|
934
958
|
...metadata,
|
|
935
959
|
ssrPath,
|
|
936
960
|
host,
|
|
@@ -956,13 +980,7 @@ const buildClient = async (
|
|
|
956
980
|
ssrPath,
|
|
957
981
|
ssrHeadComponents,
|
|
958
982
|
ssrBodyComponents,
|
|
959
|
-
renderPayload
|
|
960
|
-
apiBaseProxyPath,
|
|
961
|
-
apiBaseHost,
|
|
962
|
-
apiBasePath: process.env.BASE_API,
|
|
963
|
-
version: Underpost.version,
|
|
964
|
-
...(isDevelopment ? { dev: true } : undefined),
|
|
965
|
-
},
|
|
983
|
+
renderPayload,
|
|
966
984
|
renderApi: {
|
|
967
985
|
JSONweb,
|
|
968
986
|
},
|
|
@@ -983,7 +1001,7 @@ const buildClient = async (
|
|
|
983
1001
|
);
|
|
984
1002
|
}
|
|
985
1003
|
}
|
|
986
|
-
if (!enableLiveRebuild && siteMapLinks.length > 0) {
|
|
1004
|
+
if (!ssrOnly && !enableLiveRebuild && siteMapLinks.length > 0) {
|
|
987
1005
|
const hasSitemapTemplate = fs.existsSync(`${rootClientPath}/sitemap`);
|
|
988
1006
|
const sitemapBaseUrl = `https://${host}${path === '/' ? '' : path}`;
|
|
989
1007
|
// Create a stream to write to — omit xslUrl so we can inject a relative href below
|
|
@@ -1020,11 +1038,13 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
1020
1038
|
);
|
|
1021
1039
|
}
|
|
1022
1040
|
|
|
1023
|
-
if (fullBuildEnabled && docs) {
|
|
1041
|
+
if (!ssrOnly && fullBuildEnabled && docs) {
|
|
1024
1042
|
await buildDocs({
|
|
1025
1043
|
host,
|
|
1026
1044
|
path,
|
|
1027
1045
|
port,
|
|
1046
|
+
apiBaseHost,
|
|
1047
|
+
apiBaseProxyPath,
|
|
1028
1048
|
metadata,
|
|
1029
1049
|
apis,
|
|
1030
1050
|
publicClientId,
|
|
@@ -1058,13 +1078,7 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
1058
1078
|
ssrPath,
|
|
1059
1079
|
ssrHeadComponents: '<base target="_top">',
|
|
1060
1080
|
ssrBodyComponents: SsrComponent(),
|
|
1061
|
-
renderPayload
|
|
1062
|
-
apiBaseProxyPath,
|
|
1063
|
-
apiBaseHost,
|
|
1064
|
-
apiBasePath: process.env.BASE_API,
|
|
1065
|
-
version: Underpost.version,
|
|
1066
|
-
...(isDevelopment ? { dev: true } : undefined),
|
|
1067
|
-
},
|
|
1081
|
+
renderPayload,
|
|
1068
1082
|
renderApi: { JSONweb },
|
|
1069
1083
|
});
|
|
1070
1084
|
|
|
@@ -1110,7 +1124,7 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
1110
1124
|
|
|
1111
1125
|
if (swShouldRebuild) {
|
|
1112
1126
|
const cacheScope = path === '/' ? 'root' : path.replaceAll('/', '_');
|
|
1113
|
-
const
|
|
1127
|
+
const swRenderPayload = {
|
|
1114
1128
|
PRE_CACHED_RESOURCES: uniqueArray(PRE_CACHED_RESOURCES),
|
|
1115
1129
|
PROXY_PATH: path,
|
|
1116
1130
|
CACHE_PREFIX: `engine-core-${cacheScope}`,
|
|
@@ -1121,14 +1135,14 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
1121
1135
|
// Single write: prepend the payload prelude to the transformed SW JS.
|
|
1122
1136
|
fs.writeFileSync(
|
|
1123
1137
|
swPublicPath,
|
|
1124
|
-
`self.renderPayload = ${JSONweb(
|
|
1138
|
+
`self.renderPayload = ${JSONweb(swRenderPayload)};
|
|
1125
1139
|
self.__WB_DISABLE_DEV_LOGS = true;
|
|
1126
1140
|
${swTransformedJs}`,
|
|
1127
1141
|
'utf8',
|
|
1128
1142
|
);
|
|
1129
1143
|
}
|
|
1130
1144
|
}
|
|
1131
|
-
if (!enableLiveRebuild && options.buildZip) {
|
|
1145
|
+
if (!ssrOnly && !enableLiveRebuild && options.buildZip) {
|
|
1132
1146
|
logger.warn('build zip', rootClientPath);
|
|
1133
1147
|
|
|
1134
1148
|
if (!fs.existsSync('./build')) fs.mkdirSync('./build');
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import nodemon from 'nodemon';
|
|
8
8
|
import dotenv from 'dotenv';
|
|
9
|
-
import { shellExec } from '../server/process.js';
|
|
10
|
-
import { loggerFactory } from '../server/logger.js';
|
|
9
|
+
import { shellExec } from '../server/runtime/process.js';
|
|
10
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
11
11
|
import Underpost from '../index.js';
|
|
12
12
|
|
|
13
13
|
const logger = loggerFactory(import.meta);
|
|
@@ -32,7 +32,7 @@ const createClientDevServer = async (
|
|
|
32
32
|
const devClientEnvPath = `./engine-private/conf/${deployId}/.env.${process.env.NODE_ENV}.${subConf}-dev-client`;
|
|
33
33
|
if (fs.existsSync(devClientEnvPath)) dotenv.config({ path: devClientEnvPath, override: true });
|
|
34
34
|
|
|
35
|
-
await Underpost.
|
|
35
|
+
await Underpost.client.callback(deployId, `${subConf}-dev-client`.trim(), host, path);
|
|
36
36
|
|
|
37
37
|
shellExec(`node src/server ${deployId} ${subConf}-dev-client`.trim(), {
|
|
38
38
|
async: true,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @namespace clientIcons
|
|
5
5
|
*/
|
|
6
6
|
import { favicons } from 'favicons';
|
|
7
|
-
import { loggerFactory } from '../server/logger.js';
|
|
7
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
8
8
|
import fs from 'fs-extra';
|
|
9
9
|
import { getCapVariableName } from '../client/components/core/CommonJs.js';
|
|
10
10
|
|
|
@@ -99,7 +99,7 @@ const buildIcons = async ({
|
|
|
99
99
|
|
|
100
100
|
const ssrPath = `./src/client/ssr/head/Pwa${getCapVariableName(publicClientId)}.js`;
|
|
101
101
|
if (!fs.existsSync(ssrPath))
|
|
102
|
-
fs.writeFileSync(ssrPath, '
|
|
102
|
+
fs.writeFileSync(ssrPath, 'SSRComponent = () => html`' + response.html.join(`\n`) + '`;', 'utf8');
|
|
103
103
|
} catch (error) {
|
|
104
104
|
logger.error(error.message); // Error description e.g. "An unknown error has occurred"
|
|
105
105
|
}
|
|
@@ -10,7 +10,7 @@ import vm from 'node:vm';
|
|
|
10
10
|
import Underpost from '../index.js';
|
|
11
11
|
|
|
12
12
|
import { srcFormatted } from './client-formatted.js';
|
|
13
|
-
import { loggerFactory } from '../server/logger.js';
|
|
13
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
14
14
|
|
|
15
15
|
const logger = loggerFactory(import.meta);
|
|
16
16
|
|
|
@@ -22,10 +22,10 @@ const logger = loggerFactory(import.meta);
|
|
|
22
22
|
* @memberof ServerSideRendering
|
|
23
23
|
*/
|
|
24
24
|
const ssrFactory = async (componentPath = `./src/client/ssr/RootDocument.js`) => {
|
|
25
|
-
const context = {
|
|
25
|
+
const context = { SSRComponent: () => {}, npm_package_version: Underpost.version };
|
|
26
26
|
vm.createContext(context);
|
|
27
27
|
vm.runInContext(await srcFormatted(fs.readFileSync(componentPath, 'utf8')), context);
|
|
28
|
-
return context.
|
|
28
|
+
return context.SSRComponent;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
/**
|
package/src/client.build.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { loggerFactory } from './server/logger.js';
|
|
7
|
-
import { Config } from './server/conf.js';
|
|
8
|
-
import { ProcessController } from './server/process.js';
|
|
3
|
+
import { loggerFactory } from './server/ops/logger.js';
|
|
4
|
+
import { Config } from './server/runtime/conf.js';
|
|
5
|
+
import { ProcessController } from './server/runtime/process.js';
|
|
9
6
|
import { clientLiveBuild } from './client-builder/client-build-live.js';
|
|
10
7
|
|
|
11
8
|
await Config.build();
|
package/src/client.dev.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { loggerFactory } from './server/logger.js';
|
|
7
|
-
import { ProcessController } from './server/process.js';
|
|
8
|
-
import { Config, buildClientStaticConf } from './server/conf.js';
|
|
3
|
+
import { loggerFactory } from './server/ops/logger.js';
|
|
4
|
+
import { ProcessController } from './server/runtime/process.js';
|
|
5
|
+
import { Config, buildClientStaticConf } from './server/runtime/conf.js';
|
|
9
6
|
import { createClientDevServer } from './client-builder/client-dev-server.js';
|
|
10
7
|
|
|
11
8
|
const logger = loggerFactory(import.meta);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { MongooseDB } from './mongo/MongooseDB.js';
|
|
2
|
-
import { loggerFactory } from '../server/logger.js';
|
|
2
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
3
3
|
import { getCapVariableName } from '../client/components/core/CommonJs.js';
|
|
4
|
-
import { resolveHostKeyContext } from '../server/conf.js';
|
|
4
|
+
import { resolveHostKeyContext } from '../server/runtime/conf.js';
|
|
5
5
|
import Underpost from '../index.js';
|
|
6
|
+
import { latchRuntimeError } from '../server/runtime/runtime-status.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Module for managing and loading various database connections (e.g., Mongoose, MariaDB).
|
|
@@ -12,6 +13,60 @@ import Underpost from '../index.js';
|
|
|
12
13
|
|
|
13
14
|
const logger = loggerFactory(import.meta);
|
|
14
15
|
|
|
16
|
+
// Health watch defaults. `DB_HEALTH_INTERVAL_MS=0` disables the watch entirely.
|
|
17
|
+
const HEALTH_INTERVAL_MS = Number(process.env.DB_HEALTH_INTERVAL_MS ?? 15000);
|
|
18
|
+
const HEALTH_PING_TIMEOUT_MS = 5000;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Bounds a liveness probe that would otherwise wait on the driver's own connection timeout.
|
|
22
|
+
* @param {Promise<boolean>} probe - Provider probe resolving to liveness.
|
|
23
|
+
* @returns {Promise<boolean>} `false` when the probe throws or outlives the bound.
|
|
24
|
+
*/
|
|
25
|
+
const withPingTimeout = async (probe) => {
|
|
26
|
+
let timer;
|
|
27
|
+
try {
|
|
28
|
+
return await Promise.race([
|
|
29
|
+
probe,
|
|
30
|
+
new Promise((resolve) => {
|
|
31
|
+
timer = setTimeout(() => resolve(false), HEALTH_PING_TIMEOUT_MS);
|
|
32
|
+
}),
|
|
33
|
+
]);
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
} finally {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Per-provider health strategies, keyed by `db.provider`.
|
|
43
|
+
*
|
|
44
|
+
* A provider with no entry here gets no health watch and no reconnect: liveness probes,
|
|
45
|
+
* rebuild semantics, and teardown differ per client, so there is nothing generic to fall
|
|
46
|
+
* back on. Adding one (MariaDB, PostgreSQL, …) means adding its case here — the rest of the
|
|
47
|
+
* service dispatches through this table and needs no change.
|
|
48
|
+
*
|
|
49
|
+
* @type {object.<string, {isAlive: Function, rebuild: Function, close: Function}>}
|
|
50
|
+
*/
|
|
51
|
+
const PROVIDER_HEALTH = {
|
|
52
|
+
mongoose: {
|
|
53
|
+
isAlive: async (connection) => {
|
|
54
|
+
if (!connection || connection.readyState !== 1) return false;
|
|
55
|
+
return await withPingTimeout(
|
|
56
|
+
connection.db
|
|
57
|
+
.admin()
|
|
58
|
+
.command({ ping: 1 })
|
|
59
|
+
.then(() => true),
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
rebuild: async ({ apis, db }) => {
|
|
63
|
+
const connection = await MongooseDB.connect(db);
|
|
64
|
+
return { connection, models: await MongooseDB.loadModels({ conn: connection, apis }) };
|
|
65
|
+
},
|
|
66
|
+
close: async (connection) => await connection?.close(),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
15
70
|
/**
|
|
16
71
|
* @class
|
|
17
72
|
* @alias DataBaseProviderService
|
|
@@ -126,6 +181,128 @@ class DataBaseProviderService {
|
|
|
126
181
|
});
|
|
127
182
|
}
|
|
128
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Timers for the per-provider health watch, keyed by `<contextKey>:<provider>`.
|
|
186
|
+
* @type {object.<string, {timer: object, attempts: number, rebuilding: boolean}>}
|
|
187
|
+
*/
|
|
188
|
+
static #watchers = {};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Rebuilds a loaded provider in place: new connection, freshly bound models, old
|
|
192
|
+
* connection closed once the replacement is live.
|
|
193
|
+
*
|
|
194
|
+
* A reconnect is not the same as letting the driver heal itself. For mongoose: after a
|
|
195
|
+
* replica set is reconfigured the driver can hold a topology it will never accept a primary
|
|
196
|
+
* for again — it records the highest `setVersion`/`electionId` it has seen and rejects
|
|
197
|
+
* anything lower for the rest of the process — so only a new client recovers. Every consumer
|
|
198
|
+
* resolves models through this bucket on each call, so swapping the fields in place is
|
|
199
|
+
* enough; nothing has to be re-registered.
|
|
200
|
+
*
|
|
201
|
+
* Only providers present in {@link PROVIDER_HEALTH} can be rebuilt.
|
|
202
|
+
*
|
|
203
|
+
* @param {{host?: string, path?: string}|string} context - Context object or key.
|
|
204
|
+
* @param {string} [provider='mongoose'] - Provider name.
|
|
205
|
+
* @returns {Promise<boolean>} `true` when the provider was rebuilt.
|
|
206
|
+
*/
|
|
207
|
+
static async reconnect(context, provider = 'mongoose') {
|
|
208
|
+
const key = resolveHostKeyContext(context);
|
|
209
|
+
const strategy = PROVIDER_HEALTH[provider];
|
|
210
|
+
if (!strategy) {
|
|
211
|
+
logger.warn('No reconnect strategy for provider', { key, provider });
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const bucket = this.#instance[key]?.[provider];
|
|
216
|
+
if (!bucket?.rebuild) {
|
|
217
|
+
logger.warn('Cannot reconnect a provider that was never loaded', { key, provider });
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const previousConnection = bucket.connection;
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const { connection, models } = await strategy.rebuild(bucket.rebuild);
|
|
225
|
+
|
|
226
|
+
bucket.connection = connection;
|
|
227
|
+
bucket.models = models;
|
|
228
|
+
logger.info('Database connection rebuilt', { key, provider });
|
|
229
|
+
} catch (error) {
|
|
230
|
+
logger.error('Database reconnect failed, keeping the existing connection', {
|
|
231
|
+
key,
|
|
232
|
+
provider,
|
|
233
|
+
error: error.message,
|
|
234
|
+
});
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Closed last and best-effort: the replacement is already serving, and a close that
|
|
239
|
+
// hangs on a dead server must not take the recovery with it.
|
|
240
|
+
try {
|
|
241
|
+
await strategy.close(previousConnection);
|
|
242
|
+
} catch (error) {
|
|
243
|
+
logger.warn('Could not close the replaced connection', { key, provider, error: error.message });
|
|
244
|
+
}
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Starts the health watch for a provider: pings on an interval and rebuilds the connection
|
|
250
|
+
* on every tick that finds it down, until it answers again. A provider with no
|
|
251
|
+
* {@link PROVIDER_HEALTH} entry is left unwatched.
|
|
252
|
+
* @param {string} key - Resolved context key.
|
|
253
|
+
* @param {string} provider - Provider name.
|
|
254
|
+
*/
|
|
255
|
+
static #startHealthWatch(key, provider) {
|
|
256
|
+
const strategy = PROVIDER_HEALTH[provider];
|
|
257
|
+
if (!strategy || !(HEALTH_INTERVAL_MS > 0)) return;
|
|
258
|
+
const watchKey = `${key}:${provider}`;
|
|
259
|
+
if (this.#watchers[watchKey]) return;
|
|
260
|
+
|
|
261
|
+
const state = { attempts: 0, rebuilding: false, timer: null };
|
|
262
|
+
state.timer = setInterval(async () => {
|
|
263
|
+
// A rebuild can outlast the interval (the driver's own connect timeout is longer), so
|
|
264
|
+
// ticks that land mid-attempt are skipped rather than stacking attempts.
|
|
265
|
+
if (state.rebuilding) return;
|
|
266
|
+
const bucket = this.#instance[key]?.[provider];
|
|
267
|
+
if (!bucket) return;
|
|
268
|
+
|
|
269
|
+
if (await strategy.isAlive(bucket.connection)) {
|
|
270
|
+
if (state.attempts > 0)
|
|
271
|
+
logger.info('Database connection restored', { key, provider, attempts: state.attempts });
|
|
272
|
+
state.attempts = 0;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Every tick retries until the connection answers again: there is no attempt budget to
|
|
277
|
+
// exhaust, because giving up leaves the runtime permanently unable to reach its database.
|
|
278
|
+
state.rebuilding = true;
|
|
279
|
+
state.attempts++;
|
|
280
|
+
logger.warn('Database connection is down, rebuilding', { key, provider, attempt: state.attempts });
|
|
281
|
+
try {
|
|
282
|
+
await this.reconnect(key, provider);
|
|
283
|
+
} finally {
|
|
284
|
+
state.rebuilding = false;
|
|
285
|
+
}
|
|
286
|
+
}, HEALTH_INTERVAL_MS);
|
|
287
|
+
|
|
288
|
+
// Never hold the event loop open on account of a health check.
|
|
289
|
+
state.timer.unref?.();
|
|
290
|
+
this.#watchers[watchKey] = state;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Stops the health watch for a provider.
|
|
295
|
+
* @param {string} key - Resolved context key.
|
|
296
|
+
* @param {string} provider - Provider name.
|
|
297
|
+
*/
|
|
298
|
+
static #stopHealthWatch(key, provider) {
|
|
299
|
+
const watchKey = `${key}:${provider}`;
|
|
300
|
+
const state = this.#watchers[watchKey];
|
|
301
|
+
if (!state) return;
|
|
302
|
+
clearInterval(state.timer);
|
|
303
|
+
delete this.#watchers[watchKey];
|
|
304
|
+
}
|
|
305
|
+
|
|
129
306
|
/**
|
|
130
307
|
* Loads and initializes a database provider based on the configuration.
|
|
131
308
|
* If the connection is already loaded for the given host/path, it returns the existing instance.
|
|
@@ -166,9 +343,12 @@ class DataBaseProviderService {
|
|
|
166
343
|
const conn = await MongooseDB.connect(db);
|
|
167
344
|
this.#instance[key][db.provider] = {
|
|
168
345
|
dbSignature,
|
|
346
|
+
// Kept so the connection can be rebuilt later without the caller being present.
|
|
347
|
+
rebuild: { apis, host, path, db },
|
|
169
348
|
models: await MongooseDB.loadModels({ conn, apis }),
|
|
170
349
|
connection: conn,
|
|
171
350
|
close: async () => {
|
|
351
|
+
this.#stopHealthWatch(key, db.provider);
|
|
172
352
|
return await new Promise((resolve) => {
|
|
173
353
|
this.#instance[key][db.provider].connection.close().then(() => {
|
|
174
354
|
// logger.info('Mongoose connection is disconnected', db);
|
|
@@ -182,6 +362,9 @@ class DataBaseProviderService {
|
|
|
182
362
|
default:
|
|
183
363
|
break;
|
|
184
364
|
}
|
|
365
|
+
// Self-guarding: only providers with a PROVIDER_HEALTH entry are actually watched, so a
|
|
366
|
+
// provider added above does not have to remember to opt in here.
|
|
367
|
+
this.#startHealthWatch(key, db.provider);
|
|
185
368
|
return this.#instance[key][db.provider];
|
|
186
369
|
} catch (error) {
|
|
187
370
|
// Sanitize options to prevent credential exposure in logs
|
|
@@ -200,7 +383,7 @@ class DataBaseProviderService {
|
|
|
200
383
|
: {},
|
|
201
384
|
};
|
|
202
385
|
logger.error(error.message, { safeOptions });
|
|
203
|
-
|
|
386
|
+
latchRuntimeError();
|
|
204
387
|
return undefined;
|
|
205
388
|
}
|
|
206
389
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createPool } from 'mariadb';
|
|
2
2
|
import Underpost from '../../index.js';
|
|
3
|
-
import { loggerFactory } from '../../server/logger.js';
|
|
3
|
+
import { loggerFactory } from '../../server/ops/logger.js';
|
|
4
|
+
import { latchRuntimeError } from '../../server/runtime/runtime-status.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Module for interacting with MariaDB/MySQL databases using the mariadb connector.
|
|
@@ -51,7 +52,7 @@ class MariaDBService {
|
|
|
51
52
|
console.log(result);
|
|
52
53
|
} catch (error) {
|
|
53
54
|
logger.error('MariaDB query failed', { error: error.message });
|
|
54
|
-
|
|
55
|
+
latchRuntimeError();
|
|
55
56
|
} finally {
|
|
56
57
|
if (conn) conn.release(); // release to pool
|
|
57
58
|
await pool.end();
|