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/repository.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
buildReplicaId,
|
|
22
22
|
writeEnv,
|
|
23
23
|
} from '../server/conf.js';
|
|
24
|
-
import { buildClient } from '../server/client-build.js';
|
|
24
|
+
import { buildClient, unzipClientBuild, mergeClientBuildZip } from '../server/client-build.js';
|
|
25
25
|
import { DefaultConf } from '../../conf.js';
|
|
26
26
|
import Underpost from '../index.js';
|
|
27
27
|
|
|
@@ -97,6 +97,7 @@ class UnderpostRepository {
|
|
|
97
97
|
* @param {boolean} [options.cached=false] - If true, commits only staged changes.
|
|
98
98
|
* @param {number} [options.log=0] - If greater than 0, shows the last N commits with diffs.
|
|
99
99
|
* @param {boolean} [options.lastMsg=0] - If greater than 0, copies or show the last last single n commit message to clipboard.
|
|
100
|
+
* @param {boolean} [options.unpush=false] - If true with --log, automatically detects unpushed commits ahead of remote and uses that count.
|
|
100
101
|
* @param {string} [options.deployId=''] - An optional deploy ID to include in the commit message.
|
|
101
102
|
* @param {string} [options.hashes=''] - If provided with diff option, shows the diff between two hashes.
|
|
102
103
|
* @param {string} [options.extension=''] - If provided with diff option, filters the diff by this file extension.
|
|
@@ -127,11 +128,51 @@ class UnderpostRepository {
|
|
|
127
128
|
changelogBuild: false,
|
|
128
129
|
changelogMinVersion: '',
|
|
129
130
|
changelogNoHash: false,
|
|
131
|
+
unpush: false,
|
|
130
132
|
b: false,
|
|
133
|
+
p: undefined,
|
|
134
|
+
bc: '',
|
|
135
|
+
isRemoteRepo: '',
|
|
131
136
|
},
|
|
132
137
|
) {
|
|
133
138
|
if (!repoPath) repoPath = '.';
|
|
134
139
|
|
|
140
|
+
if (options.isRemoteRepo) {
|
|
141
|
+
const accessible = Underpost.repo.isRemoteRepo(options.isRemoteRepo);
|
|
142
|
+
console.log(accessible);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (options.bc) {
|
|
147
|
+
console.log(
|
|
148
|
+
shellExec(`cd ${repoPath} && git for-each-ref --contains ${options.bc} --format='%(refname:short)'`, {
|
|
149
|
+
stdout: true,
|
|
150
|
+
silent: true,
|
|
151
|
+
disableLog: true,
|
|
152
|
+
}).trim(),
|
|
153
|
+
);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (options.p !== undefined) {
|
|
158
|
+
const branch =
|
|
159
|
+
options.p === true
|
|
160
|
+
? shellExec(`cd ${repoPath} && git branch --show-current`, {
|
|
161
|
+
stdout: true,
|
|
162
|
+
silent: true,
|
|
163
|
+
disableLog: true,
|
|
164
|
+
}).trim()
|
|
165
|
+
: options.p;
|
|
166
|
+
console.log(
|
|
167
|
+
shellExec(`cd ${repoPath} && git --no-pager reflog show refs/heads/${branch}`, {
|
|
168
|
+
stdout: true,
|
|
169
|
+
silent: true,
|
|
170
|
+
disableLog: true,
|
|
171
|
+
}).trim(),
|
|
172
|
+
);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
135
176
|
if (options.b) {
|
|
136
177
|
const currentBranch = shellExec(`cd ${repoPath} && git branch --show-current`, {
|
|
137
178
|
stdout: true,
|
|
@@ -304,17 +345,25 @@ class UnderpostRepository {
|
|
|
304
345
|
else console.log('Diff command:', _diffCmd);
|
|
305
346
|
return;
|
|
306
347
|
}
|
|
307
|
-
if (options.log) {
|
|
308
|
-
|
|
348
|
+
if (options.log || options.unpush) {
|
|
349
|
+
if (options.unpush) {
|
|
350
|
+
const { count, hasUnpushed } = Underpost.repo.getUnpushedCount(repoPath);
|
|
351
|
+
if (!hasUnpushed) {
|
|
352
|
+
logger.warn('No unpushed commits found');
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
options.log = count;
|
|
356
|
+
}
|
|
357
|
+
const history = Underpost.repo.getHistory(options.log, repoPath);
|
|
309
358
|
const chainCmd = history
|
|
310
359
|
.reverse()
|
|
311
|
-
.map((commitData, i) => `${i === 0 ? '' : ' && '}git ${diffCmd} ${commitData.hash}`)
|
|
360
|
+
.map((commitData, i) => `${i === 0 ? '' : ' && '}git -C ${repoPath} ${diffCmd} ${commitData.hash}`)
|
|
312
361
|
.join('');
|
|
313
362
|
if (history[0]) {
|
|
314
363
|
let index = history.length;
|
|
315
364
|
for (const commit of history) {
|
|
316
365
|
console.log(
|
|
317
|
-
shellExec(`git show -s --format=%ci ${commit.hash}`, {
|
|
366
|
+
shellExec(`cd ${repoPath} && git show -s --format=%ci ${commit.hash}`, {
|
|
318
367
|
stdout: true,
|
|
319
368
|
silent: true,
|
|
320
369
|
disableLog: true,
|
|
@@ -323,7 +372,7 @@ class UnderpostRepository {
|
|
|
323
372
|
console.log(`${index}`.magenta, commit.hash.yellow, commit.message);
|
|
324
373
|
index--;
|
|
325
374
|
console.log(
|
|
326
|
-
shellExec(`git show --name-status --pretty="" ${commit.hash}`, {
|
|
375
|
+
shellExec(`cd ${repoPath} && git show --name-status --pretty="" ${commit.hash}`, {
|
|
327
376
|
stdout: true,
|
|
328
377
|
silent: true,
|
|
329
378
|
disableLog: true,
|
|
@@ -352,6 +401,7 @@ class UnderpostRepository {
|
|
|
352
401
|
|
|
353
402
|
/**
|
|
354
403
|
* Retrieves the message of the last Git commit.
|
|
404
|
+
* @param {number} [skip=0] - Number of commits to skip from HEAD (0 = most recent).
|
|
355
405
|
* @returns {string} The last commit message.
|
|
356
406
|
* @memberof UnderpostRepository
|
|
357
407
|
*/
|
|
@@ -547,14 +597,9 @@ class UnderpostRepository {
|
|
|
547
597
|
logger.info(`Created repository directory: ${repo.path}`);
|
|
548
598
|
}
|
|
549
599
|
|
|
550
|
-
// Initialize git repository
|
|
551
|
-
shellExec(`cd ${repo.path} && git init`, { disableLog: false });
|
|
552
|
-
logger.info(`Initialized git repository in: ${repo.path}`);
|
|
553
|
-
|
|
554
|
-
// Add remote origin
|
|
555
600
|
const remoteUrl = `https://${token ? `${token}@` : ''}github.com/${username}/${repo.name}.git`;
|
|
556
|
-
|
|
557
|
-
logger.info(`
|
|
601
|
+
UnderpostRepository.API.initLocalRepo({ path: repo.path, origin: remoteUrl });
|
|
602
|
+
logger.info(`Initialized git repository with remote: ${repo.name}`);
|
|
558
603
|
}
|
|
559
604
|
}
|
|
560
605
|
return resolve(true);
|
|
@@ -573,7 +618,8 @@ class UnderpostRepository {
|
|
|
573
618
|
fs.readFileSync(`${underpostRoot}/.dockerignore`, 'utf8'),
|
|
574
619
|
'utf8',
|
|
575
620
|
);
|
|
576
|
-
|
|
621
|
+
UnderpostRepository.API.initLocalRepo({ path: destFolder });
|
|
622
|
+
shellExec(`cd ${destFolder} && git add . && git commit -m "Base template implementation"`);
|
|
577
623
|
}
|
|
578
624
|
shellExec(`cd ${destFolder} && npm run build`);
|
|
579
625
|
shellExec(`cd ${destFolder} && npm run dev`);
|
|
@@ -597,6 +643,9 @@ class UnderpostRepository {
|
|
|
597
643
|
* @param {boolean} [options.syncEnvPort=false] - If true, syncs environment port assignments across all deploy IDs.
|
|
598
644
|
* @param {boolean} [options.singleReplica=false] - If true, builds single replica folders instead of full client.
|
|
599
645
|
* @param {boolean} [options.buildZip=false] - If true, creates zip files of the builds.
|
|
646
|
+
* @param {string|number} [options.split=''] - Optional ZIP part size in MB. When set with buildZip, writes split parts.
|
|
647
|
+
* @param {string} [options.unzip=''] - Optional build ZIP prefix to extract from ./build.
|
|
648
|
+
* @param {string} [options.mergeZip=''] - Optional build prefix to merge split ZIP parts into a single ZIP.
|
|
600
649
|
* @param {boolean} [options.liteBuild=false] - If true, skips full build (default is full build).
|
|
601
650
|
* @param {boolean} [options.iconsBuild=false] - If true, builds icons.
|
|
602
651
|
* @returns {Promise<boolean>} A promise that resolves when the build is complete.
|
|
@@ -611,71 +660,32 @@ class UnderpostRepository {
|
|
|
611
660
|
syncEnvPort: false,
|
|
612
661
|
singleReplica: false,
|
|
613
662
|
buildZip: false,
|
|
663
|
+
split: '',
|
|
664
|
+
unzip: '',
|
|
665
|
+
mergeZip: '',
|
|
614
666
|
liteBuild: false,
|
|
615
667
|
iconsBuild: false,
|
|
616
668
|
},
|
|
617
669
|
) {
|
|
618
670
|
return new Promise(async (resolve, reject) => {
|
|
619
671
|
try {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
];
|
|
628
|
-
let portOffset = 0;
|
|
629
|
-
const singleReplicaPortOffsets = {};
|
|
630
|
-
for (const deployIdObj of dataDeploy) {
|
|
631
|
-
const { deployId } = deployIdObj;
|
|
632
|
-
const baseConfPath = fs.existsSync(`./engine-private/replica/${deployId}`)
|
|
633
|
-
? `./engine-private/replica`
|
|
634
|
-
: `./engine-private/conf`;
|
|
635
|
-
|
|
636
|
-
const effectivePortOffset =
|
|
637
|
-
singleReplicaPortOffsets[deployId] !== undefined ? singleReplicaPortOffsets[deployId] : portOffset;
|
|
638
|
-
|
|
639
|
-
for (const envInstanceObj of dataEnv) {
|
|
640
|
-
const envPath = `${baseConfPath}/${deployId}/.env.${envInstanceObj.env}`;
|
|
641
|
-
const envObj = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
642
|
-
envObj.PORT = `${envInstanceObj.port + effectivePortOffset}`;
|
|
643
|
-
writeEnv(envPath, envObj);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (singleReplicaPortOffsets[deployId] !== undefined) continue;
|
|
672
|
+
if (options.mergeZip) {
|
|
673
|
+
mergeClientBuildZip({
|
|
674
|
+
buildPrefix: options.mergeZip,
|
|
675
|
+
logger,
|
|
676
|
+
});
|
|
677
|
+
return resolve(true);
|
|
678
|
+
}
|
|
647
679
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
let deferredSingleReplicaSlots = [];
|
|
654
|
-
for (const path of Object.keys(serverConf[host])) {
|
|
655
|
-
if (serverConf[host][path].singleReplica && serverConf[host][path].replicas) {
|
|
656
|
-
deferredSingleReplicaSlots.push({
|
|
657
|
-
replicas: serverConf[host][path].replicas,
|
|
658
|
-
peer: !!serverConf[host][path].peer,
|
|
659
|
-
});
|
|
660
|
-
continue;
|
|
661
|
-
}
|
|
662
|
-
portOffset++;
|
|
663
|
-
if (serverConf[host][path].peer) portOffset++;
|
|
664
|
-
}
|
|
665
|
-
for (const slot of deferredSingleReplicaSlots) {
|
|
666
|
-
for (const replica of slot.replicas) {
|
|
667
|
-
const replicaDeployId = buildReplicaId({ deployId, replica });
|
|
668
|
-
singleReplicaPortOffsets[replicaDeployId] = portOffset;
|
|
669
|
-
portOffset++;
|
|
670
|
-
if (slot.peer) portOffset++;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
680
|
+
if (options.unzip) {
|
|
681
|
+
unzipClientBuild({
|
|
682
|
+
buildPrefix: options.unzip,
|
|
683
|
+
logger,
|
|
684
|
+
});
|
|
675
685
|
return resolve(true);
|
|
676
686
|
}
|
|
677
687
|
|
|
678
|
-
// Handle singleReplica operation
|
|
688
|
+
// Handle singleReplica operation (must run before syncEnvPort to ensure replica dirs exist)
|
|
679
689
|
if (options.singleReplica) {
|
|
680
690
|
const replicaPath = path;
|
|
681
691
|
if (!deployId || !host || !replicaPath) {
|
|
@@ -741,6 +751,71 @@ class UnderpostRepository {
|
|
|
741
751
|
}
|
|
742
752
|
}
|
|
743
753
|
}
|
|
754
|
+
if (!options.syncEnvPort) return resolve(true);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Handle syncEnvPort operation
|
|
758
|
+
if (options.syncEnvPort) {
|
|
759
|
+
const dataDeploy = await getDataDeploy({ disableSyncEnvPort: true });
|
|
760
|
+
const dataEnv = [
|
|
761
|
+
{ env: 'production', port: 3000 },
|
|
762
|
+
{ env: 'development', port: 4000 },
|
|
763
|
+
{ env: 'test', port: 5000 },
|
|
764
|
+
];
|
|
765
|
+
let portOffset = 0;
|
|
766
|
+
const singleReplicaPortOffsets = {};
|
|
767
|
+
for (const deployIdObj of dataDeploy) {
|
|
768
|
+
const { deployId } = deployIdObj;
|
|
769
|
+
const baseConfPath = fs.existsSync(`./engine-private/replica/${deployId}`)
|
|
770
|
+
? `./engine-private/replica`
|
|
771
|
+
: `./engine-private/conf`;
|
|
772
|
+
|
|
773
|
+
const effectivePortOffset =
|
|
774
|
+
singleReplicaPortOffsets[deployId] !== undefined ? singleReplicaPortOffsets[deployId] : portOffset;
|
|
775
|
+
|
|
776
|
+
let skipDeploy = false;
|
|
777
|
+
for (const envInstanceObj of dataEnv) {
|
|
778
|
+
const envPath = `${baseConfPath}/${deployId}/.env.${envInstanceObj.env}`;
|
|
779
|
+
if (!fs.existsSync(envPath)) {
|
|
780
|
+
logger.warn(`Skipping ${deployId}: ${envPath} not found`);
|
|
781
|
+
skipDeploy = true;
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
const envObj = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
785
|
+
envObj.PORT = `${envInstanceObj.port + effectivePortOffset}`;
|
|
786
|
+
writeEnv(envPath, envObj);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (skipDeploy) continue;
|
|
790
|
+
if (singleReplicaPortOffsets[deployId] !== undefined) continue;
|
|
791
|
+
|
|
792
|
+
const serverConf = loadReplicas(
|
|
793
|
+
deployId,
|
|
794
|
+
loadConfServerJson(`${baseConfPath}/${deployId}/conf.server.json`),
|
|
795
|
+
);
|
|
796
|
+
for (const host of Object.keys(serverConf)) {
|
|
797
|
+
let deferredSingleReplicaSlots = [];
|
|
798
|
+
for (const path of Object.keys(serverConf[host])) {
|
|
799
|
+
if (serverConf[host][path].singleReplica && serverConf[host][path].replicas) {
|
|
800
|
+
deferredSingleReplicaSlots.push({
|
|
801
|
+
replicas: serverConf[host][path].replicas,
|
|
802
|
+
peer: !!serverConf[host][path].peer,
|
|
803
|
+
});
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
portOffset++;
|
|
807
|
+
if (serverConf[host][path].peer) portOffset++;
|
|
808
|
+
}
|
|
809
|
+
for (const slot of deferredSingleReplicaSlots) {
|
|
810
|
+
for (const replica of slot.replicas) {
|
|
811
|
+
const replicaDeployId = buildReplicaId({ deployId, replica });
|
|
812
|
+
singleReplicaPortOffsets[replicaDeployId] = portOffset;
|
|
813
|
+
portOffset++;
|
|
814
|
+
if (slot.peer) portOffset++;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
744
819
|
return resolve(true);
|
|
745
820
|
}
|
|
746
821
|
|
|
@@ -752,6 +827,9 @@ class UnderpostRepository {
|
|
|
752
827
|
let argPath = path ? path.split(',') : [];
|
|
753
828
|
let deployIdSingleReplicas = [];
|
|
754
829
|
let singleReplicaHosts = [];
|
|
830
|
+
const isReplicaContext = resolvedDeployId
|
|
831
|
+
? fs.existsSync(`./engine-private/replica/${resolvedDeployId}`)
|
|
832
|
+
: false;
|
|
755
833
|
const serverConf = resolvedDeployId
|
|
756
834
|
? readConfJson(resolvedDeployId, 'server', { loadReplicas: true })
|
|
757
835
|
: Config.default.server;
|
|
@@ -762,7 +840,7 @@ class UnderpostRepository {
|
|
|
762
840
|
if (argHost.length && argPath.length && (!argHost.includes(host) || !argPath.includes(path))) {
|
|
763
841
|
delete serverConf[host][path];
|
|
764
842
|
} else {
|
|
765
|
-
if (serverConf[host][path].singleReplica && serverConf[host][path].replicas) {
|
|
843
|
+
if (!isReplicaContext && serverConf[host][path].singleReplica && serverConf[host][path].replicas) {
|
|
766
844
|
singleReplicaHosts.push({ host, path });
|
|
767
845
|
deployIdSingleReplicas = deployIdSingleReplicas.concat(
|
|
768
846
|
serverConf[host][path].replicas.map((replica) =>
|
|
@@ -775,10 +853,17 @@ class UnderpostRepository {
|
|
|
775
853
|
}
|
|
776
854
|
await buildClient({
|
|
777
855
|
buildZip: options.buildZip || false,
|
|
856
|
+
split: options.split || '',
|
|
778
857
|
fullBuild: options.liteBuild ? false : true,
|
|
779
858
|
iconsBuild: options.iconsBuild || false,
|
|
780
859
|
});
|
|
781
|
-
for (const replicaDeployId of deployIdSingleReplicas)
|
|
860
|
+
for (const replicaDeployId of deployIdSingleReplicas) {
|
|
861
|
+
if (!fs.existsSync(`./engine-private/replica/${replicaDeployId}`)) {
|
|
862
|
+
logger.warn('Skip replica client build: replica folder not found', { replicaDeployId });
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
await Underpost.repo.client(replicaDeployId);
|
|
866
|
+
}
|
|
782
867
|
|
|
783
868
|
return resolve(true);
|
|
784
869
|
}
|
|
@@ -865,11 +950,12 @@ Prevent build private config repo.`,
|
|
|
865
950
|
/**
|
|
866
951
|
* Retrieves the Git commit history.
|
|
867
952
|
* @param {number} [sinceCommit=1] - The number of recent commits to retrieve.
|
|
953
|
+
* @param {string} [repoPath='.'] - The path to the repository.
|
|
868
954
|
* @returns {Array<{hash: string, message: string, files: string}>} An array of commit objects with hash, message, and files.
|
|
869
955
|
* @memberof UnderpostRepository
|
|
870
956
|
*/
|
|
871
|
-
getHistory(sinceCommit = 1) {
|
|
872
|
-
return shellExec(`git log -1 --pretty=format:"%h %s" -n ${sinceCommit}`, {
|
|
957
|
+
getHistory(sinceCommit = 1, repoPath = '.') {
|
|
958
|
+
return shellExec(`cd ${repoPath} && git log -1 --pretty=format:"%h %s" -n ${sinceCommit}`, {
|
|
873
959
|
stdout: true,
|
|
874
960
|
silent: true,
|
|
875
961
|
disableLog: true,
|
|
@@ -884,7 +970,7 @@ Prevent build private config repo.`,
|
|
|
884
970
|
})
|
|
885
971
|
.filter((line) => line.hash)
|
|
886
972
|
.map((line) => {
|
|
887
|
-
line.files = shellExec(`git show --name-status --pretty="" ${line.hash}`, {
|
|
973
|
+
line.files = shellExec(`cd ${repoPath} && git show --name-status --pretty="" ${line.hash}`, {
|
|
888
974
|
stdout: true,
|
|
889
975
|
silent: true,
|
|
890
976
|
disableLog: true,
|
|
@@ -1185,6 +1271,74 @@ Prevent build private config repo.`,
|
|
|
1185
1271
|
logger.info('Dispatched workflow', `${repo} -> ${workflowFile}`, inputs.job ? `(job: ${inputs.job})` : '');
|
|
1186
1272
|
},
|
|
1187
1273
|
|
|
1274
|
+
/**
|
|
1275
|
+
* Resolves a Git remote URL, normalizing short-form owner/repo references to full
|
|
1276
|
+
* GitHub HTTPS URLs and injecting GITHUB_TOKEN when available.
|
|
1277
|
+
* @param {string} url - The repository URL or short-form (e.g. "owner/repo" or full HTTPS URL).
|
|
1278
|
+
* @returns {string} The resolved (and optionally authenticated) HTTPS URL.
|
|
1279
|
+
* @memberof UnderpostRepository
|
|
1280
|
+
*/
|
|
1281
|
+
resolveAuthUrl(url) {
|
|
1282
|
+
if (!url) return url;
|
|
1283
|
+
// Normalize short form "owner/repo" → full GitHub HTTPS URL
|
|
1284
|
+
let normalized = url;
|
|
1285
|
+
if (!url.startsWith('http://') && !url.startsWith('https://') && !url.startsWith('git@')) {
|
|
1286
|
+
normalized = `https://github.com/${url}`;
|
|
1287
|
+
}
|
|
1288
|
+
if (process.env.GITHUB_TOKEN && normalized.startsWith('https://github.com/')) {
|
|
1289
|
+
return normalized.replace(
|
|
1290
|
+
'https://github.com/',
|
|
1291
|
+
`https://x-access-token:${process.env.GITHUB_TOKEN}@github.com/`,
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
return normalized;
|
|
1295
|
+
},
|
|
1296
|
+
/**
|
|
1297
|
+
* Checks whether a remote Git repository URL is reachable.
|
|
1298
|
+
* Uses `git ls-remote` with `|| true` so the process always exits 0.
|
|
1299
|
+
* Injects `GITHUB_TOKEN` into GitHub HTTPS URLs when available.
|
|
1300
|
+
* @param {string} url - Full HTTPS clone URL to test (e.g. "https://github.com/org/repo.git").
|
|
1301
|
+
* @returns {boolean} `true` when the remote responded with at least one ref hash.
|
|
1302
|
+
* @memberof UnderpostRepository
|
|
1303
|
+
*/
|
|
1304
|
+
isRemoteRepo(url) {
|
|
1305
|
+
if (!url) return false;
|
|
1306
|
+
const authUrl = Underpost.repo.resolveAuthUrl(url);
|
|
1307
|
+
// GIT_TERMINAL_PROMPT=0 prevents git from hanging on credential prompts inside containers.
|
|
1308
|
+
const raw = shellExec(`GIT_TERMINAL_PROMPT=0 git ls-remote "${authUrl}" HEAD 2>&1 || true`, {
|
|
1309
|
+
stdout: true,
|
|
1310
|
+
silent: true,
|
|
1311
|
+
disableLog: true,
|
|
1312
|
+
});
|
|
1313
|
+
logger.info('isRemoteRepo', { url, raw: (raw || '').slice(0, 120) });
|
|
1314
|
+
return typeof raw === 'string' && /^[0-9a-f]{40}\t/m.test(raw);
|
|
1315
|
+
},
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* Returns metadata about unpushed commits in a git repository.
|
|
1319
|
+
* Fetches from origin, then counts commits ahead of the remote branch.
|
|
1320
|
+
* @param {string} [repoPath='.'] - Path to the git repository.
|
|
1321
|
+
* @param {number} [fallback=1] - Value to return as `count` when no unpushed commits are detected.
|
|
1322
|
+
* @returns {{ count: number, branch: string, hasUnpushed: boolean }} Unpush metadata.
|
|
1323
|
+
* @memberof UnderpostRepository
|
|
1324
|
+
*/
|
|
1325
|
+
getUnpushedCount(repoPath = '.', fallback = 1) {
|
|
1326
|
+
const branch = shellExec(`cd ${repoPath} && git branch --show-current`, {
|
|
1327
|
+
stdout: true,
|
|
1328
|
+
silent: true,
|
|
1329
|
+
disableLog: true,
|
|
1330
|
+
}).trim();
|
|
1331
|
+
shellExec(`cd ${repoPath} && git fetch origin 2>/dev/null`, { silent: true, disableLog: true });
|
|
1332
|
+
const raw = shellExec(`cd ${repoPath} && git rev-list --count origin/${branch}..HEAD 2>/dev/null`, {
|
|
1333
|
+
stdout: true,
|
|
1334
|
+
silent: true,
|
|
1335
|
+
disableLog: true,
|
|
1336
|
+
}).trim();
|
|
1337
|
+
const count = parseInt(raw);
|
|
1338
|
+
const hasUnpushed = !isNaN(count) && count > 0;
|
|
1339
|
+
return { count: hasUnpushed ? count : fallback, branch, hasUnpushed };
|
|
1340
|
+
},
|
|
1341
|
+
|
|
1188
1342
|
/**
|
|
1189
1343
|
* Sanitizes a markdown changelog string into a compact message format.
|
|
1190
1344
|
* Strips date headers, converts section tags to `[tag]` prefixes, removes bullet markers and special characters.
|
|
@@ -1207,6 +1361,253 @@ Prevent build private config repo.`,
|
|
|
1207
1361
|
.trim()
|
|
1208
1362
|
.replaceAll('] - ', '] ');
|
|
1209
1363
|
},
|
|
1364
|
+
/**
|
|
1365
|
+
* Initializes a git repository at the given path and configures user identity
|
|
1366
|
+
* from environment variables (`GITHUB_USERNAME` / `GITHUB_EMAIL`).
|
|
1367
|
+
* Safe to call on an already-initialized repo — only runs `git init` when
|
|
1368
|
+
* `.git` is absent and always ensures user.name / user.email are set.
|
|
1369
|
+
* @param {object} opts
|
|
1370
|
+
* @param {string} opts.path - Absolute or relative path to the repository.
|
|
1371
|
+
* @param {string} [opts.origin] - If provided, sets or updates git remote `origin`.
|
|
1372
|
+
* @memberof UnderpostRepository
|
|
1373
|
+
*/
|
|
1374
|
+
initLocalRepo({ path: repoPath, origin }) {
|
|
1375
|
+
const gitUsername = process.env.GITHUB_USERNAME || 'underpostnet';
|
|
1376
|
+
const gitEmail = process.env.GITHUB_EMAIL || `development@underpost.net`;
|
|
1377
|
+
|
|
1378
|
+
if (!fs.existsSync(`${repoPath}/.git`)) {
|
|
1379
|
+
shellExec(`cd "${repoPath}" && git init`);
|
|
1380
|
+
}
|
|
1381
|
+
shellExec(`cd "${repoPath}" && git config user.name '${gitUsername}'`);
|
|
1382
|
+
shellExec(`cd "${repoPath}" && git config user.email '${gitEmail}'`);
|
|
1383
|
+
|
|
1384
|
+
if (origin) {
|
|
1385
|
+
const currentRemote = shellExec(`cd "${repoPath}" && git remote get-url origin 2>/dev/null || true`, {
|
|
1386
|
+
stdout: true,
|
|
1387
|
+
silent: true,
|
|
1388
|
+
}).trim();
|
|
1389
|
+
if (!currentRemote) {
|
|
1390
|
+
shellExec(`cd "${repoPath}" && git remote add origin "${origin}"`);
|
|
1391
|
+
} else if (currentRemote !== origin) {
|
|
1392
|
+
shellExec(`cd "${repoPath}" && git remote set-url origin "${origin}"`);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
},
|
|
1396
|
+
/**
|
|
1397
|
+
* Manages a cron-backup Git repository: clone, pull, commit, or push.
|
|
1398
|
+
* Resolves the repository path as `../<repoName>` relative to the CWD.
|
|
1399
|
+
* Requires the `GITHUB_USERNAME` environment variable to be set.
|
|
1400
|
+
* @param {object} params
|
|
1401
|
+
* @param {string} params.repoName - Repository name (e.g. `engine-cyberia-cron-backups`).
|
|
1402
|
+
* @param {'clone'|'pull'|'commit'|'push'} params.operation - Git operation to perform.
|
|
1403
|
+
* @param {string} [params.message=''] - Commit message (used by the `commit` operation).
|
|
1404
|
+
* @param {boolean} [params.forceClone=false] - Remove existing clone before re-cloning.
|
|
1405
|
+
* @returns {boolean} `true` on success, `false` if GITHUB_USERNAME is unset or on error.
|
|
1406
|
+
* @memberof UnderpostRepository
|
|
1407
|
+
*/
|
|
1408
|
+
manageBackupRepo({ repoName, operation, message = '', forceClone = false }) {
|
|
1409
|
+
try {
|
|
1410
|
+
const username = process.env.GITHUB_USERNAME;
|
|
1411
|
+
if (!username) {
|
|
1412
|
+
logger.error('GITHUB_USERNAME environment variable not set');
|
|
1413
|
+
return false;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
const repoPath = `../${repoName}`;
|
|
1417
|
+
|
|
1418
|
+
switch (operation) {
|
|
1419
|
+
case 'clone':
|
|
1420
|
+
if (forceClone && fs.existsSync(repoPath)) {
|
|
1421
|
+
logger.info(`Force clone: removing existing repository: ${repoName}`);
|
|
1422
|
+
fs.removeSync(repoPath);
|
|
1423
|
+
}
|
|
1424
|
+
if (!fs.existsSync(repoPath)) {
|
|
1425
|
+
shellExec(`cd .. && underpost clone ${username}/${repoName}`);
|
|
1426
|
+
logger.info(`Cloned repository: ${repoName}`);
|
|
1427
|
+
}
|
|
1428
|
+
break;
|
|
1429
|
+
|
|
1430
|
+
case 'pull':
|
|
1431
|
+
if (fs.existsSync(repoPath)) {
|
|
1432
|
+
shellExec(`cd ${repoPath} && git checkout . && git clean -f -d`);
|
|
1433
|
+
shellExec(`cd ${repoPath} && underpost pull . ${username}/${repoName}`, { silent: true });
|
|
1434
|
+
logger.info(`Pulled repository: ${repoName}`);
|
|
1435
|
+
}
|
|
1436
|
+
break;
|
|
1437
|
+
|
|
1438
|
+
case 'commit':
|
|
1439
|
+
if (fs.existsSync(repoPath)) {
|
|
1440
|
+
shellExec(`cd ${repoPath} && git add .`);
|
|
1441
|
+
shellExec(`underpost cmt ${repoPath} backup '' '${message}'`);
|
|
1442
|
+
logger.info(`Committed to repository: ${repoName}`, { message });
|
|
1443
|
+
}
|
|
1444
|
+
break;
|
|
1445
|
+
|
|
1446
|
+
case 'push':
|
|
1447
|
+
if (fs.existsSync(repoPath)) {
|
|
1448
|
+
shellExec(`cd ${repoPath} && underpost push . ${username}/${repoName}`, { silent: true });
|
|
1449
|
+
logger.info(`Pushed repository: ${repoName}`);
|
|
1450
|
+
}
|
|
1451
|
+
break;
|
|
1452
|
+
|
|
1453
|
+
default:
|
|
1454
|
+
logger.warn(`Unknown git operation: ${operation}`);
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
return true;
|
|
1459
|
+
} catch (error) {
|
|
1460
|
+
logger.error(`Git operation failed`, { repoName, operation, error: error.message });
|
|
1461
|
+
return false;
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
|
|
1465
|
+
/**
|
|
1466
|
+
* Runtime-type → in-pod site-root directory resolver.
|
|
1467
|
+
* Maps each known runtime to the filesystem path where its repository lives inside the container.
|
|
1468
|
+
* @param {string} runtime - The runtime identifier (e.g. 'wp').
|
|
1469
|
+
* @param {string} host - The virtual-host name.
|
|
1470
|
+
* @returns {string|null} Absolute path inside the pod, or null if the runtime has no known mapping.
|
|
1471
|
+
* @memberof UnderpostRepository
|
|
1472
|
+
*/
|
|
1473
|
+
runtimeSiteRoot(runtime, host) {
|
|
1474
|
+
const runtimePaths = {
|
|
1475
|
+
wp: `/opt/lampp/htdocs/wp/${host}`,
|
|
1476
|
+
};
|
|
1477
|
+
return runtimePaths[runtime] || null;
|
|
1478
|
+
},
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Backs up all repositories defined in a deployment's conf.server.json by executing
|
|
1482
|
+
* git commit+push inside the running deployment pod via `kubectl exec`.
|
|
1483
|
+
*
|
|
1484
|
+
* Scans every `server[host][path]` entry for a `repository` field. For each match
|
|
1485
|
+
* the runtime-specific site root is resolved and a git backup script is executed
|
|
1486
|
+
* inside the pod. GITHUB_TOKEN and GITHUB_USERNAME are injected as ephemeral
|
|
1487
|
+
* environment variables in the exec command — never persisted to the pod filesystem.
|
|
1488
|
+
*
|
|
1489
|
+
* @param {object} opts
|
|
1490
|
+
* @param {string} opts.deployId - Deployment ID (used to read conf.server.json and find pods).
|
|
1491
|
+
* @param {string} [opts.namespace='default'] - Kubernetes namespace.
|
|
1492
|
+
* @param {string} [opts.env='production'] - Deployment environment.
|
|
1493
|
+
* @returns {void}
|
|
1494
|
+
* @memberof UnderpostRepository
|
|
1495
|
+
*/
|
|
1496
|
+
backupPodRepositories({ deployId, namespace = 'default', env = 'production' }) {
|
|
1497
|
+
const confServer = readConfJson(deployId, 'server', { resolve: true });
|
|
1498
|
+
const githubToken = process.env.GITHUB_TOKEN || '';
|
|
1499
|
+
const githubUsername = process.env.GITHUB_USERNAME || 'underpostnet';
|
|
1500
|
+
|
|
1501
|
+
if (!githubToken) {
|
|
1502
|
+
logger.warn('backupPodRepositories: GITHUB_TOKEN not available — git push will fail');
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// Resolve the active blue/green traffic colour so we target the correct pod
|
|
1506
|
+
const traffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace });
|
|
1507
|
+
if (!traffic) {
|
|
1508
|
+
logger.warn(`backupPodRepositories: could not resolve current traffic for ${deployId} — skipping`);
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// Find a running pod that matches the active traffic colour
|
|
1513
|
+
const pods = Underpost.kubectl.get(`${deployId}-${env}-${traffic}`, 'pods', namespace);
|
|
1514
|
+
const runningPod = pods.find((p) => p.STATUS === 'Running');
|
|
1515
|
+
if (!runningPod) {
|
|
1516
|
+
logger.warn(`backupPodRepositories: no running ${traffic} pod found for ${deployId} in namespace ${namespace}`);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
const podName = runningPod.NAME;
|
|
1520
|
+
|
|
1521
|
+
for (const host of Object.keys(confServer)) {
|
|
1522
|
+
for (const routePath of Object.keys(confServer[host])) {
|
|
1523
|
+
const entry = confServer[host][routePath];
|
|
1524
|
+
if (!entry.repository) continue;
|
|
1525
|
+
|
|
1526
|
+
const siteRoot = Underpost.repo.runtimeSiteRoot(entry.runtime, host);
|
|
1527
|
+
if (!siteRoot) {
|
|
1528
|
+
logger.warn(`backupPodRepositories: no site-root mapping for runtime '${entry.runtime}' (${host})`);
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
const repoName = entry.repository.split('/').pop().split('.')[0];
|
|
1533
|
+
|
|
1534
|
+
// Build the backup script — secrets are injected as env vars in the exec,
|
|
1535
|
+
// never written to filesystem. The shell process inherits them ephemerally.
|
|
1536
|
+
const backupScript = [
|
|
1537
|
+
`export GITHUB_TOKEN='${githubToken.replace(/'/g, "'\\''")}'`,
|
|
1538
|
+
`export GITHUB_USERNAME='${githubUsername.replace(/'/g, "'\\''")}'`,
|
|
1539
|
+
`git config --global --add safe.directory '${siteRoot}' 2>/dev/null || true`,
|
|
1540
|
+
`cd '${siteRoot}' && git add -A && git commit -m 'backup $(date -u +%Y-%m-%dT%H:%M:%SZ)' || true`,
|
|
1541
|
+
`cd '${siteRoot}' && underpost push . ${githubUsername}/${repoName}`,
|
|
1542
|
+
`cd /home/dd/engine && node bin secret underpost --global-clean`,
|
|
1543
|
+
].join(' && ');
|
|
1544
|
+
|
|
1545
|
+
try {
|
|
1546
|
+
logger.info(`backupPodRepositories: backing up ${host} (${entry.runtime}) in pod ${podName}`);
|
|
1547
|
+
Underpost.kubectl.exec({ podName, namespace, command: backupScript });
|
|
1548
|
+
logger.info(`backupPodRepositories: git push done for ${host}`);
|
|
1549
|
+
} catch (err) {
|
|
1550
|
+
logger.error(`backupPodRepositories: backup failed for ${host}`, err.message);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
},
|
|
1555
|
+
|
|
1556
|
+
/**
|
|
1557
|
+
* Clones the deploy-specific private repository into `./engine-private`
|
|
1558
|
+
* when it does not already exist on disk. Returns `{ ephemeral: true }`
|
|
1559
|
+
* If `./engine-private` already exists, the call is a no-op unless
|
|
1560
|
+
* `options.force` is `true`, in which case the directory is removed and
|
|
1561
|
+
* re-cloned.
|
|
1562
|
+
*
|
|
1563
|
+
* @param {string} [deployId] - Deploy ID (e.g. `dd-core`) used to derive
|
|
1564
|
+
* the repo name `engine-{component}-private`. Falls back to
|
|
1565
|
+
* `process.env.DEFAULT_DEPLOY_ID`. When neither is available the
|
|
1566
|
+
* default repo name `engine-private` is used.
|
|
1567
|
+
* @param {object} [options]
|
|
1568
|
+
* @param {boolean} [options.force=false] - Remove existing `engine-private`
|
|
1569
|
+
* and re-clone.
|
|
1570
|
+
* @memberof UnderpostRepository
|
|
1571
|
+
*/
|
|
1572
|
+
privateEngineRepoFactory(deployId, options = { force: false }) {
|
|
1573
|
+
if (fs.existsSync('./engine-private') && !options.force) return;
|
|
1574
|
+
|
|
1575
|
+
if (options.force && fs.existsSync('./engine-private')) {
|
|
1576
|
+
fs.removeSync('./engine-private');
|
|
1577
|
+
logger.info('engine-private removed (force re-clone)');
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const effectiveDeployId = deployId || process.env.DEFAULT_DEPLOY_ID;
|
|
1581
|
+
|
|
1582
|
+
const username = process.env.GITHUB_USERNAME;
|
|
1583
|
+
if (!username) {
|
|
1584
|
+
throw new Error('privateEngineRepoFactory: GITHUB_USERNAME not set');
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
const repoName = effectiveDeployId ? `engine-${effectiveDeployId.split('-')[1]}-private` : 'engine-private';
|
|
1588
|
+
logger.info(`engine-private missing — cloning ${username}/${repoName}`);
|
|
1589
|
+
shellExec(`underpost clone ${username}/${repoName}`);
|
|
1590
|
+
if (!fs.existsSync(`./${repoName}`)) {
|
|
1591
|
+
throw new Error(`privateEngineRepoFactory: clone failed for ${username}/${repoName}`);
|
|
1592
|
+
}
|
|
1593
|
+
if (repoName !== 'engine-private') shellExec(`mv ./${repoName} ./engine-private`);
|
|
1594
|
+
},
|
|
1595
|
+
|
|
1596
|
+
/**
|
|
1597
|
+
* Removes the ephemeral `engine-private/` clone created by
|
|
1598
|
+
* `privateEngineRepoFactory()`. No-op if the directory does not exist.
|
|
1599
|
+
* @memberof UnderpostRepository
|
|
1600
|
+
*/
|
|
1601
|
+
cleanupPrivateEngineRepo() {
|
|
1602
|
+
if (fs.existsSync('./engine-private')) {
|
|
1603
|
+
fs.removeSync('./engine-private');
|
|
1604
|
+
logger.info('engine-private ephemeral clone removed');
|
|
1605
|
+
}
|
|
1606
|
+
if (fs.existsSync('/home/dd/engine-private')) {
|
|
1607
|
+
fs.removeSync('/home/dd/engine-private');
|
|
1608
|
+
logger.info('engine-private in /home/dd removed');
|
|
1609
|
+
}
|
|
1610
|
+
},
|
|
1210
1611
|
};
|
|
1211
1612
|
}
|
|
1212
1613
|
|