@underpostnet/cyberia 3.3.0 → 3.3.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +1 -0
- package/.env.example +17 -5
- package/.github/workflows/coverall.cyberia.ci.yml +39 -14
- package/.github/workflows/cyberia-client.cd.yml +5 -0
- package/.github/workflows/cyberia-server.cd.yml +5 -0
- 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 +3 -0
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +35 -20
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/publish.cyberia.ci.yml +44 -0
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +1 -0
- package/.prettierignore +1 -0
- package/AGENTS.md +96 -0
- package/CHANGELOG.md +653 -2513
- package/CLI-HELP.md +323 -157
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +5 -5
- package/README.md +48 -28
- package/bin/build.js +86 -41
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +1494 -1403
- package/bin/deploy.js +18 -104
- package/bin/index.js +1494 -1403
- package/compose.env +17 -5
- package/conf.js +98 -7
- package/deploy/cyberia-client/deploy.sh +46 -0
- package/deploy/cyberia-client/package.sh +17 -0
- package/deploy/cyberia-client/state.sh +15 -0
- package/deploy/cyberia-server/deploy.sh +46 -0
- package/deploy/cyberia-server/package.sh +17 -0
- package/deploy/cyberia-server/state.sh +15 -0
- package/deploy/dd-cyberia/deploy.sh +9 -29
- package/deploy/dd-cyberia/init.sh +38 -45
- package/deploy/dd-cyberia/package.sh +16 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +133 -147
- package/deploy/lib/config.sh +29 -0
- package/deploy/lib/github-actions-logging.sh +610 -0
- package/deploy/lib/host.sh +194 -0
- package/deploy/lib/state.sh +65 -0
- package/deploy/pwa-microservices-template/deploy.sh +17 -42
- package/deploy/release/deploy.sh +9 -41
- package/deployment.yaml +7 -2
- package/docker-compose.yml +23 -17
- 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 +101 -40
- package/hardhat/package.json +2 -2
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +32 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +32 -7
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/mongo-express/deployment.yaml +46 -27
- package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
- package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
- package/manifests/deployment/mongo-express/service.yaml +16 -0
- package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
- package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
- 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 +87 -12
- package/scripts/event-monitor.sh +56 -0
- package/scripts/k3s-node-setup.sh +27 -14
- package/scripts/kubeadm-node-setup.sh +31 -11
- package/scripts/maas-setup.sh +8 -8
- package/scripts/selinux-normalize.sh +907 -0
- package/scripts/shutdown-machine.sh +843 -0
- package/scripts/test-monitor.sh +5 -5
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +15 -10
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +7 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +90 -186
- 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 +3 -3
- package/src/api/cyberia-action/cyberia-action.service.js +5 -6
- package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
- package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
- package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
- package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +2 -4
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +13 -35
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +17 -34
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
- 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.model.js +2 -0
- package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.service.js +3 -3
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +468 -5
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +502 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +29 -40
- package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
- package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +35 -142
- package/src/api/cyberia-instance/cyberia-instance.controller.js +2 -5
- package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
- package/src/api/cyberia-instance/cyberia-instance.router.js +5 -18
- package/src/api/cyberia-instance/cyberia-instance.service.js +5 -45
- package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +76 -3
- 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 +8 -4
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
- package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +4 -4
- package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.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 +403 -214
- package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
- 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.ref.js +153 -0
- package/src/api/file/file.ref.json +11 -2
- 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 +47 -12
- package/src/api/object-layer/object-layer.router.js +12 -5
- package/src/api/object-layer/object-layer.service.js +116 -123
- 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 +402 -0
- package/src/cli/baremetal.js +30 -35
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +191 -82
- package/src/cli/db.js +120 -68
- package/src/cli/deploy.js +157 -75
- 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-selection.js +115 -0
- package/src/cli/fs.js +159 -343
- package/src/cli/host.js +672 -0
- package/src/cli/image.js +4 -6
- package/src/cli/index.js +343 -151
- 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 +16 -12
- package/src/cli/repository.js +586 -363
- package/src/cli/run.js +398 -843
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +478 -279
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +1 -1
- package/src/cli/test.js +203 -125
- package/src/cli/vultr.js +61 -21
- package/src/cli/wireguard.js +1112 -306
- package/src/client/components/core/CalendarCore.js +53 -96
- package/src/client/components/core/Docs.js +327 -303
- package/src/client/components/core/FileExplorer.js +0 -21
- package/src/client/components/core/Modal.js +56 -1
- 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/ActionEngineCyberia.js +12 -36
- package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
- package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
- package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
- package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
- package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +2 -35
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
- 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 +15 -15
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +313 -30
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
- package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
- package/src/client/public/cyberia-docs/CYBERIA.md +48 -28
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
- 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/STATS-PROGRESSION.md +217 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
- 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-audio/cyberia-audio.service.js +99 -0
- package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
- package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
- package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
- package/src/client/services/object-layer/object-layer.management.js +6 -10
- package/src/client/services/object-layer/object-layer.service.js +3 -1
- 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 +92 -77
- package/src/client-builder/client-build-live.js +2 -2
- package/src/client-builder/client-build.js +105 -74
- package/src/client-builder/client-bundle.js +347 -0
- 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/MongoExpress.js +187 -0
- package/src/db/mongo/MongooseDB.js +7 -8
- package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
- package/src/grpc/cyberia/grpc-server.js +6 -8
- package/src/index.js +79 -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 +144 -147
- package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
- package/src/projects/cyberia/besu-genesis-generator.js +8 -17
- package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
- package/src/projects/cyberia/catalog-cyberia.js +54 -10
- package/src/projects/cyberia/gemini-client.js +4 -4
- package/src/projects/cyberia/generate-saga.js +5 -12
- package/src/projects/cyberia/hot-reload-trigger.js +18 -29
- package/src/projects/cyberia/instance-backup.js +210 -0
- package/src/projects/cyberia/instance-data.js +178 -258
- package/src/projects/cyberia/ipfs-client.js +4 -4
- package/src/projects/cyberia/map-preview-generator.js +33 -69
- package/src/projects/cyberia/object-layer.js +153 -320
- package/src/projects/cyberia/seed-audio.js +139 -0
- package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
- package/src/projects/cyberia/semantic-layer-generator.js +3 -19
- package/src/projects/cyberia/stat-balance.js +81 -0
- package/src/projects/cyberia/stat-commands.js +23 -0
- package/src/projects/cyberia/stat-contract-generator.js +101 -0
- package/src/projects/underpost/catalog-underpost.js +9 -1
- package/src/proxy.js +4 -7
- package/src/runtime/cyberia-client/Dockerfile +17 -8
- package/src/runtime/cyberia-client/Dockerfile.dev +13 -4
- package/src/runtime/cyberia-server/Dockerfile +18 -6
- package/src/runtime/cyberia-server/Dockerfile.dev +16 -3
- package/src/runtime/engine-cyberia/Dockerfile +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.test +5 -5
- package/src/runtime/engine-cyberia/compose.env +17 -5
- package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
- 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 +188 -0
- package/src/server/build/execution.js +402 -0
- package/src/server/build/package.js +508 -0
- package/src/server/build/testing.js +578 -0
- package/src/server/{dns.js → network/dns.js} +144 -11
- package/src/server/{forward-proxy.js → network/forward-proxy.js} +10 -18
- package/src/server/{middlewares.js → network/middlewares.js} +11 -5
- 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/{underpost-compression.js → network/underpost-compression.js} +1 -1
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +7 -7
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +2 -2
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/{cron.js → ops/cron.js} +349 -74
- package/src/server/ops/event-notification.js +284 -0
- package/src/server/{logger.js → ops/logger.js} +143 -23
- package/src/server/ops/monitoring.js +1724 -0
- package/src/server/{systemd.js → ops/systemd.js} +55 -1
- package/src/server/{conf.js → runtime/conf.js} +516 -423
- 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 -12
- 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/{selinux.js → security/selinux.js} +1 -1
- package/src/server/{backup.js → storage/backup.js} +17 -8
- package/src/server/{data-query.js → storage/data-query.js} +17 -1
- package/src/server/storage/downloader.js +121 -0
- package/src/server/storage/repository.js +68 -0
- package/src/server/storage/zip.js +153 -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/atlas-sprite-sheet-store.test.js +402 -0
- package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +64 -0
- package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
- package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
- package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +17 -23
- package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
- package/test/integration/app/cyberia/cyberia-load.test.js +466 -0
- package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
- package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +338 -0
- package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
- package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
- package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
- package/test/integration/app/cyberia/seed-audio.test.js +275 -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/{selinux.test.js → integration/infra/1-security/selinux.test.js} +2 -4
- 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 +1187 -0
- package/test/{wireguard-edge.test.js → integration/infra/2-network/wireguard-edge.test.js} +649 -55
- 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/3-cluster/mongo-express-deploy.test.js +156 -0
- package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -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} +6 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +4 -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 +361 -0
- package/test/unit/client-bundle.test.js +313 -0
- package/test/unit/conf-loading.test.js +303 -0
- package/test/unit/conf-resolution.test.js +996 -0
- package/test/unit/coverage-artifact.test.js +221 -0
- package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
- package/test/unit/cyberia/instance-backup.test.js +183 -0
- package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
- package/test/unit/cyberia/publish-workflow.test.js +22 -0
- package/test/unit/cyberia/stat-balance.test.js +69 -0
- package/test/unit/deploy-env-resolution.test.js +38 -0
- package/test/unit/deploy-log-table.test.js +518 -0
- package/test/unit/downloader-integrity.test.js +98 -0
- package/test/unit/execution-profiles.test.js +219 -0
- package/test/unit/file-reference-registry.test.js +141 -0
- package/test/unit/fleet-sync-source.test.js +149 -0
- package/test/unit/fs-storage-paths.test.js +596 -0
- package/test/unit/logger-redaction.test.js +141 -0
- package/test/unit/package.test.js +457 -0
- package/test/unit/prepare-host.test.js +382 -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 +220 -0
- package/test/unit/zip-archive.test.js +142 -0
- package/vitest.config.js +66 -0
- package/.nycrc +0 -9
- package/deploy/lib/logging.sh +0 -96
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/coverall-test-cyberia.sh +0 -24
- package/scripts/coverall-test.sh +0 -24
- package/scripts/link-local-underpost-cli.sh +0 -6
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
- 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/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
- 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/downloader.js +0 -73
- package/src/server/environment.js +0 -98
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mongo Express Deployment Module
|
|
3
|
+
* @module src/db/mongo/MongoExpress
|
|
4
|
+
* @namespace MongoExpress
|
|
5
|
+
* @description Deploys the mongo-express web client used to inspect the cluster's MongoDB
|
|
6
|
+
* StatefulSet collections. The workload is a plain Deployment plus a ClusterIP Service, so the
|
|
7
|
+
* same manifests converge identically under Kind, Kubeadm and K3s; the only runtime-dependent
|
|
8
|
+
* decision is whether the deployed mongod enforces authentication, which selects the overlay.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { loggerFactory } from '../../server/ops/logger.js';
|
|
12
|
+
import { shellExec } from '../../server/runtime/process.js';
|
|
13
|
+
// Cyclic by construction (index -> cluster -> MongoExpress -> index), same as MongoBootstrap.js.
|
|
14
|
+
// Safe because the binding is only dereferenced inside method bodies, never at module scope.
|
|
15
|
+
import Underpost from '../../index.js';
|
|
16
|
+
import { MONGODB_DEFAULT_PORT, MONGODB_SERVICE_NAME, MONGODB_STATEFULSET_NAME } from './MongooseDB.js';
|
|
17
|
+
|
|
18
|
+
const logger = loggerFactory(import.meta);
|
|
19
|
+
|
|
20
|
+
const MONGO_EXPRESS_NAME = 'mongo-express';
|
|
21
|
+
const MONGO_EXPRESS_SERVICE_NAME = 'mongo-express-service';
|
|
22
|
+
const MONGO_EXPRESS_IMAGE = 'mongo-express:1.0.2';
|
|
23
|
+
const MONGO_EXPRESS_PORT = 8081;
|
|
24
|
+
const MONGO_EXPRESS_NODE_PORT = 32081;
|
|
25
|
+
const MONGO_EXPRESS_BASE_URL = '/mongo/';
|
|
26
|
+
// The UI reads the root credentials and gates its own session with the same pair, so it consumes
|
|
27
|
+
// the StatefulSet's secret rather than owning a second credential of its own.
|
|
28
|
+
const MONGO_EXPRESS_SECRET_NAME = 'mongodb-secret';
|
|
29
|
+
const MONGO_EXPRESS_MANIFEST_DIR = 'manifests/deployment/mongo-express';
|
|
30
|
+
const MONGO_EXPRESS_NO_AUTH_MANIFEST_DIR = 'manifests/deployment/mongo-express-no-auth';
|
|
31
|
+
|
|
32
|
+
// Literal and unescaped: kubectl's jsonpath quotes carry escape sequences of their own, and no
|
|
33
|
+
// mongod argument contains a pipe.
|
|
34
|
+
const MONGOD_ARGS_FIELD_SEPARATOR = '|';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Parses the mongod argument vector reported by `kubectl -o jsonpath` for the StatefulSet.
|
|
38
|
+
* @param {string} raw - Raw jsonpath stdout: the StatefulSet name, then one field per argument.
|
|
39
|
+
* @returns {Array<string>|null} Argument vector, or null when no StatefulSet was reported.
|
|
40
|
+
* @memberof MongoExpress
|
|
41
|
+
*/
|
|
42
|
+
const parseMongodArgs = (raw) => {
|
|
43
|
+
const value = `${raw || ''}`;
|
|
44
|
+
if (!value.trim()) return null;
|
|
45
|
+
const [, ...args] = value.split(MONGOD_ARGS_FIELD_SEPARATOR);
|
|
46
|
+
return args.map((arg) => arg.trim()).filter(Boolean);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Decides whether mongo-express must authenticate against the deployed mongod.
|
|
51
|
+
*
|
|
52
|
+
* The deployed StatefulSet is the authority: `manifests/mongodb` starts mongod with `--auth` and
|
|
53
|
+
* `manifests/mongodb-4.4` does not, and either can be the one running regardless of which flag
|
|
54
|
+
* this invocation carries. The flags only answer for a cluster with no StatefulSet deployed yet,
|
|
55
|
+
* where `--mongodb` (the auth-enabled manifest set) is the default the platform installs.
|
|
56
|
+
* @param {object} [params={}] - Resolution inputs.
|
|
57
|
+
* @param {Array<string>|null} [params.args=null] - mongod argument vector, or null when undeployed.
|
|
58
|
+
* @param {object} [params.options={}] - Cluster options (`mongodb`, `mongodb4`).
|
|
59
|
+
* @returns {boolean} True when the admin credential pair must be projected.
|
|
60
|
+
* @memberof MongoExpress
|
|
61
|
+
*/
|
|
62
|
+
const mongoAuthEnabledFactory = ({ args = null, options = {} } = {}) => {
|
|
63
|
+
if (Array.isArray(args)) return args.includes('--auth');
|
|
64
|
+
return options.mongodb4 !== true;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the kustomization root the auth mode selects.
|
|
69
|
+
* @param {object} [params={}] - Path inputs.
|
|
70
|
+
* @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
|
|
71
|
+
* @param {boolean} [params.authEnabled=true] - Whether mongod enforces authentication.
|
|
72
|
+
* @returns {string} Kustomization directory path.
|
|
73
|
+
* @memberof MongoExpress
|
|
74
|
+
*/
|
|
75
|
+
const mongoExpressManifestPathFactory = ({ underpostRoot = '.', authEnabled = true } = {}) =>
|
|
76
|
+
`${underpostRoot}/${authEnabled ? MONGO_EXPRESS_MANIFEST_DIR : MONGO_EXPRESS_NO_AUTH_MANIFEST_DIR}`;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Resolves the opt-in NodePort Service manifest path. It lives in the base directory and is left
|
|
80
|
+
* out of both kustomizations: exposing an admin UI on the node network is a caller's decision.
|
|
81
|
+
* @param {object} [params={}] - Path inputs.
|
|
82
|
+
* @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
|
|
83
|
+
* @returns {string} NodePort manifest path.
|
|
84
|
+
* @memberof MongoExpress
|
|
85
|
+
*/
|
|
86
|
+
const mongoExpressNodePortManifestFactory = ({ underpostRoot = '.' } = {}) =>
|
|
87
|
+
`${underpostRoot}/${MONGO_EXPRESS_MANIFEST_DIR}/mongo-express-nodeport.yaml`;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @class MongoExpress
|
|
91
|
+
* @description Static deployment surface for the mongo-express admin client.
|
|
92
|
+
* @memberof MongoExpress
|
|
93
|
+
*/
|
|
94
|
+
class MongoExpress {
|
|
95
|
+
/**
|
|
96
|
+
* Reads the mongod argument vector from the deployed MongoDB StatefulSet.
|
|
97
|
+
*
|
|
98
|
+
* The projection leads with the StatefulSet name so a deployed server that declares no arguments
|
|
99
|
+
* stays distinguishable from no server at all — one is mongod on its defaults, the other is a
|
|
100
|
+
* cluster with no data tier yet, and both would otherwise reduce to empty output.
|
|
101
|
+
* @param {string} [namespace='default'] - Namespace holding the StatefulSet.
|
|
102
|
+
* @returns {Array<string>|null} Argument vector, or null when no StatefulSet is deployed.
|
|
103
|
+
* @memberof MongoExpress
|
|
104
|
+
*/
|
|
105
|
+
static readMongodArgs(namespace = 'default') {
|
|
106
|
+
const raw = shellExec(
|
|
107
|
+
`kubectl get statefulset ${MONGODB_STATEFULSET_NAME} -n ${namespace} --ignore-not-found -o jsonpath=` +
|
|
108
|
+
`'{.metadata.name}{"${MONGOD_ARGS_FIELD_SEPARATOR}"}` +
|
|
109
|
+
`{range .spec.template.spec.containers[?(@.name=="${MONGODB_STATEFULSET_NAME}")].args[*]}` +
|
|
110
|
+
`{@}{"${MONGOD_ARGS_FIELD_SEPARATOR}"}{end}'`,
|
|
111
|
+
{ stdout: true, silent: true, silentOnError: true },
|
|
112
|
+
);
|
|
113
|
+
return parseMongodArgs(raw);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Deploys mongo-express and, once it is Ready, applies the exposure and placement the caller
|
|
118
|
+
* asked for. Cluster-type agnostic by construction: only the image pull differs between Kind
|
|
119
|
+
* (loaded into the node's image store) and Kubeadm/K3s (pulled through the CRI).
|
|
120
|
+
* @param {object} [params={}] - Deployment parameters.
|
|
121
|
+
* @param {string} [params.namespace='default'] - Target namespace.
|
|
122
|
+
* @param {string} [params.underpostRoot='.'] - Repository root holding `manifests/`.
|
|
123
|
+
* @param {object} [params.options={}] - Cluster options (`pullImage`, `nodePort`, `nodeName`, `mongodb4`).
|
|
124
|
+
* @returns {Promise<boolean>} Whether the deployment reported Ready.
|
|
125
|
+
* @memberof MongoExpress
|
|
126
|
+
*/
|
|
127
|
+
static async deploy({ namespace = 'default', underpostRoot = '.', options = {} } = {}) {
|
|
128
|
+
// Secret before workload: the Deployment's secretKeyRef must resolve at pod admission, and
|
|
129
|
+
// the encrypted store stays the source of truth wherever a manifest exists.
|
|
130
|
+
if (!Underpost.secret.applyIfPresent(MONGO_EXPRESS_SECRET_NAME, namespace))
|
|
131
|
+
Underpost.secret.applyFromOriginSeed(MONGO_EXPRESS_SECRET_NAME, namespace);
|
|
132
|
+
|
|
133
|
+
if (options.pullImage) Underpost.cluster.pullImage(MONGO_EXPRESS_IMAGE, options);
|
|
134
|
+
|
|
135
|
+
const args = MongoExpress.readMongodArgs(namespace);
|
|
136
|
+
const authEnabled = mongoAuthEnabledFactory({ args, options });
|
|
137
|
+
const manifestPath = mongoExpressManifestPathFactory({ underpostRoot, authEnabled });
|
|
138
|
+
logger.info('Deploying mongo-express', {
|
|
139
|
+
namespace,
|
|
140
|
+
authEnabled,
|
|
141
|
+
manifestPath,
|
|
142
|
+
mongodb: args ? 'deployed' : 'not deployed',
|
|
143
|
+
});
|
|
144
|
+
shellExec(`kubectl apply -k ${manifestPath} -n ${namespace}`);
|
|
145
|
+
|
|
146
|
+
const ready = await Underpost.test.statusMonitor(MONGO_EXPRESS_NAME, 'Running', 'pods', 1000, 60 * 10);
|
|
147
|
+
if (!ready) {
|
|
148
|
+
logger.error('mongo-express did not report Running', { namespace });
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (options.nodePort)
|
|
153
|
+
shellExec(`kubectl apply -f ${mongoExpressNodePortManifestFactory({ underpostRoot })} -n ${namespace}`);
|
|
154
|
+
if (options.nodeName)
|
|
155
|
+
Underpost.cluster.pinToNode({
|
|
156
|
+
kind: 'deployment',
|
|
157
|
+
name: MONGO_EXPRESS_NAME,
|
|
158
|
+
namespace,
|
|
159
|
+
node: options.nodeName,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
logger.info('mongo-express ready', {
|
|
163
|
+
server: `${MONGODB_STATEFULSET_NAME}-0.${MONGODB_SERVICE_NAME}:${MONGODB_DEFAULT_PORT}`,
|
|
164
|
+
basicAuth: `secret/${MONGO_EXPRESS_SECRET_NAME}`,
|
|
165
|
+
clusterIp: `${MONGO_EXPRESS_SERVICE_NAME}:${MONGO_EXPRESS_PORT}${MONGO_EXPRESS_BASE_URL}`,
|
|
166
|
+
nodePort: options.nodePort ? `<node>:${MONGO_EXPRESS_NODE_PORT}${MONGO_EXPRESS_BASE_URL}` : null,
|
|
167
|
+
portForward: `kubectl port-forward -n ${namespace} svc/${MONGO_EXPRESS_SERVICE_NAME} ${MONGO_EXPRESS_PORT}:${MONGO_EXPRESS_PORT}`,
|
|
168
|
+
});
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export {
|
|
174
|
+
MONGO_EXPRESS_BASE_URL,
|
|
175
|
+
MONGO_EXPRESS_IMAGE,
|
|
176
|
+
MONGO_EXPRESS_NAME,
|
|
177
|
+
MONGO_EXPRESS_NODE_PORT,
|
|
178
|
+
MONGO_EXPRESS_PORT,
|
|
179
|
+
MONGO_EXPRESS_SECRET_NAME,
|
|
180
|
+
MONGO_EXPRESS_SERVICE_NAME,
|
|
181
|
+
MongoExpress,
|
|
182
|
+
mongoAuthEnabledFactory,
|
|
183
|
+
mongoExpressManifestPathFactory,
|
|
184
|
+
mongoExpressNodePortManifestFactory,
|
|
185
|
+
parseMongodArgs,
|
|
186
|
+
};
|
|
187
|
+
export default MongoExpress;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import mongoose from 'mongoose';
|
|
2
2
|
import { getCapVariableName } from '../../client/components/core/CommonJs.js';
|
|
3
|
-
import { loggerFactory } from '../../server/logger.js';
|
|
3
|
+
import { loggerFactory } from '../../server/ops/logger.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Module for connecting to and loading models for a MongoDB database using Mongoose.
|
|
@@ -13,16 +13,13 @@ const logger = loggerFactory(import.meta);
|
|
|
13
13
|
const MONGODB_SERVICE_NAME = 'mongodb-service';
|
|
14
14
|
const MONGODB_STATEFULSET_NAME = 'mongodb';
|
|
15
15
|
const MONGODB_DEFAULT_AUTH_SOURCE = 'admin';
|
|
16
|
+
const MONGODB_DEFAULT_PORT = 27017;
|
|
16
17
|
const MONGODB_DEFAULT_REPLICA_SET = 'rs0';
|
|
17
18
|
const MONGODB_DEFAULT_REPLICA_COUNT = 3;
|
|
18
|
-
// Node-local base path backing the hostPath PVs (`<root>/v<replica index>`),
|
|
19
|
-
// generated one-per-replica by MongoBootstrap.applyReplicaVolumes().
|
|
20
19
|
const MONGODB_DATA_ROOT = '/data/mongodb';
|
|
21
|
-
// Replica volumes are hostPath PVs generated one per member, each pinned by `claimRef`. The class
|
|
22
|
-
// must stay static: a dynamic provisioner competes with the static binder and makes
|
|
23
|
-
// member-to-directory assignment non-deterministic.
|
|
24
20
|
const MONGODB_STORAGE_CLASS_NAME = 'mongodb-storage-class';
|
|
25
21
|
const MONGODB_STORAGE_CLASS_PROVISIONER = 'kubernetes.io/no-provisioner';
|
|
22
|
+
|
|
26
23
|
/**
|
|
27
24
|
* Mongoose connection options for MongoDB, with sensible defaults for production and development environments.
|
|
28
25
|
* @type {import('mongoose').ConnectOptions}
|
|
@@ -51,12 +48,12 @@ const resolveMongoReplicaHosts = ({ hostList = '', replicaCount = MONGODB_DEFAUL
|
|
|
51
48
|
.split(',')
|
|
52
49
|
.map((host) => host.trim())
|
|
53
50
|
.filter(Boolean)
|
|
54
|
-
.map((host) => (host.includes(':') ? host : `${host}
|
|
51
|
+
.map((host) => (host.includes(':') ? host : `${host}:${MONGODB_DEFAULT_PORT}`));
|
|
55
52
|
}
|
|
56
53
|
|
|
57
54
|
return Array.from(
|
|
58
55
|
{ length: replicaCount },
|
|
59
|
-
(_, index) => `${MONGODB_STATEFULSET_NAME}-${index}.${MONGODB_SERVICE_NAME}
|
|
56
|
+
(_, index) => `${MONGODB_STATEFULSET_NAME}-${index}.${MONGODB_SERVICE_NAME}:${MONGODB_DEFAULT_PORT}`,
|
|
60
57
|
);
|
|
61
58
|
};
|
|
62
59
|
|
|
@@ -208,6 +205,8 @@ export {
|
|
|
208
205
|
MongooseDB,
|
|
209
206
|
MongooseDBService as MongooseDBClass,
|
|
210
207
|
MONGODB_DATA_ROOT,
|
|
208
|
+
MONGODB_DEFAULT_AUTH_SOURCE,
|
|
209
|
+
MONGODB_DEFAULT_PORT,
|
|
211
210
|
MONGODB_DEFAULT_REPLICA_COUNT,
|
|
212
211
|
MONGODB_DEFAULT_REPLICA_SET,
|
|
213
212
|
MONGODB_SERVICE_NAME,
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
* Out of scope: domain model factories, DTO projection — those belong in
|
|
10
10
|
* their respective service modules (e.g. guest.service.js).
|
|
11
11
|
*
|
|
12
|
-
* @module src/
|
|
12
|
+
* @module src/db/valkey/Valkey.js
|
|
13
13
|
* @namespace ValkeyService
|
|
14
14
|
*/
|
|
15
15
|
import Valkey from 'iovalkey';
|
|
16
|
-
import { loggerFactory } from '
|
|
17
|
-
import Underpost from '
|
|
16
|
+
import { loggerFactory } from '../../server/ops/logger.js';
|
|
17
|
+
import Underpost from '../../index.js';
|
|
18
|
+
import { latchRuntimeError } from '../../server/runtime/runtime-status.js';
|
|
18
19
|
|
|
19
20
|
const logger = loggerFactory(import.meta);
|
|
20
21
|
|
|
@@ -71,7 +72,7 @@ const createValkeyConnection = async (instance = {}, connectionOptions = {}) =>
|
|
|
71
72
|
client.on('error', (err) => {
|
|
72
73
|
ValkeyStatus[key] = 'error';
|
|
73
74
|
logger.error('Valkey error', { err: err?.message, instance });
|
|
74
|
-
|
|
75
|
+
latchRuntimeError();
|
|
75
76
|
});
|
|
76
77
|
client.on('reconnecting', () => {
|
|
77
78
|
ValkeyStatus[key] = 'reconnecting';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gRPC transport for the Cyberia Engine data pipeline.
|
|
3
3
|
*
|
|
4
|
-
* Runs
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* /api/cyberia-instance/boot/* — so both transports stay equivalent.
|
|
4
|
+
* Runs beside Express on its own port (default 50051). Thin adapter over
|
|
5
|
+
* src/projects/cyberia/instance-data.js, the same assembly the REST fallback
|
|
6
|
+
* at /api/cyberia-instance/boot/* serves, so both transports stay equivalent.
|
|
8
7
|
*
|
|
9
8
|
* @module src/grpc/cyberia/grpc-server.js
|
|
10
9
|
*/
|
|
@@ -13,10 +12,9 @@ import * as grpc from '@grpc/grpc-js';
|
|
|
13
12
|
import * as protoLoader from '@grpc/proto-loader';
|
|
14
13
|
import path from 'path';
|
|
15
14
|
import { fileURLToPath } from 'url';
|
|
16
|
-
import { loggerFactory } from '../../server/logger.js';
|
|
15
|
+
import { loggerFactory } from '../../server/ops/logger.js';
|
|
17
16
|
import {
|
|
18
17
|
buildFallbackConfig,
|
|
19
|
-
buildFallbackInstanceConfig,
|
|
20
18
|
fetchFullInstance,
|
|
21
19
|
fetchMapData,
|
|
22
20
|
fetchObjectLayer,
|
|
@@ -131,7 +129,7 @@ class GrpcServer {
|
|
|
131
129
|
|
|
132
130
|
server.addService(proto.CyberiaDataService.service, buildHandlers(dbKey));
|
|
133
131
|
|
|
134
|
-
// gRPC
|
|
132
|
+
// gRPC stays on the cluster-internal network, so credentials are insecure.
|
|
135
133
|
const creds = grpc.ServerCredentials.createInsecure();
|
|
136
134
|
|
|
137
135
|
return new Promise((resolve, reject) => {
|
|
@@ -159,4 +157,4 @@ class GrpcServer {
|
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
|
|
162
|
-
export { GrpcServer, buildFallbackConfig
|
|
160
|
+
export { GrpcServer, buildFallbackConfig };
|
package/src/index.js
CHANGED
|
@@ -5,23 +5,28 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import UnderpostBaremetal from './cli/baremetal.js';
|
|
8
|
+
import UnderpostApp from './cli/app.js';
|
|
9
|
+
import UnderpostClient from './cli/client.js';
|
|
10
|
+
import UnderpostHost from './cli/host.js';
|
|
8
11
|
import UnderpostCloudInit from './cli/cloud-init.js';
|
|
9
12
|
import UnderpostKickStart from './cli/kickstart.js';
|
|
10
13
|
import UnderpostCluster from './cli/cluster.js';
|
|
11
14
|
import UnderpostDB from './cli/db.js';
|
|
12
15
|
import UnderpostDeploy from './cli/deploy.js';
|
|
13
16
|
import UnderpostDockerCompose from './cli/docker-compose.js';
|
|
17
|
+
import UnderpostEvent from './cli/event.js';
|
|
14
18
|
import UnderpostKubectl from './cli/kubectl.js';
|
|
15
|
-
import UnderpostRootEnv from './cli/env.js';
|
|
16
19
|
import UnderpostFileStorage from './cli/fs.js';
|
|
17
20
|
import UnderpostIPFS from './cli/ipfs.js';
|
|
18
21
|
import UnderpostImage from './cli/image.js';
|
|
19
22
|
import UnderpostLxd from './cli/lxd.js';
|
|
20
23
|
import UnderpostMonitor from './cli/monitor.js';
|
|
24
|
+
import UnderpostPackage from './cli/package.js';
|
|
21
25
|
import UnderpostRepository from './cli/repository.js';
|
|
22
26
|
import UnderpostRun from './cli/run.js';
|
|
23
27
|
import UnderpostSecret from './cli/secrets.js';
|
|
24
28
|
import UnderpostSSH from './cli/ssh.js';
|
|
29
|
+
import UnderpostState from './cli/state.js';
|
|
25
30
|
import UnderpostStatic from './cli/static.js';
|
|
26
31
|
import UnderpostTest from './cli/test.js';
|
|
27
32
|
import UnderpostRelease from './cli/release.js';
|
|
@@ -29,11 +34,11 @@ import UnderpostSystemProvisionig from './cli/system.js';
|
|
|
29
34
|
import UnderpostVultr from './cli/vultr.js';
|
|
30
35
|
import UnderpostWireguard from './cli/wireguard.js';
|
|
31
36
|
|
|
32
|
-
import UnderpostDns from './server/dns.js';
|
|
33
|
-
import UnderpostBackup from './server/backup.js';
|
|
34
|
-
import UnderpostCron from './server/cron.js';
|
|
35
|
-
import UnderpostStartUp from './server/start.js';
|
|
36
|
-
import UnderpostTLS from './server/tls.js';
|
|
37
|
+
import UnderpostDns from './server/network/dns.js';
|
|
38
|
+
import UnderpostBackup from './server/storage/backup.js';
|
|
39
|
+
import UnderpostCron from './server/ops/cron.js';
|
|
40
|
+
import UnderpostStartUp from './server/runtime/start.js';
|
|
41
|
+
import UnderpostTLS from './server/network/tls.js';
|
|
37
42
|
|
|
38
43
|
/**
|
|
39
44
|
* Underpost main module methods
|
|
@@ -47,7 +52,7 @@ class Underpost {
|
|
|
47
52
|
* @type {String}
|
|
48
53
|
* @memberof Underpost
|
|
49
54
|
*/
|
|
50
|
-
static version = 'v3.3.
|
|
55
|
+
static version = 'v3.3.76';
|
|
51
56
|
|
|
52
57
|
/**
|
|
53
58
|
* Required Node.js major version
|
|
@@ -67,24 +72,14 @@ class Underpost {
|
|
|
67
72
|
return UnderpostRepository.API;
|
|
68
73
|
}
|
|
69
74
|
/**
|
|
70
|
-
*
|
|
75
|
+
* Client build cli API
|
|
71
76
|
* @static
|
|
72
|
-
* @type {
|
|
77
|
+
* @type {UnderpostClient.API}
|
|
73
78
|
* @memberof Underpost
|
|
74
79
|
*/
|
|
75
|
-
static get
|
|
76
|
-
return
|
|
80
|
+
static get client() {
|
|
81
|
+
return UnderpostClient.API;
|
|
77
82
|
}
|
|
78
|
-
/**
|
|
79
|
-
* Test cli API
|
|
80
|
-
* @static
|
|
81
|
-
* @type {UnderpostTest.API}
|
|
82
|
-
* @memberof Underpost
|
|
83
|
-
*/
|
|
84
|
-
static get test() {
|
|
85
|
-
return UnderpostTest.API;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
83
|
/**
|
|
89
84
|
* Static cli API
|
|
90
85
|
* @static
|
|
@@ -119,6 +114,33 @@ class Underpost {
|
|
|
119
114
|
* @type {UnderpostSecret.API}
|
|
120
115
|
* @memberof Underpost
|
|
121
116
|
*/
|
|
117
|
+
static get host() {
|
|
118
|
+
return UnderpostHost.API;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* App deployment environment domain cli API
|
|
122
|
+
* @static
|
|
123
|
+
* @type {UnderpostApp.API}
|
|
124
|
+
* @memberof Underpost
|
|
125
|
+
*/
|
|
126
|
+
static get app() {
|
|
127
|
+
return UnderpostApp.API;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Workload secret store domain cli API
|
|
131
|
+
* @static
|
|
132
|
+
* @type {UnderpostSecret.API}
|
|
133
|
+
* @memberof Underpost
|
|
134
|
+
*/
|
|
135
|
+
static get state() {
|
|
136
|
+
return UnderpostState.API;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Workload secret store domain cli API
|
|
140
|
+
* @static
|
|
141
|
+
* @type {UnderpostSecret.API}
|
|
142
|
+
* @memberof Underpost
|
|
143
|
+
*/
|
|
122
144
|
static get secret() {
|
|
123
145
|
return UnderpostSecret.API;
|
|
124
146
|
}
|
|
@@ -185,6 +207,15 @@ class Underpost {
|
|
|
185
207
|
static get monitor() {
|
|
186
208
|
return UnderpostMonitor.API;
|
|
187
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Operational event dispatcher cli API
|
|
212
|
+
* @static
|
|
213
|
+
* @type {UnderpostEvent.API}
|
|
214
|
+
* @memberof Underpost
|
|
215
|
+
*/
|
|
216
|
+
static get event() {
|
|
217
|
+
return UnderpostEvent.API;
|
|
218
|
+
}
|
|
188
219
|
/**
|
|
189
220
|
* SSH cli API
|
|
190
221
|
* @static
|
|
@@ -333,6 +364,26 @@ class Underpost {
|
|
|
333
364
|
static get release() {
|
|
334
365
|
return UnderpostRelease.API;
|
|
335
366
|
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Test runner cli API
|
|
370
|
+
* @static
|
|
371
|
+
* @type {UnderpostTest.API}
|
|
372
|
+
* @memberof Underpost
|
|
373
|
+
*/
|
|
374
|
+
static get test() {
|
|
375
|
+
return UnderpostTest.API;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Deploy package manifest cli API
|
|
380
|
+
* @static
|
|
381
|
+
* @type {UnderpostPackage.API}
|
|
382
|
+
* @memberof Underpost
|
|
383
|
+
*/
|
|
384
|
+
static get package() {
|
|
385
|
+
return UnderpostPackage.API;
|
|
386
|
+
}
|
|
336
387
|
}
|
|
337
388
|
|
|
338
389
|
if (!process.version || !process.version.startsWith(`${Underpost.majorNodejsVersion}.`))
|
|
@@ -354,20 +405,25 @@ export {
|
|
|
354
405
|
UnderpostDB,
|
|
355
406
|
UnderpostDeploy,
|
|
356
407
|
UnderpostDockerCompose,
|
|
408
|
+
UnderpostEvent,
|
|
357
409
|
UnderpostKubectl,
|
|
358
|
-
UnderpostRootEnv,
|
|
359
410
|
UnderpostFileStorage,
|
|
360
411
|
UnderpostImage,
|
|
361
412
|
UnderpostStatic,
|
|
413
|
+
UnderpostTest,
|
|
362
414
|
UnderpostLxd,
|
|
363
415
|
UnderpostKickStart,
|
|
364
416
|
UnderpostIPFS,
|
|
365
417
|
UnderpostMonitor,
|
|
418
|
+
UnderpostPackage,
|
|
419
|
+
UnderpostApp,
|
|
420
|
+
UnderpostClient,
|
|
421
|
+
UnderpostHost,
|
|
366
422
|
UnderpostRepository,
|
|
367
423
|
UnderpostRun,
|
|
368
424
|
UnderpostSecret,
|
|
369
425
|
UnderpostSSH,
|
|
370
|
-
|
|
426
|
+
UnderpostState,
|
|
371
427
|
UnderpostDns,
|
|
372
428
|
UnderpostBackup,
|
|
373
429
|
UnderpostCron,
|
|
@@ -98,8 +98,8 @@ class EmailRenderService {
|
|
|
98
98
|
for (const templateKey of Object.keys(options.templates)) {
|
|
99
99
|
const ssrEmailComponent = options.templates[templateKey];
|
|
100
100
|
// Note: ssrFactory is assumed to load and return a functional component/function
|
|
101
|
-
const
|
|
102
|
-
templates[templateKey] =
|
|
101
|
+
const SSRComponent = await ssrFactory(`./src/client/ssr/mailer/${ssrEmailComponent}.js`);
|
|
102
|
+
templates[templateKey] = SSRComponent(this, options);
|
|
103
103
|
}
|
|
104
104
|
return templates;
|
|
105
105
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { MailerProvider } from './MailerProvider.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* General-purpose capture of everything {@link MailerProviderService#send}
|
|
5
|
+
* delivers, built on the provider's send middleware.
|
|
6
|
+
*
|
|
7
|
+
* Assertions about mail are otherwise only possible against a real inbox. The
|
|
8
|
+
* interceptor records the delivery context and the transport result of each
|
|
9
|
+
* send, which is what lets a caller wait for a specific message and know
|
|
10
|
+
* whether the transport actually accepted it.
|
|
11
|
+
*
|
|
12
|
+
* @module src/mailer/MailerInterceptor.js
|
|
13
|
+
* @namespace MailerInterceptor
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} InterceptedMail
|
|
18
|
+
* @property {string} id - Mailer instance the message was sent through.
|
|
19
|
+
* @property {object} sendOptions - Nodemailer options as the transport received them.
|
|
20
|
+
* @property {object|undefined} info - Transport result; `undefined` when delivery failed.
|
|
21
|
+
* @property {boolean} accepted - Whether the transport accepted the message.
|
|
22
|
+
* @property {string} at - ISO timestamp of the delivery attempt.
|
|
23
|
+
* @memberof MailerInterceptor
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @method mailerInterceptorFactory
|
|
28
|
+
* @description Installs a send interceptor and returns its recorder.
|
|
29
|
+
*
|
|
30
|
+
* The interceptor is transparent: it forwards every send to the transport and
|
|
31
|
+
* records the outcome. `suppress` holds the message instead, for callers that
|
|
32
|
+
* must exercise the send path without delivering.
|
|
33
|
+
*
|
|
34
|
+
* @param {object} [params]
|
|
35
|
+
* @param {import('./MailerProvider.js').MailerProvider} [params.provider] - Provider to intercept.
|
|
36
|
+
* @param {function(object): boolean} [params.filter] - Records only the contexts it accepts.
|
|
37
|
+
* @param {boolean} [params.suppress=false] - Record without handing the message to the transport.
|
|
38
|
+
* @returns {{messages: Array<InterceptedMail>, waitFor: function, close: function(): void}} Recorder.
|
|
39
|
+
* @memberof MailerInterceptor
|
|
40
|
+
*/
|
|
41
|
+
const mailerInterceptorFactory = ({ provider = MailerProvider, filter, suppress = false } = {}) => {
|
|
42
|
+
const messages = [];
|
|
43
|
+
|
|
44
|
+
const dispose = provider.use(async (context, next) => {
|
|
45
|
+
const matched = !filter || filter(context);
|
|
46
|
+
const info = matched && suppress ? { messageId: `suppressed:${Date.now()}`, suppressed: true } : await next();
|
|
47
|
+
if (matched)
|
|
48
|
+
messages.push({
|
|
49
|
+
id: context.id,
|
|
50
|
+
sendOptions: context.sendOptions,
|
|
51
|
+
info,
|
|
52
|
+
accepted: Boolean(info),
|
|
53
|
+
at: new Date().toISOString(),
|
|
54
|
+
});
|
|
55
|
+
return info;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
messages,
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolves with the first recorded message matching `predicate`.
|
|
63
|
+
*
|
|
64
|
+
* Polls rather than resolving on registration, because a send started
|
|
65
|
+
* before the caller began waiting must still satisfy the wait.
|
|
66
|
+
*
|
|
67
|
+
* @param {function(InterceptedMail): boolean} predicate - Match to wait for.
|
|
68
|
+
* @param {object} [options]
|
|
69
|
+
* @param {number} [options.timeoutMs=60000] - Maximum wait.
|
|
70
|
+
* @param {number} [options.intervalMs=250] - Poll interval.
|
|
71
|
+
* @returns {Promise<InterceptedMail|undefined>} The match, or `undefined` on timeout.
|
|
72
|
+
*/
|
|
73
|
+
async waitFor(predicate, { timeoutMs = 60000, intervalMs = 250 } = {}) {
|
|
74
|
+
const deadline = Date.now() + timeoutMs;
|
|
75
|
+
do {
|
|
76
|
+
const match = messages.find(predicate);
|
|
77
|
+
if (match) return match;
|
|
78
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
79
|
+
} while (Date.now() < deadline);
|
|
80
|
+
return messages.find(predicate);
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
close: dispose,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { mailerInterceptorFactory };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import nodemailer from 'nodemailer';
|
|
2
|
-
import { loggerFactory } from '../server/logger.js';
|
|
2
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
3
3
|
import { EmailRender } from './EmailRender.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -45,6 +45,12 @@ class MailerProviderService {
|
|
|
45
45
|
*/
|
|
46
46
|
#instance = {};
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Registered send middlewares, in the order they wrap a delivery.
|
|
50
|
+
* @type {Array<function(object, function(): Promise<object|undefined>): Promise<object|undefined>>}
|
|
51
|
+
*/
|
|
52
|
+
#middlewares = [];
|
|
53
|
+
|
|
48
54
|
/**
|
|
49
55
|
* Retrieves the internal instance storage for direct access (used for backward compatibility).
|
|
50
56
|
* @returns {object.<string, object>} The internal mailer instance map.
|
|
@@ -53,6 +59,28 @@ class MailerProviderService {
|
|
|
53
59
|
return this.#instance;
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Registers a send middleware.
|
|
64
|
+
*
|
|
65
|
+
* Middlewares wrap every {@link MailerProviderService#send}, in registration
|
|
66
|
+
* order, and receive the delivery context plus the `next` continuation that
|
|
67
|
+
* yields the transport result. A middleware that never calls `next` suppresses
|
|
68
|
+
* the delivery, which is what makes this usable both for cross-cutting
|
|
69
|
+
* concerns (auditing, rate limiting) and for capturing mail in a test run.
|
|
70
|
+
*
|
|
71
|
+
* @param {function(object, function(): Promise<object|undefined>): Promise<object|undefined>} middleware -
|
|
72
|
+
* Receives `({ id, sendOptions, sender }, next)`.
|
|
73
|
+
* @returns {function(): void} Disposer that unregisters the middleware.
|
|
74
|
+
*/
|
|
75
|
+
use(middleware) {
|
|
76
|
+
if (typeof middleware !== 'function') throw new Error('[mailer] a send middleware must be a function');
|
|
77
|
+
this.#middlewares.push(middleware);
|
|
78
|
+
return () => {
|
|
79
|
+
const index = this.#middlewares.indexOf(middleware);
|
|
80
|
+
if (index !== -1) this.#middlewares.splice(index, 1);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
56
84
|
/**
|
|
57
85
|
* Loads and initializes a new mailer provider instance using Nodemailer.
|
|
58
86
|
* The created instance is stored internally and includes the transporter and rendered templates.
|
|
@@ -145,6 +173,24 @@ class MailerProviderService {
|
|
|
145
173
|
}
|
|
146
174
|
}
|
|
147
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Closes a loaded instance's transport and forgets it.
|
|
178
|
+
*
|
|
179
|
+
* A transport holds an open socket, which keeps a one-shot process alive long
|
|
180
|
+
* after its work is done. Callers that load an instance for a single delivery
|
|
181
|
+
* release it here; a long-running server keeps its instances loaded instead.
|
|
182
|
+
*
|
|
183
|
+
* @param {string} id - Mailer instance id.
|
|
184
|
+
* @returns {boolean} True when an instance was closed.
|
|
185
|
+
*/
|
|
186
|
+
close(id) {
|
|
187
|
+
const instance = this.#instance[id];
|
|
188
|
+
if (!instance) return false;
|
|
189
|
+
if (typeof instance.transporter?.close === 'function') instance.transporter.close();
|
|
190
|
+
delete this.#instance[id];
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
|
|
148
194
|
/**
|
|
149
195
|
* Sends an email using a previously loaded transporter instance.
|
|
150
196
|
*
|
|
@@ -189,12 +235,10 @@ class MailerProviderService {
|
|
|
189
235
|
|
|
190
236
|
if (!sendOptions.from) sendOptions.from = `${instance.sender.name} <${instance.sender.email}>`;
|
|
191
237
|
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
// logger.info('Message sent', info);
|
|
238
|
+
const context = { id, sendOptions, sender: instance.sender };
|
|
239
|
+
const deliver = () => instance.transporter.sendMail(sendOptions);
|
|
196
240
|
|
|
197
|
-
return
|
|
241
|
+
return await this.#middlewares.reduceRight((next, middleware) => () => middleware(context, next), deliver)();
|
|
198
242
|
} catch (error) {
|
|
199
243
|
logger.error(error, error.stack);
|
|
200
244
|
return undefined;
|