cyberia 3.1.3 → 3.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +0 -2
- package/.github/workflows/engine-cyberia.cd.yml +10 -8
- package/.github/workflows/engine-cyberia.ci.yml +12 -29
- package/.github/workflows/ghpkg.ci.yml +4 -4
- package/.github/workflows/npmpkg.ci.yml +28 -11
- package/.github/workflows/publish.ci.yml +21 -2
- package/.github/workflows/pwa-microservices-template-page.cd.yml +4 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
- package/.github/workflows/release.cd.yml +14 -10
- package/CHANGELOG.md +783 -1
- package/CLI-HELP.md +95 -18
- package/Dockerfile +0 -2
- package/README.md +290 -220
- package/bin/build.js +24 -7
- package/bin/cyberia.js +2838 -252
- package/bin/deploy.js +747 -125
- package/bin/file.js +9 -0
- package/bin/index.js +2838 -252
- package/bin/vs.js +1 -1
- package/conf.js +99 -65
- package/deployment.yaml +18 -164
- package/hardhat/hardhat.config.js +13 -13
- package/hardhat/ignition/modules/ObjectLayerToken.js +1 -1
- package/hardhat/package-lock.json +2559 -5864
- package/hardhat/package.json +14 -23
- package/hardhat/scripts/deployObjectLayerToken.js +1 -1
- package/hardhat/test/ObjectLayerToken.js +4 -2
- package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
- package/hardhat/types/ethers-contracts/common.ts +92 -0
- package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
- package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
- package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
- package/hardhat/types/ethers-contracts/index.ts +6 -0
- package/jsconfig.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +6 -5
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +6 -5
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +18 -164
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +7 -79
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
- package/manifests/deployment/dd-test-development/deployment.yaml +112 -28
- package/manifests/deployment/dd-test-development/proxy.yaml +46 -1
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +39 -24
- package/proxy.yaml +7 -79
- package/scripts/k3s-node-setup.sh +2 -2
- package/scripts/nat-iptables.sh +103 -18
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +58 -14
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +23 -14
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +148 -20
- package/src/api/core/core.controller.js +10 -10
- package/src/api/core/core.service.js +10 -10
- package/src/api/crypto/crypto.controller.js +8 -8
- package/src/api/crypto/crypto.service.js +8 -8
- package/src/api/cyberia-action/cyberia-action.controller.js +74 -0
- package/src/api/cyberia-action/cyberia-action.model.js +87 -0
- package/src/api/cyberia-action/cyberia-action.router.js +27 -0
- package/src/api/cyberia-action/cyberia-action.service.js +42 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
- package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
- package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
- package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
- package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +178 -0
- package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
- package/src/api/cyberia-instance/cyberia-instance.model.js +87 -0
- package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +156 -0
- package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
- package/src/api/cyberia-instance/cyberia-world-generator.js +505 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +574 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +231 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
- package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
- package/src/api/cyberia-map/cyberia-map.model.js +30 -0
- package/src/api/cyberia-map/cyberia-map.router.js +40 -0
- package/src/api/cyberia-map/cyberia-map.service.js +74 -0
- package/src/api/cyberia-quest/cyberia-quest.controller.js +74 -0
- package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +27 -0
- package/src/api/cyberia-quest/cyberia-quest.service.js +42 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +74 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +27 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
- package/src/api/default/default.controller.js +10 -10
- package/src/api/default/default.service.js +10 -10
- package/src/api/document/document.controller.js +12 -12
- package/src/api/document/document.model.js +10 -16
- package/src/api/file/file.controller.js +8 -8
- package/src/api/file/file.model.js +10 -10
- package/src/api/file/file.ref.json +18 -0
- package/src/api/file/file.service.js +36 -36
- package/src/api/instance/instance.controller.js +10 -10
- package/src/api/instance/instance.model.js +4 -10
- package/src/api/instance/instance.service.js +10 -10
- package/src/api/ipfs/ipfs.controller.js +15 -36
- package/src/api/ipfs/ipfs.model.js +47 -47
- package/src/api/ipfs/ipfs.router.js +8 -13
- package/src/api/ipfs/ipfs.service.js +67 -129
- package/src/api/object-layer/object-layer.controller.js +12 -12
- package/src/api/object-layer/object-layer.model.js +4 -17
- package/src/api/object-layer/object-layer.router.js +30 -0
- package/src/api/object-layer/object-layer.service.js +126 -43
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +10 -10
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +6 -16
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +18 -14
- package/src/api/test/test.controller.js +8 -8
- package/src/api/test/test.service.js +8 -8
- package/src/api/user/guest.service.js +99 -0
- package/src/api/user/user.controller.js +6 -6
- package/src/api/user/user.model.js +8 -13
- package/src/api/user/user.service.js +11 -27
- package/src/cli/cluster.js +68 -21
- package/src/cli/db.js +753 -825
- package/src/cli/deploy.js +215 -125
- package/src/cli/env.js +29 -0
- package/src/cli/fs.js +82 -8
- package/src/cli/image.js +43 -1
- package/src/cli/index.js +74 -3
- package/src/cli/kubectl.js +211 -0
- package/src/cli/release.js +340 -0
- package/src/cli/repository.js +475 -74
- package/src/cli/run.js +582 -43
- package/src/cli/secrets.js +73 -0
- package/src/cli/ssh.js +1 -1
- package/src/cli/static.js +43 -115
- package/src/cli/test.js +3 -3
- package/src/client/Cryptokoyn.index.js +18 -22
- package/src/client/CyberiaPortal.index.js +19 -24
- package/src/client/Default.index.js +21 -34
- package/src/client/Itemledger.index.js +20 -27
- package/src/client/Underpost.index.js +19 -24
- package/src/client/components/core/404.js +4 -4
- package/src/client/components/core/500.js +4 -4
- package/src/client/components/core/Account.js +73 -60
- package/src/client/components/core/AgGrid.js +23 -33
- package/src/client/components/core/Alert.js +12 -13
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/Auth.js +35 -37
- package/src/client/components/core/Badge.js +7 -13
- package/src/client/components/core/BtnIcon.js +15 -17
- package/src/client/components/core/CalendarCore.js +43 -64
- package/src/client/components/core/Chat.js +13 -15
- package/src/client/components/core/ClientEvents.js +87 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/Content.js +17 -14
- package/src/client/components/core/Css.js +15 -71
- package/src/client/components/core/CssCore.js +12 -16
- package/src/client/components/core/D3Chart.js +4 -4
- package/src/client/components/core/Docs.js +64 -91
- package/src/client/components/core/DropDown.js +194 -96
- package/src/client/components/core/EventBus.js +92 -0
- package/src/client/components/core/EventsUI.js +14 -17
- package/src/client/components/core/FileExplorer.js +96 -228
- package/src/client/components/core/FullScreen.js +47 -75
- package/src/client/components/core/Input.js +24 -69
- package/src/client/components/core/Keyboard.js +26 -19
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +25 -31
- package/src/client/components/core/LogIn.js +43 -43
- package/src/client/components/core/LogOut.js +25 -16
- package/src/client/components/core/Modal.js +462 -179
- package/src/client/components/core/NotificationManager.js +14 -18
- package/src/client/components/core/Panel.js +54 -51
- package/src/client/components/core/PanelForm.js +44 -144
- package/src/client/components/core/Polyhedron.js +110 -214
- package/src/client/components/core/PublicProfile.js +39 -32
- package/src/client/components/core/Recover.js +48 -44
- package/src/client/components/core/Responsive.js +88 -32
- package/src/client/components/core/RichText.js +9 -18
- package/src/client/components/core/Router.js +24 -3
- package/src/client/components/core/SearchBox.js +37 -37
- package/src/client/components/core/SignUp.js +39 -30
- package/src/client/components/core/SocketIo.js +112 -30
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/ToggleSwitch.js +8 -20
- package/src/client/components/core/ToolTip.js +5 -17
- package/src/client/components/core/Translate.js +56 -59
- package/src/client/components/core/Validator.js +26 -16
- package/src/client/components/core/Wallet.js +15 -26
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/core/Worker.js +163 -27
- package/src/client/components/core/windowGetDimensions.js +7 -7
- package/src/client/components/cryptokoyn/{MenuCryptokoyn.js → AppShellCryptokoyn.js} +59 -59
- package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
- package/src/client/components/cryptokoyn/CssCryptokoyn.js +15 -15
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +9 -7
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +8 -6
- package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +4 -4
- package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +6 -4
- package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
- package/src/client/components/cyberia/InstanceEngineCyberia.js +781 -0
- package/src/client/components/cyberia/MapEngineCyberia.js +1836 -2
- package/src/client/components/cyberia/ObjectLayerEngine.js +19 -0
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +1220 -99
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +252 -316
- package/src/client/components/cyberia-portal/{MenuCyberiaPortal.js → AppShellCyberiaPortal.js} +136 -103
- package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +462 -32
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +15 -15
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +9 -7
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +8 -6
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +60 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +8 -4
- package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +91 -91
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/CssDefault.js +12 -12
- package/src/client/components/default/LogInDefault.js +9 -7
- package/src/client/components/default/LogOutDefault.js +8 -6
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +4 -4
- package/src/client/components/default/SignUpDefault.js +6 -4
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/components/default/TranslateDefault.js +3 -3
- package/src/client/components/itemledger/{MenuItemledger.js → AppShellItemledger.js} +59 -59
- package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
- package/src/client/components/itemledger/CssItemledger.js +15 -15
- package/src/client/components/itemledger/LogInItemledger.js +9 -7
- package/src/client/components/itemledger/LogOutItemledger.js +8 -6
- package/src/client/components/itemledger/RouterItemledger.js +38 -0
- package/src/client/components/itemledger/SettingsItemledger.js +4 -4
- package/src/client/components/itemledger/SignUpItemledger.js +6 -4
- package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
- package/src/client/components/itemledger/TranslateItemledger.js +3 -3
- package/src/client/components/underpost/{MenuUnderpost.js → AppShellUnderpost.js} +92 -92
- package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
- package/src/client/components/underpost/CssUnderpost.js +14 -14
- package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +4 -4
- package/src/client/components/underpost/DocumentSearchProvider.js +1 -1
- package/src/client/components/underpost/LabGalleryUnderpost.js +12 -15
- package/src/client/components/underpost/LogInUnderpost.js +9 -7
- package/src/client/components/underpost/LogOutUnderpost.js +8 -6
- package/src/client/components/underpost/RouterUnderpost.js +45 -0
- package/src/client/components/underpost/SettingsUnderpost.js +4 -4
- package/src/client/components/underpost/SignUpUnderpost.js +6 -4
- package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
- package/src/client/components/underpost/TranslateUnderpost.js +4 -4
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +235 -0
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +443 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +417 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +313 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +260 -0
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +241 -0
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +279 -0
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +206 -0
- package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +732 -0
- package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +14 -20
- package/src/client/services/core/core.service.js +35 -55
- package/src/client/services/crypto/crypto.service.js +8 -13
- package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +116 -0
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
- package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
- package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
- package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
- package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
- package/src/client/services/default/default.management.js +159 -267
- package/src/client/services/default/default.service.js +10 -16
- package/src/client/services/document/document.service.js +14 -19
- package/src/client/services/file/file.service.js +8 -13
- package/src/client/services/instance/instance.management.js +6 -6
- package/src/client/services/instance/instance.service.js +10 -15
- package/src/client/services/ipfs/ipfs.service.js +14 -40
- package/src/client/services/object-layer/object-layer.management.js +14 -14
- package/src/client/services/object-layer/object-layer.service.js +39 -24
- package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +10 -16
- package/src/client/services/test/test.service.js +8 -13
- package/src/client/services/user/guest.service.js +86 -0
- package/src/client/services/user/user.management.js +6 -6
- package/src/client/services/user/user.service.js +14 -20
- package/src/client/ssr/body/404.js +3 -3
- package/src/client/ssr/body/500.js +3 -3
- package/src/client/ssr/body/CacheControl.js +5 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +13 -6
- package/src/client/ssr/head/PwaItemledger.js +197 -60
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
- package/src/client/ssr/offline/Maintenance.js +12 -11
- package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
- package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/pages/Test.js +2 -2
- package/src/client/sw/core.sw.js +212 -0
- package/src/grpc/cyberia/grpc-server.js +642 -0
- package/src/index.js +24 -1
- package/src/runtime/cyberia-client/Dockerfile +80 -0
- package/src/runtime/cyberia-server/Dockerfile +37 -0
- package/src/runtime/express/Dockerfile +5 -1
- package/src/runtime/express/Express.js +18 -1
- package/src/runtime/lampp/Dockerfile +17 -5
- package/src/runtime/lampp/Lampp.js +27 -4
- package/src/runtime/wp/Dockerfile +62 -0
- package/src/runtime/wp/Wp.js +639 -0
- package/src/server/atlas-sprite-sheet-generator.js +4 -2
- package/src/server/auth.js +24 -1
- package/src/server/backup.js +37 -9
- package/src/server/client-build-docs.js +52 -46
- package/src/server/client-build.js +356 -82
- package/src/server/client-formatted.js +140 -57
- package/src/server/conf.js +29 -13
- package/src/server/cron.js +25 -23
- package/src/server/data-query.js +32 -20
- package/src/server/dns.js +24 -1
- package/src/server/ipfs-client.js +253 -89
- package/src/server/object-layer.js +150 -114
- package/src/server/peer.js +8 -0
- package/src/server/process.js +13 -27
- package/src/server/runtime.js +25 -1
- package/src/server/semantic-layer-generator-floor.js +319 -0
- package/src/server/semantic-layer-generator-resource.js +259 -0
- package/src/server/semantic-layer-generator-skin.js +1164 -0
- package/src/server/semantic-layer-generator.js +211 -542
- package/src/server/shape-generator.js +108 -0
- package/src/server/start.js +19 -5
- package/src/server/valkey.js +141 -235
- package/src/ws/IoInterface.js +1 -10
- package/src/ws/IoServer.js +14 -33
- package/src/ws/core/channels/core.ws.chat.js +65 -20
- package/src/ws/core/channels/core.ws.mailer.js +113 -32
- package/src/ws/core/channels/core.ws.stream.js +90 -31
- package/src/ws/core/core.ws.connection.js +12 -33
- package/src/ws/core/core.ws.emit.js +10 -26
- package/src/ws/core/core.ws.server.js +25 -58
- package/src/ws/default/channels/default.ws.main.js +53 -12
- package/src/ws/default/default.ws.connection.js +26 -13
- package/src/ws/default/default.ws.server.js +30 -12
- package/tsconfig.docs.json +15 -0
- package/typedoc.dd-cyberia.json +29 -0
- package/typedoc.json +29 -0
- package/WHITE-PAPER.md +0 -1540
- package/hardhat/README.md +0 -531
- package/hardhat/WHITE-PAPER.md +0 -1540
- package/jsdoc.dd-cyberia.json +0 -59
- package/jsdoc.json +0 -59
- package/src/api/object-layer/README.md +0 -347
- package/src/client/components/core/ColorPalette.js +0 -5267
- package/src/client/components/core/JoyStick.js +0 -80
- package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
- package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
- package/src/client/components/cryptokoyn/RoutesCryptokoyn.js +0 -39
- package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +0 -58
- package/src/client/components/cyberia-portal/ServerCyberiaPortal.js +0 -136
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/client/components/default/RoutesDefault.js +0 -49
- package/src/client/components/itemledger/CommonItemledger.js +0 -29
- package/src/client/components/itemledger/ElementsItemledger.js +0 -38
- package/src/client/components/itemledger/RoutesItemledger.js +0 -40
- package/src/client/components/underpost/CommonUnderpost.js +0 -29
- package/src/client/components/underpost/ElementsUnderpost.js +0 -38
- package/src/client/components/underpost/RoutesUnderpost.js +0 -47
- package/src/client/sw/default.sw.js +0 -127
- package/src/client/sw/template.sw.js +0 -84
- package/src/ws/core/management/core.ws.chat.js +0 -8
- package/src/ws/core/management/core.ws.mailer.js +0 -16
- package/src/ws/core/management/core.ws.stream.js +0 -8
- package/src/ws/default/management/default.ws.main.js +0 -8
package/src/cli/fs.js
CHANGED
|
@@ -75,6 +75,7 @@ class UnderpostFileStorage {
|
|
|
75
75
|
* @param {boolean} [options.force=false] - Flag to force file operations.
|
|
76
76
|
* @param {boolean} [options.pull=false] - Flag to pull files from storage.
|
|
77
77
|
* @param {boolean} [options.git=false] - Flag to use Git for file operations.
|
|
78
|
+
* @param {boolean} [options.omitUnzip=false] - If true, do not extract zip and keep downloaded zip file.
|
|
78
79
|
* @param {string} [options.storageFilePath=''] - The path to the storage configuration file.
|
|
79
80
|
* @returns {Promise<void>} A promise that resolves when the recursive callback is complete.
|
|
80
81
|
* @memberof UnderpostFileStorage
|
|
@@ -88,10 +89,50 @@ class UnderpostFileStorage {
|
|
|
88
89
|
force: false,
|
|
89
90
|
pull: false,
|
|
90
91
|
git: false,
|
|
92
|
+
omitUnzip: false,
|
|
91
93
|
storageFilePath: '',
|
|
92
94
|
},
|
|
93
95
|
) {
|
|
94
96
|
const { storage, storageConf } = Underpost.fs.getStorageConf(options);
|
|
97
|
+
|
|
98
|
+
// In recursive remove mode, delete every tracked storage key under the requested path,
|
|
99
|
+
// even when local files/directories are already missing.
|
|
100
|
+
if (options.rm === true) {
|
|
101
|
+
const normalizedPath = typeof path === 'string' ? path.trim() : '';
|
|
102
|
+
const basePath = normalizedPath.replace(/\/+$/, '');
|
|
103
|
+
const hasPathFilter = basePath.length > 0;
|
|
104
|
+
|
|
105
|
+
const associatedPaths = Object.keys(storage || {}).filter((storedPath) => {
|
|
106
|
+
if (!hasPathFilter) return true;
|
|
107
|
+
return storedPath === basePath || storedPath.startsWith(`${basePath}/`);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
for (const associatedPath of associatedPaths) {
|
|
111
|
+
await Underpost.fs.delete(associatedPath);
|
|
112
|
+
if (storage) delete storage[associatedPath];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (hasPathFilter && options.force === true && fs.existsSync(basePath)) fs.removeSync(basePath);
|
|
116
|
+
|
|
117
|
+
Underpost.fs.writeStorageConf(storage, storageConf);
|
|
118
|
+
|
|
119
|
+
if (associatedPaths.length === 0)
|
|
120
|
+
logger.warn('No associated tracked storage paths found', { path: hasPathFilter ? basePath : '*' });
|
|
121
|
+
else
|
|
122
|
+
logger.info('Removed associated tracked storage paths', {
|
|
123
|
+
path: hasPathFilter ? basePath : '*',
|
|
124
|
+
removed: associatedPaths.length,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (options.git === true) {
|
|
128
|
+
const gitPath = hasPathFilter ? basePath : '.';
|
|
129
|
+
shellExec(`cd ${gitPath} && git add .`);
|
|
130
|
+
shellExec(`underpost cmt ${gitPath} feat`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
95
136
|
const deleteFiles = options.pull === true ? [] : Underpost.repo.getDeleteFiles(path);
|
|
96
137
|
for (const relativePath of deleteFiles) {
|
|
97
138
|
const _path = path + '/' + relativePath;
|
|
@@ -101,13 +142,20 @@ class UnderpostFileStorage {
|
|
|
101
142
|
}
|
|
102
143
|
}
|
|
103
144
|
if (options.pull === true) {
|
|
145
|
+
let pullSkipCount = 0;
|
|
104
146
|
for (const _path of Object.keys(storage)) {
|
|
105
147
|
if (!fs.existsSync(_path) || options.force === true) {
|
|
106
148
|
if (options.force === true && fs.existsSync(_path)) fs.removeSync(_path);
|
|
107
149
|
await Underpost.fs.pull(_path, options);
|
|
108
|
-
} else
|
|
150
|
+
} else pullSkipCount++;
|
|
151
|
+
}
|
|
152
|
+
if (pullSkipCount > 0) logger.warn(`Pull skipped ${pullSkipCount} files that already exist`);
|
|
153
|
+
// Only run git init/commit when the caller explicitly requests git tracking (--git flag).
|
|
154
|
+
// For bundle pulls into ./build the git step is unwanted and would error on a non-repo path.
|
|
155
|
+
if (options.git === true) {
|
|
156
|
+
Underpost.repo.initLocalRepo({ path });
|
|
157
|
+
shellExec(`cd ${path} && git add . && git commit -m "Base pull state"`);
|
|
109
158
|
}
|
|
110
|
-
shellExec(`cd ${path} && git init && git add . && git commit -m "Base pull state"`);
|
|
111
159
|
} else {
|
|
112
160
|
const files =
|
|
113
161
|
options.git === true ? Underpost.repo.getChangedFiles(path) : await fs.readdir(path, { recursive: true });
|
|
@@ -140,12 +188,13 @@ class UnderpostFileStorage {
|
|
|
140
188
|
* @param {boolean} [options.force=false] - Flag to force file operations.
|
|
141
189
|
* @param {boolean} [options.pull=false] - Flag to pull files from storage.
|
|
142
190
|
* @param {boolean} [options.git=false] - Flag to use Git for file operations.
|
|
191
|
+
* @param {boolean} [options.omitUnzip=false] - If true, do not extract zip and keep downloaded zip file.
|
|
143
192
|
* @returns {Promise<void>} A promise that resolves when the callback is complete.
|
|
144
193
|
* @memberof UnderpostFileStorage
|
|
145
194
|
*/
|
|
146
195
|
async callback(
|
|
147
196
|
path,
|
|
148
|
-
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false },
|
|
197
|
+
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false, omitUnzip: false },
|
|
149
198
|
) {
|
|
150
199
|
if (options.recursive === true || options.git === true)
|
|
151
200
|
return await Underpost.fs.recursiveCallback(path, options);
|
|
@@ -158,11 +207,13 @@ class UnderpostFileStorage {
|
|
|
158
207
|
* @description Uploads a file to Cloudinary.
|
|
159
208
|
* @param {string} path - The path to the file to upload.
|
|
160
209
|
* @param {object} [options] - An object containing options for the upload.
|
|
161
|
-
* @param {
|
|
210
|
+
* @param {string} [options.deployId=''] - The identifier for the deployment (used to locate the storage config file).
|
|
211
|
+
* @param {boolean} [options.force=false] - Flag to force file operations (overwrites existing remote asset).
|
|
162
212
|
* @param {string} [options.storageFilePath=''] - The path to the storage configuration file.
|
|
163
213
|
* @returns {Promise<object>} A promise that resolves to the upload result.
|
|
164
214
|
* @memberof UnderpostFileStorage
|
|
165
215
|
*/
|
|
216
|
+
|
|
166
217
|
async upload(
|
|
167
218
|
path,
|
|
168
219
|
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, storageFilePath: '' },
|
|
@@ -188,22 +239,45 @@ class UnderpostFileStorage {
|
|
|
188
239
|
* @method pull
|
|
189
240
|
* @description Pulls a file from Cloudinary.
|
|
190
241
|
* @param {string} path - The path to the file to pull.
|
|
242
|
+
* @param {object} [options] - Pull options.
|
|
243
|
+
* @param {boolean} [options.omitUnzip=false] - If true, do not extract zip and keep downloaded zip file.
|
|
244
|
+
* @param {boolean} [options.force=false] - If true, re-download even if the local zip already exists.
|
|
191
245
|
* @returns {Promise<void>} A promise that resolves when the file is pulled.
|
|
192
246
|
* @memberof UnderpostFileStorage
|
|
193
247
|
*/
|
|
194
|
-
async pull(path) {
|
|
248
|
+
async pull(path, options = { omitUnzip: false, force: false }) {
|
|
195
249
|
Underpost.fs.cloudinaryConfig();
|
|
196
250
|
const folder = dir.dirname(path);
|
|
197
251
|
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
252
|
+
const zipPath = `${path}.zip`;
|
|
253
|
+
|
|
254
|
+
if (options.omitUnzip === true && options.force !== true && fs.existsSync(zipPath)) {
|
|
255
|
+
logger.warn('pull skipped, zip already exists and omit-unzip is enabled', { path, zipPath });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
198
259
|
const downloadResult = await cloudinary.utils.download_archive_url({
|
|
199
260
|
public_ids: [path],
|
|
200
261
|
resource_type: 'raw',
|
|
201
262
|
});
|
|
202
263
|
logger.info('download result', downloadResult);
|
|
203
|
-
await Downloader.downloadFile(downloadResult,
|
|
204
|
-
|
|
205
|
-
|
|
264
|
+
await Downloader.downloadFile(downloadResult, zipPath);
|
|
265
|
+
|
|
266
|
+
if (options.omitUnzip === true) {
|
|
267
|
+
logger.warn('omit unzip enabled, keeping downloaded zip file', { path, zipPath });
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
path = Underpost.fs.zip2File(zipPath);
|
|
272
|
+
fs.removeSync(`${path}.zip`);
|
|
206
273
|
},
|
|
274
|
+
/**
|
|
275
|
+
* @method delete
|
|
276
|
+
* @description Deletes a file from Cloudinary by its public ID.
|
|
277
|
+
* @param {string} path - The path (public ID) of the file to delete.
|
|
278
|
+
* @returns {Promise<object>} A promise that resolves to the Cloudinary delete result.
|
|
279
|
+
* @memberof UnderpostFileStorage
|
|
280
|
+
*/
|
|
207
281
|
async delete(path) {
|
|
208
282
|
Underpost.fs.cloudinaryConfig();
|
|
209
283
|
const deleteResult = await cloudinary.api
|
package/src/cli/image.js
CHANGED
|
@@ -99,6 +99,7 @@ class UnderpostImage {
|
|
|
99
99
|
if (!path) path = '.';
|
|
100
100
|
if (!imageName) imageName = `rockylinux9-underpost:${Underpost.version}`;
|
|
101
101
|
if (!imagePath) imagePath = '.';
|
|
102
|
+
if (imageName.match('/')) imageName = imageName.split('/')[1];
|
|
102
103
|
if (!version) version = 'latest';
|
|
103
104
|
version = imageName && imageName.match(':') ? '' : `:${version}`;
|
|
104
105
|
const podManImg = `localhost/${imageName}${version}`;
|
|
@@ -178,6 +179,12 @@ class UnderpostImage {
|
|
|
178
179
|
* @memberof UnderpostImage
|
|
179
180
|
*/
|
|
180
181
|
pullDockerHubImage(options = { k3s: false, kubeadm: false, kind: false, dockerhubImage: '', version: '' }) {
|
|
182
|
+
if (options.dockerhubImage && options.dockerhubImage.startsWith('localhost')) {
|
|
183
|
+
logger.warn(`[image] pullDockerHubImage skipped — local image cannot be pulled from Docker Hub`, {
|
|
184
|
+
dockerhubImage: options.dockerhubImage,
|
|
185
|
+
});
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
181
188
|
if (options.dockerhubImage === 'underpost') {
|
|
182
189
|
options.dockerhubImage = 'underpost/underpost-engine';
|
|
183
190
|
if (!options.version) options.version = Underpost.version;
|
|
@@ -185,7 +192,42 @@ class UnderpostImage {
|
|
|
185
192
|
if (!options.version) options.version = 'latest';
|
|
186
193
|
const version = options.dockerhubImage && options.dockerhubImage.match(':') ? '' : `:${options.version}`;
|
|
187
194
|
const image = `${options.dockerhubImage}${version}`;
|
|
188
|
-
|
|
195
|
+
const targetKind = options.kind === true;
|
|
196
|
+
const targetK3s = options.k3s === true;
|
|
197
|
+
const targetKubeadm = options.kubeadm === true || (!targetKind && !targetK3s);
|
|
198
|
+
|
|
199
|
+
const requestedRepo = image.replace(/:[^/]+$/, '');
|
|
200
|
+
const requestedTag = image.match(/:([^/]+)$/)?.[1] || 'latest';
|
|
201
|
+
const normalizeRepo = (repo = '') =>
|
|
202
|
+
repo
|
|
203
|
+
.trim()
|
|
204
|
+
.replace(/^localhost\//, '')
|
|
205
|
+
.replace(/^docker\.io\//, '')
|
|
206
|
+
.replace(/^library\//, '');
|
|
207
|
+
|
|
208
|
+
const currentImages = UnderpostImage.API.list({
|
|
209
|
+
kind: targetKind,
|
|
210
|
+
kubeadm: targetKubeadm,
|
|
211
|
+
k3s: targetK3s,
|
|
212
|
+
log: false,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const existsInCluster = currentImages.some((row) => {
|
|
216
|
+
const rowImageRaw = String(row.IMAGE || row.image || '').trim();
|
|
217
|
+
if (!rowImageRaw) return false;
|
|
218
|
+
const rowImage = rowImageRaw.replace(/:[^/]+$/, '');
|
|
219
|
+
const rowTag = String(row.TAG || rowImageRaw.match(/:([^/]+)$/)?.[1] || '').trim();
|
|
220
|
+
return normalizeRepo(rowImage) === normalizeRepo(requestedRepo) && rowTag === requestedTag;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (existsInCluster) {
|
|
224
|
+
logger.info(`[image] pull skipped. Image already loaded`, {
|
|
225
|
+
image,
|
|
226
|
+
clusterType: targetKind ? 'kind' : targetK3s ? 'k3s' : 'kubeadm',
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (targetKind) {
|
|
189
231
|
shellExec(`docker pull ${image}`);
|
|
190
232
|
shellExec(`sudo kind load docker-image ${image}`);
|
|
191
233
|
} else {
|
package/src/cli/index.js
CHANGED
|
@@ -46,6 +46,9 @@ program
|
|
|
46
46
|
.option('--sync-env-port', 'Sync environment port assignments across all deploy IDs')
|
|
47
47
|
.option('--single-replica', 'Build single replica folders instead of full client')
|
|
48
48
|
.option('--build-zip', 'Create zip files of the builds')
|
|
49
|
+
.option('--split <mb>', 'Split generated zip files into parts of the specified size in MB')
|
|
50
|
+
.option('--unzip <build-prefix>', 'Extract a built client zip or split zip parts using the given build prefix')
|
|
51
|
+
.option('--merge-zip <build-prefix>', 'Merge split ZIP parts back into a single ZIP file for the given build prefix')
|
|
49
52
|
.option('--lite-build', 'Skip full build (default is full build)')
|
|
50
53
|
.option('--icons-build', 'Build icons')
|
|
51
54
|
.description('Builds client assets, single replicas, and/or syncs environment ports.')
|
|
@@ -62,6 +65,11 @@ program
|
|
|
62
65
|
.option('--build', 'Triggers the client-side application build process.')
|
|
63
66
|
.option('--underpost-quickly-install', 'Uses Underpost Quickly Install for dependency installation.')
|
|
64
67
|
.option('--skip-pull-base', 'Skips cloning repositories, uses current workspace code directly.')
|
|
68
|
+
.option('--skip-full-build', 'Skips the full client bundle build during deployment.')
|
|
69
|
+
.option(
|
|
70
|
+
'--pull-bundle',
|
|
71
|
+
'Downloads the pre-built client bundle from Cloudinary via pull-bundle before starting. Use together with --skip-full-build to skip the local build entirely.',
|
|
72
|
+
)
|
|
65
73
|
.action(Underpost.start.callback)
|
|
66
74
|
.description('Initiates application servers, build pipelines, or other defined services based on the deployment ID.');
|
|
67
75
|
|
|
@@ -87,7 +95,7 @@ program
|
|
|
87
95
|
.argument(`[commit-type]`, `The type of commit to perform. Options: ${Object.keys(commitData).join(', ')}.`)
|
|
88
96
|
.argument(`[module-tag]`, 'Optional: Sets a specific module tag for the commit.')
|
|
89
97
|
.argument(`[message]`, 'Optional: Provides an additional custom message for the commit.')
|
|
90
|
-
.option(`--log
|
|
98
|
+
.option(`--log [latest-n]`, 'Shows commit history from the specified number of latest n path commits.')
|
|
91
99
|
.option('--last-msg <latest-n>', 'Displays the last n commit message.')
|
|
92
100
|
.option('--empty', 'Allows committing with empty files.')
|
|
93
101
|
.option('--copy', 'Copies the generated commit message to the clipboard.')
|
|
@@ -108,7 +116,14 @@ program
|
|
|
108
116
|
'--changelog-no-hash',
|
|
109
117
|
'Excludes commit hashes from the generated changelog entries (used with --changelog-build).',
|
|
110
118
|
)
|
|
119
|
+
.option('--unpush', 'With --log, automatically sets range to unpushed commits ahead of remote.')
|
|
111
120
|
.option('-b', 'Shows the current Git branch name.')
|
|
121
|
+
.option('-p [branch]', 'Shows the reflog for the specified branch.')
|
|
122
|
+
.option('--bc <commit-hash>', 'Shows branches that contain the specified commit.')
|
|
123
|
+
.option(
|
|
124
|
+
'--is-remote-repo <url-repo>',
|
|
125
|
+
'Checks whether a remote Git repository URL is reachable. Prints true or false.',
|
|
126
|
+
)
|
|
112
127
|
.description('Manages commits to a GitHub repository, supporting various commit types and options.')
|
|
113
128
|
.action(Underpost.repo.commit);
|
|
114
129
|
|
|
@@ -219,6 +234,7 @@ program
|
|
|
219
234
|
.option('--ban-egress-clear', 'Clears all banned egress IP addresses.')
|
|
220
235
|
.option('--ban-both-add', 'Adds IP addresses to both banned ingress and egress lists.')
|
|
221
236
|
.option('--ban-both-remove', 'Removes IP addresses from both banned ingress and egress lists.')
|
|
237
|
+
.option('--mac', 'Prints the MAC address of the main network interface.')
|
|
222
238
|
.description('Displays the current public machine IP addresses.')
|
|
223
239
|
.action(Underpost.dns.ipDispatcher);
|
|
224
240
|
|
|
@@ -308,6 +324,9 @@ program
|
|
|
308
324
|
'Retrieves current network traffic data from resource deployments and the host machine network configuration.',
|
|
309
325
|
)
|
|
310
326
|
.option('--kubeadm', 'Enables the kubeadm context for deployment operations.')
|
|
327
|
+
.option('--k3s', 'Enables the k3s context for deployment operations.')
|
|
328
|
+
.option('--kind', 'Enables the kind context for deployment operations.')
|
|
329
|
+
.option('--git-clean', 'Runs git clean on volume mount paths before copying.')
|
|
311
330
|
.option('--etc-hosts', 'Enables the etc-hosts context for deployment operations.')
|
|
312
331
|
.option('--restore-hosts', 'Restores default `/etc/hosts` entries.')
|
|
313
332
|
.option('--disable-update-underpost-config', 'Disables updates to Underpost configuration during deployment.')
|
|
@@ -319,6 +338,14 @@ program
|
|
|
319
338
|
'Sets the local:remote port to expose when --expose is active (overrides auto-detected service port).',
|
|
320
339
|
)
|
|
321
340
|
.option('--cmd <cmd>', 'Custom initialization command for deployment (comma-separated commands).')
|
|
341
|
+
.option(
|
|
342
|
+
'--skip-full-build',
|
|
343
|
+
'Skip client bundle rebuild; container will pull pre-built bundle via pull-bundle instead.',
|
|
344
|
+
)
|
|
345
|
+
.option(
|
|
346
|
+
'--pull-bundle',
|
|
347
|
+
'Explicitly pull the pre-built client bundle from Cloudinary inside the container. Use together with --skip-full-build.',
|
|
348
|
+
)
|
|
322
349
|
.description('Manages application deployments, defaulting to deploying development pods.')
|
|
323
350
|
.action(Underpost.deploy.callback);
|
|
324
351
|
|
|
@@ -327,10 +354,14 @@ program
|
|
|
327
354
|
.argument('<platform>', `The secret management platform. Options: ${Object.keys(Underpost.secret).join(', ')}.`)
|
|
328
355
|
.option('--init', 'Initializes the secrets platform environment.')
|
|
329
356
|
.option('--create-from-file <path-env-file>', 'Creates secrets from a specified environment file.')
|
|
357
|
+
.option('--create-from-env', 'Creates secrets from container environment variables (envFrom: secretRef).')
|
|
358
|
+
.option('--global-clean', 'Removes all filesystem traces of secrets (engine-private, .env, conf cache).')
|
|
330
359
|
.option('--list', 'Lists all available secrets for the platform.')
|
|
331
360
|
.description(`Manages secrets for various platforms.`)
|
|
332
361
|
.action((...args) => {
|
|
362
|
+
if (args[1].globalClean) return Underpost.secret.globalSecretClean();
|
|
333
363
|
if (args[1].createFromFile) return Underpost.secret[args[0]].createFromEnvFile(args[1].createFromFile);
|
|
364
|
+
if (args[1].createFromEnv) return Underpost.secret[args[0]].createFromContainerEnv();
|
|
334
365
|
if (args[1].list) return Underpost.secret[args[0]].list();
|
|
335
366
|
if (args[1].init) return Underpost.secret[args[0]].init();
|
|
336
367
|
});
|
|
@@ -413,6 +444,7 @@ program
|
|
|
413
444
|
.option('--kubeadm', 'Enables the kubeadm context for database operations.')
|
|
414
445
|
.option('--kind', 'Enables the kind context for database operations.')
|
|
415
446
|
.option('--k3s', 'Enables the k3s context for database operations.')
|
|
447
|
+
.option('--repo-backup', 'Backs up repositories (git commit+push) inside deployment pods via kubectl exec.')
|
|
416
448
|
.description(
|
|
417
449
|
'Manages database operations with support for MariaDB and MongoDB, including import/export, multi-pod targeting, and Git integration.',
|
|
418
450
|
)
|
|
@@ -429,6 +461,7 @@ program
|
|
|
429
461
|
.option('--instances', 'Apply to instance data collection')
|
|
430
462
|
.option('--generate', 'Generate cluster metadata')
|
|
431
463
|
.option('--itc', 'Apply under container execution context')
|
|
464
|
+
.option('--dev', 'Sets the development cli context')
|
|
432
465
|
.description('Manages cluster metadata operations, including import and export.')
|
|
433
466
|
.action(Underpost.db.clusterMetadataBackupCallback);
|
|
434
467
|
|
|
@@ -458,7 +491,6 @@ program
|
|
|
458
491
|
'--create-job-now',
|
|
459
492
|
'After applying manifests, immediately create a Job from each CronJob (requires --apply).',
|
|
460
493
|
)
|
|
461
|
-
.option('--ssh', 'Execute backup commands via SSH on the remote node instead of locally.')
|
|
462
494
|
.description('Manages cron jobs: execute jobs directly or generate and apply K8s CronJob manifests.')
|
|
463
495
|
.action(Underpost.cron.callback);
|
|
464
496
|
|
|
@@ -470,6 +502,7 @@ program
|
|
|
470
502
|
.option('--recursive', 'Uploads files recursively from the specified path.')
|
|
471
503
|
.option('--deploy-id <deploy-id>', 'Specifies the deployment configuration ID for file operations.')
|
|
472
504
|
.option('--pull', 'Downloads the specified file.')
|
|
505
|
+
.option('--omit-unzip', 'With --pull, keeps the downloaded .zip file and skips extraction.')
|
|
473
506
|
.option('--force', 'Forces the action, overriding any warnings or conflicts.')
|
|
474
507
|
.option('--storage-file-path <storage-file-path>', 'Specifies a custom file storage path.')
|
|
475
508
|
.description('Manages file storage, defaulting to file upload operations.')
|
|
@@ -597,7 +630,7 @@ program
|
|
|
597
630
|
.option('--kubeadm', 'Sets the kubeadm cluster context for the runner execution.')
|
|
598
631
|
.option('--k3s', 'Sets the k3s cluster context for the runner execution.')
|
|
599
632
|
.option('--kind', 'Sets the kind cluster context for the runner execution.')
|
|
600
|
-
.option('--
|
|
633
|
+
.option('--git-clean', 'Runs git clean on volume mount paths before copying.')
|
|
601
634
|
.option('--deploy-id <deploy-id>', 'Sets deploy id context for the runner execution.')
|
|
602
635
|
.option('--user <user>', 'Sets user context for the runner execution.')
|
|
603
636
|
.option('--hosts <hosts>', 'Comma-separated list of hosts for the runner execution.')
|
|
@@ -640,6 +673,15 @@ program
|
|
|
640
673
|
'Format: semicolon-separated entries of "ip=hostname1,hostname2" ' +
|
|
641
674
|
'(e.g., "127.0.0.1=foo.local,bar.local;10.1.2.3=foo.remote,bar.remote").',
|
|
642
675
|
)
|
|
676
|
+
.option('--copy', 'Copies the runner output to the clipboard (supported by: generate-pass, template-deploy-local).')
|
|
677
|
+
.option(
|
|
678
|
+
'--skip-full-build',
|
|
679
|
+
'Skip client bundle rebuild; triggers pull-bundle in container startup (supported by: sync, template-deploy).',
|
|
680
|
+
)
|
|
681
|
+
.option(
|
|
682
|
+
'--pull-bundle',
|
|
683
|
+
'Explicitly download the pre-built client bundle from Cloudinary inside the container (supported by: sync, template-deploy). Use together with --skip-full-build.',
|
|
684
|
+
)
|
|
643
685
|
.description('Runs specified scripts using various runners.')
|
|
644
686
|
.action(Underpost.run.callback);
|
|
645
687
|
|
|
@@ -764,4 +806,33 @@ program
|
|
|
764
806
|
)
|
|
765
807
|
.action(Underpost.baremetal.callback);
|
|
766
808
|
|
|
809
|
+
program
|
|
810
|
+
.command('release')
|
|
811
|
+
.argument('[version]', 'The new version string to set (e.g., "3.1.4"). Defaults to current version.')
|
|
812
|
+
.option('--build', 'Builds a new version: tests template, bumps versions, rebuilds manifests and configs.')
|
|
813
|
+
.option('--deploy', 'Deploys the release: syncs secrets, commits, and pushes to remote repositories.')
|
|
814
|
+
.option(
|
|
815
|
+
'--ci-push <deploy-id>',
|
|
816
|
+
'Local equivalent of engine-*.ci.yml: builds dd-{deploy-id} and pushes to the engine-{deploy-id} repository. ' +
|
|
817
|
+
'Accepts the suffix (e.g., "cyberia"), "dd-cyberia", or "engine-cyberia".',
|
|
818
|
+
)
|
|
819
|
+
.option(
|
|
820
|
+
'--message <message>',
|
|
821
|
+
'Commit message for --ci-push or --pwa-build (defaults to last commit of the engine repository).',
|
|
822
|
+
)
|
|
823
|
+
.option(
|
|
824
|
+
'--pwa-build',
|
|
825
|
+
'Runs the pwa-microservices-template update flow: always re-clones, syncs engine sources, installs, builds, and pushes.',
|
|
826
|
+
)
|
|
827
|
+
.description('Release orchestrator for building new versions and deploying releases of the Underpost CLI.')
|
|
828
|
+
.action(async (version, options) => {
|
|
829
|
+
if (options.build) return Underpost.release.build(version, options);
|
|
830
|
+
if (options.deploy) return Underpost.release.deploy(version, options);
|
|
831
|
+
if (options.ciPush) return Underpost.release.ci(options.ciPush, options.message, options);
|
|
832
|
+
if (options.pwaBuild) return Underpost.release.pwa(options.message, options);
|
|
833
|
+
console.log(
|
|
834
|
+
'Please specify --build, --deploy, --ci-push, or --pwa-build. Use "underpost release --help" for details.',
|
|
835
|
+
);
|
|
836
|
+
});
|
|
837
|
+
|
|
767
838
|
export { program };
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubectl module providing low-level Kubernetes resource management primitives.
|
|
3
|
+
* Centralises pod querying, file transfer, and in-container execution operations
|
|
4
|
+
* that were previously scattered across db, deploy, and cluster modules.
|
|
5
|
+
* @module src/cli/kubectl.js
|
|
6
|
+
* @namespace UnderpostKubectl
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { loggerFactory } from '../server/logger.js';
|
|
10
|
+
import { shellExec } from '../server/process.js';
|
|
11
|
+
import Underpost from '../index.js';
|
|
12
|
+
|
|
13
|
+
const logger = loggerFactory(import.meta);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Redacts credentials from shell command strings before logging.
|
|
17
|
+
* Masks passwords in `-p<password>`, `--password=<password>`, and `-P <password>` patterns.
|
|
18
|
+
* @param {string} cmd - The raw command string.
|
|
19
|
+
* @returns {string} The command with credentials replaced by `***`.
|
|
20
|
+
* @memberof UnderpostKubectl
|
|
21
|
+
*/
|
|
22
|
+
const sanitizeCommand = (cmd) => {
|
|
23
|
+
if (typeof cmd !== 'string') return cmd;
|
|
24
|
+
return cmd
|
|
25
|
+
.replace(/-p['"]?[^\s'"]+/g, '-p***')
|
|
26
|
+
.replace(/--password=['"]?[^\s'"]+/g, '--password=***')
|
|
27
|
+
.replace(/-P\s+['"]?[^\s'"]+/g, '-P ***');
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @class UnderpostKubectl
|
|
32
|
+
* @description Kubernetes cluster resource management primitives.
|
|
33
|
+
* Provides a unified interface for kubectl operations: resource listing, in-pod
|
|
34
|
+
* command execution, file transfer, and pod discovery/filtering.
|
|
35
|
+
* All methods are stateless and safe to call from any other CLI module.
|
|
36
|
+
* @memberof UnderpostKubectl
|
|
37
|
+
*/
|
|
38
|
+
class UnderpostKubectl {
|
|
39
|
+
static API = {
|
|
40
|
+
/**
|
|
41
|
+
* Lists Kubernetes resources matching `deployId`, parsed into plain objects.
|
|
42
|
+
* Equivalent to `kubectl get <kindType> -o wide`, filtered by name substring.
|
|
43
|
+
* @param {string} deployId - Substring to match against resource names. Empty string returns all.
|
|
44
|
+
* @param {string} [kindType='pods'] - Resource kind: pods, deployments, svc, nodes, …
|
|
45
|
+
* @param {string} [namespace=''] - Namespace to query; empty string → --all-namespaces.
|
|
46
|
+
* @returns {Array<object>} Parsed rows keyed by column header (NAME, STATUS, NODE, …).
|
|
47
|
+
* @memberof UnderpostKubectl
|
|
48
|
+
*/
|
|
49
|
+
get(deployId, kindType = 'pods', namespace = '') {
|
|
50
|
+
const raw = shellExec(
|
|
51
|
+
`sudo kubectl get ${kindType}${namespace ? ` -n ${namespace}` : ` --all-namespaces`} -o wide`,
|
|
52
|
+
{ stdout: true, disableLog: true, silent: true },
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const heads = raw
|
|
56
|
+
.split(`\n`)[0]
|
|
57
|
+
.split(' ')
|
|
58
|
+
.filter((_r) => _r.trim());
|
|
59
|
+
|
|
60
|
+
const pods = raw
|
|
61
|
+
.split(`\n`)
|
|
62
|
+
.filter((r) => (deployId ? r.match(deployId) : r.trim() && !r.match('NAME')))
|
|
63
|
+
.map((r) => r.split(' ').filter((_r) => _r.trim()));
|
|
64
|
+
|
|
65
|
+
const result = [];
|
|
66
|
+
for (const row of pods) {
|
|
67
|
+
const pod = {};
|
|
68
|
+
let index = -1;
|
|
69
|
+
for (const head of heads) {
|
|
70
|
+
index++;
|
|
71
|
+
pod[head] = row[index];
|
|
72
|
+
}
|
|
73
|
+
result.push(pod);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Executes a kubectl command with credential-safe logging and error propagation.
|
|
80
|
+
* @param {string} command - Full kubectl command string.
|
|
81
|
+
* @param {object} [options={}] - Execution options.
|
|
82
|
+
* @param {string} [options.context=''] - Human-readable label for log messages.
|
|
83
|
+
* @returns {string} stdout output from the command.
|
|
84
|
+
* @throws {Error} Re-throws any execution error after logging.
|
|
85
|
+
* @memberof UnderpostKubectl
|
|
86
|
+
*/
|
|
87
|
+
run(command, options = {}) {
|
|
88
|
+
const { context = '' } = options;
|
|
89
|
+
try {
|
|
90
|
+
logger.info(`Executing kubectl command`, { command: sanitizeCommand(command), context });
|
|
91
|
+
return shellExec(command, { stdout: true, disableLog: true });
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logger.error(`kubectl command failed`, { command: sanitizeCommand(command), error: error.message, context });
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Runs a shell command inside a pod container via `kubectl exec`.
|
|
100
|
+
* @param {object} params
|
|
101
|
+
* @param {string} params.podName - Target pod name.
|
|
102
|
+
* @param {string} params.namespace - Pod namespace.
|
|
103
|
+
* @param {string} params.command - Shell command to run inside the container.
|
|
104
|
+
* @returns {string} stdout output from the in-pod command.
|
|
105
|
+
* @throws {Error} Re-throws any execution error after logging.
|
|
106
|
+
* @memberof UnderpostKubectl
|
|
107
|
+
*/
|
|
108
|
+
exec({ podName, namespace, command }) {
|
|
109
|
+
try {
|
|
110
|
+
const kubectlCmd = `sudo kubectl exec -n ${namespace} -i ${podName} -- sh -c "${command}"`;
|
|
111
|
+
return Underpost.kubectl.run(kubectlCmd, { context: `exec in pod ${podName}` });
|
|
112
|
+
} catch (error) {
|
|
113
|
+
logger.error('Failed to execute command in pod', {
|
|
114
|
+
podName,
|
|
115
|
+
command: sanitizeCommand(command),
|
|
116
|
+
error: error.message,
|
|
117
|
+
});
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Copies a local file into a pod via `kubectl cp`.
|
|
124
|
+
* @param {object} params
|
|
125
|
+
* @param {string} params.sourcePath - Local source path.
|
|
126
|
+
* @param {string} params.podName - Target pod name.
|
|
127
|
+
* @param {string} params.namespace - Pod namespace.
|
|
128
|
+
* @param {string} params.destPath - Destination path inside the container.
|
|
129
|
+
* @returns {boolean} `true` on success, `false` on error.
|
|
130
|
+
* @memberof UnderpostKubectl
|
|
131
|
+
*/
|
|
132
|
+
cpTo({ sourcePath, podName, namespace, destPath }) {
|
|
133
|
+
try {
|
|
134
|
+
const command = `sudo kubectl cp ${sourcePath} ${namespace}/${podName}:${destPath}`;
|
|
135
|
+
Underpost.kubectl.run(command, { context: `copy to pod ${podName}` });
|
|
136
|
+
return true;
|
|
137
|
+
} catch (error) {
|
|
138
|
+
logger.error('Failed to copy file to pod', { sourcePath, podName, destPath, error: error.message });
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Copies a file from a pod to the local filesystem via `kubectl cp`.
|
|
145
|
+
* @param {object} params
|
|
146
|
+
* @param {string} params.podName - Source pod name.
|
|
147
|
+
* @param {string} params.namespace - Pod namespace.
|
|
148
|
+
* @param {string} params.sourcePath - Source path inside the container.
|
|
149
|
+
* @param {string} params.destPath - Local destination path.
|
|
150
|
+
* @returns {boolean} `true` on success, `false` on error.
|
|
151
|
+
* @memberof UnderpostKubectl
|
|
152
|
+
*/
|
|
153
|
+
cpFrom({ podName, namespace, sourcePath, destPath }) {
|
|
154
|
+
try {
|
|
155
|
+
const command = `sudo kubectl cp ${namespace}/${podName}:${sourcePath} ${destPath}`;
|
|
156
|
+
Underpost.kubectl.run(command, { context: `copy from pod ${podName}` });
|
|
157
|
+
return true;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
logger.error('Failed to copy file from pod', { podName, sourcePath, destPath, error: error.message });
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Checks whether a file exists inside a pod container.
|
|
166
|
+
* @param {object} params
|
|
167
|
+
* @param {string} params.podName - Pod name.
|
|
168
|
+
* @param {string} params.path - Absolute path inside the container to test.
|
|
169
|
+
* @returns {boolean} `true` if the file exists.
|
|
170
|
+
* @memberof UnderpostKubectl
|
|
171
|
+
*/
|
|
172
|
+
existsFile({ podName, path }) {
|
|
173
|
+
const result = shellExec(`kubectl exec ${podName} -- test -f ${path} && echo "true" || echo "false"`, {
|
|
174
|
+
stdout: true,
|
|
175
|
+
disableLog: true,
|
|
176
|
+
silent: true,
|
|
177
|
+
}).trim();
|
|
178
|
+
return result === 'true';
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Returns a filtered list of pods from the cluster.
|
|
183
|
+
* Supports wildcard glob patterns on pod names and optional deployId substring filtering.
|
|
184
|
+
* @param {object} [criteria={}] - Filter criteria.
|
|
185
|
+
* @param {string} [criteria.deployId] - Substring to match against pod names (forwards to `get`).
|
|
186
|
+
* @param {string} [criteria.podNames] - Comma-separated glob patterns (supports `*`).
|
|
187
|
+
* @param {string} [criteria.namespace='default'] - Kubernetes namespace to query.
|
|
188
|
+
* @returns {Array<object>} Filtered pod rows from `get`.
|
|
189
|
+
* @memberof UnderpostKubectl
|
|
190
|
+
*/
|
|
191
|
+
getFilteredPods(criteria = {}) {
|
|
192
|
+
const { podNames, namespace = 'default', deployId } = criteria;
|
|
193
|
+
try {
|
|
194
|
+
let pods = Underpost.kubectl.get(deployId || '', 'pods', namespace);
|
|
195
|
+
if (podNames) {
|
|
196
|
+
const patterns = podNames.split(',').map((p) => p.trim());
|
|
197
|
+
pods = pods.filter((pod) =>
|
|
198
|
+
patterns.some((pattern) => new RegExp('^' + pattern.replace(/\*/g, '.*') + '$').test(pod.NAME)),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
logger.info(`Found ${pods.length} pod(s) matching criteria`, { criteria, podNames: pods.map((p) => p.NAME) });
|
|
202
|
+
return pods;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
logger.error('Error filtering pods', { error: error.message, criteria });
|
|
205
|
+
return [];
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export default UnderpostKubectl;
|