cyberia 3.0.3 → 3.2.5
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.production → .env.example} +20 -4
- package/.github/workflows/engine-cyberia.cd.yml +43 -10
- package/.github/workflows/engine-cyberia.ci.yml +48 -26
- package/.github/workflows/ghpkg.ci.yml +5 -5
- package/.github/workflows/gitlab.ci.yml +1 -1
- package/.github/workflows/hardhat.ci.yml +82 -0
- package/.github/workflows/npmpkg.ci.yml +60 -14
- package/.github/workflows/publish.ci.yml +26 -7
- package/.github/workflows/publish.cyberia.ci.yml +5 -5
- package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -7
- package/.github/workflows/pwa-microservices-template-test.ci.yml +4 -4
- package/.github/workflows/release.cd.yml +14 -8
- package/.vscode/extensions.json +9 -8
- package/.vscode/settings.json +3 -2
- package/CHANGELOG.md +643 -1
- package/CLI-HELP.md +132 -57
- package/Dockerfile +4 -2
- package/README.md +347 -22
- package/WHITE-PAPER.md +1540 -0
- package/bin/build.js +21 -12
- package/bin/cyberia.js +2640 -106
- package/bin/deploy.js +258 -372
- package/bin/file.js +5 -1
- package/bin/index.js +2640 -106
- package/bin/vs.js +3 -3
- package/conf.js +169 -105
- package/deployment.yaml +236 -20
- package/hardhat/.env.example +31 -0
- package/hardhat/README.md +531 -0
- package/hardhat/WHITE-PAPER.md +1540 -0
- package/hardhat/contracts/ObjectLayerToken.sol +391 -0
- package/hardhat/deployments/.gitkeep +0 -0
- package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
- package/hardhat/hardhat.config.js +136 -0
- package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
- package/hardhat/networks/besu-object-layer.network.json +138 -0
- package/hardhat/package-lock.json +4323 -0
- package/hardhat/package.json +36 -0
- package/hardhat/scripts/deployObjectLayerToken.js +98 -0
- package/hardhat/test/ObjectLayerToken.js +592 -0
- 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/jsdoc.dd-cyberia.json +68 -0
- package/jsdoc.json +65 -49
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +562 -0
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +297 -0
- package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
- package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/manifests/pv-pvc-dd.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +60 -48
- package/proxy.yaml +118 -10
- package/pv-pvc.yaml +132 -0
- package/scripts/k3s-node-setup.sh +1 -1
- package/scripts/ports-ls.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +47 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +17 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
- 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 +368 -0
- package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
- package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
- package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
- package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -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 +413 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -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 +42 -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/document/document.service.js +1 -1
- package/src/api/file/file.controller.js +3 -1
- package/src/api/file/file.ref.json +18 -0
- package/src/api/file/file.service.js +28 -5
- package/src/api/ipfs/ipfs.controller.js +4 -25
- package/src/api/ipfs/ipfs.model.js +43 -34
- package/src/api/ipfs/ipfs.router.js +8 -13
- package/src/api/ipfs/ipfs.service.js +56 -104
- package/src/api/object-layer/README.md +347 -22
- package/src/api/object-layer/object-layer.controller.js +6 -2
- package/src/api/object-layer/object-layer.model.js +12 -8
- package/src/api/object-layer/object-layer.router.js +698 -42
- package/src/api/object-layer/object-layer.service.js +119 -37
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
- package/src/api/user/user.router.js +10 -5
- package/src/api/user/user.service.js +15 -14
- package/src/cli/baremetal.js +6 -10
- package/src/cli/cloud-init.js +0 -3
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +723 -857
- package/src/cli/deploy.js +215 -105
- package/src/cli/env.js +34 -5
- package/src/cli/fs.js +5 -4
- package/src/cli/image.js +0 -3
- package/src/cli/index.js +83 -15
- package/src/cli/kubectl.js +211 -0
- package/src/cli/monitor.js +5 -6
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +708 -62
- package/src/cli/run.js +371 -151
- package/src/cli/secrets.js +73 -2
- package/src/cli/ssh.js +1 -1
- package/src/cli/test.js +3 -3
- package/src/client/Cryptokoyn.index.js +3 -4
- package/src/client/CyberiaPortal.index.js +3 -4
- package/src/client/Default.index.js +3 -4
- package/src/client/Itemledger.index.js +4 -963
- package/src/client/Underpost.index.js +3 -4
- package/src/client/components/core/AgGrid.js +20 -5
- package/src/client/components/core/Alert.js +2 -2
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/Content.js +22 -3
- package/src/client/components/core/Docs.js +30 -6
- package/src/client/components/core/DropDown.js +137 -17
- package/src/client/components/core/FileExplorer.js +71 -4
- package/src/client/components/core/Input.js +1 -1
- package/src/client/components/core/Keyboard.js +2 -2
- package/src/client/components/core/LogIn.js +2 -2
- package/src/client/components/core/LogOut.js +2 -2
- package/src/client/components/core/Modal.js +20 -7
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- package/src/client/components/core/RichText.js +1 -2
- package/src/client/components/core/SocketIo.js +82 -29
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
- package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
- package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
- package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
- package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +217 -30
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -4
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +104 -9
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/LogInDefault.js +3 -3
- package/src/client/components/default/LogOutDefault.js +2 -2
- package/src/client/components/default/MenuDefault.js +5 -5
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
- package/src/client/components/itemledger/LogInItemledger.js +3 -3
- package/src/client/components/itemledger/LogOutItemledger.js +2 -2
- package/src/client/components/itemledger/MenuItemledger.js +3 -3
- package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
- package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
- package/src/client/components/underpost/CssUnderpost.js +59 -0
- package/src/client/components/underpost/LogInUnderpost.js +6 -3
- package/src/client/components/underpost/LogOutUnderpost.js +4 -2
- package/src/client/components/underpost/MenuUnderpost.js +104 -18
- package/src/client/components/underpost/RoutesUnderpost.js +2 -0
- package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
- package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
- package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
- package/src/client/public/cryptokoyn/microdata.json +85 -0
- package/src/client/public/cryptokoyn/site.webmanifest +57 -0
- package/src/client/public/cryptokoyn/sitemap +3 -3
- package/src/client/public/default/sitemap +3 -3
- package/src/client/public/itemledger/browserconfig.xml +2 -2
- package/src/client/public/itemledger/manifest.webmanifest +4 -4
- package/src/client/public/itemledger/microdata.json +71 -0
- package/src/client/public/itemledger/sitemap +3 -3
- package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
- package/src/client/public/test/sitemap +3 -3
- package/src/client/services/core/core.service.js +20 -8
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
- package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
- package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
- package/src/client/services/instance/instance.management.js +2 -2
- package/src/client/services/ipfs/ipfs.service.js +3 -23
- package/src/client/services/object-layer/object-layer.management.js +3 -3
- package/src/client/services/object-layer/object-layer.service.js +21 -0
- package/src/client/services/user/user.management.js +2 -2
- package/src/client/ssr/body/404.js +15 -11
- package/src/client/ssr/body/500.js +15 -11
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/head/PwaItemledger.js +60 -0
- package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
- package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/pages/Test.js +11 -10
- package/src/client.build.js +0 -3
- package/src/client.dev.js +0 -3
- package/src/db/DataBaseProvider.js +17 -2
- package/src/db/mariadb/MariaDB.js +14 -9
- package/src/db/mongo/MongooseDB.js +17 -1
- package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
- package/src/grpc/cyberia/README.md +326 -0
- package/src/grpc/cyberia/grpc-server.js +530 -0
- package/src/index.js +24 -1
- package/src/proxy.js +0 -3
- package/src/runtime/express/Dockerfile +4 -0
- package/src/runtime/express/Express.js +33 -10
- package/src/runtime/lampp/Dockerfile +13 -2
- package/src/runtime/lampp/Lampp.js +33 -17
- package/src/runtime/wp/Dockerfile +68 -0
- package/src/runtime/wp/Wp.js +639 -0
- package/src/server/auth.js +36 -15
- package/src/server/backup.js +39 -12
- package/src/server/besu-genesis-generator.js +1630 -0
- package/src/server/client-build-docs.js +133 -17
- package/src/server/client-build-live.js +9 -18
- package/src/server/client-build.js +229 -101
- package/src/server/client-dev-server.js +14 -13
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +391 -164
- package/src/server/cron.js +27 -24
- package/src/server/dns.js +29 -12
- package/src/server/downloader.js +0 -2
- package/src/server/ipfs-client.js +24 -1
- package/src/server/logger.js +27 -9
- package/src/server/object-layer.js +217 -103
- package/src/server/peer.js +8 -2
- package/src/server/process.js +1 -50
- package/src/server/proxy.js +4 -8
- package/src/server/runtime.js +30 -9
- package/src/server/semantic-layer-generator-floor.js +359 -0
- package/src/server/semantic-layer-generator-skin.js +1294 -0
- package/src/server/semantic-layer-generator.js +116 -555
- package/src/server/ssr.js +0 -3
- package/src/server/start.js +19 -12
- package/src/server/tls.js +0 -2
- package/src/server.js +0 -4
- 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/.env.development +0 -43
- package/.env.test +0 -43
- package/hardhat/contracts/CryptoKoyn.sol +0 -59
- package/hardhat/contracts/ItemLedger.sol +0 -73
- package/hardhat/contracts/Lock.sol +0 -34
- package/hardhat/hardhat.config.cjs +0 -45
- package/hardhat/ignition/modules/Lock.js +0 -18
- package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
- package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
- package/hardhat/scripts/deployItemledger.cjs +0 -25
- package/hardhat/test/Lock.js +0 -126
- package/hardhat/white-paper.md +0 -581
- package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
- package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
- package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/client/components/itemledger/CommonItemledger.js +0 -29
- package/src/client/components/itemledger/ElementsItemledger.js +0 -38
- package/src/client/components/underpost/CommonUnderpost.js +0 -29
- package/src/client/components/underpost/ElementsUnderpost.js +0 -38
- 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/white-paper.md +0 -581
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Provides utilities and engine logic for processing and managing Cyberia Online's object layer assets (skins, floors, weapons, etc.).
|
|
3
|
-
*
|
|
3
|
+
* Shared logic consumed by both the Cyberia CLI and the REST API service layer.
|
|
4
4
|
* @module src/server/object-layer.js
|
|
5
5
|
* @namespace CyberiaObjectLayer
|
|
6
6
|
*/
|
|
@@ -82,7 +82,7 @@ const logger = loggerFactory(import.meta);
|
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
* Engine class providing static utilities for Cyberia Online object layer asset processing,
|
|
85
|
-
* frame extraction, directory iteration, image building, and
|
|
85
|
+
* frame extraction, directory iteration, image building, and document creation logic.
|
|
86
86
|
* @class ObjectLayerEngine
|
|
87
87
|
* @memberof CyberiaObjectLayer
|
|
88
88
|
*/
|
|
@@ -374,7 +374,7 @@ export class ObjectLayerEngine {
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
// ──────────────────────────────────────────────────────────────────────────
|
|
377
|
-
//
|
|
377
|
+
// Document lifecycle methods
|
|
378
378
|
// ──────────────────────────────────────────────────────────────────────────
|
|
379
379
|
|
|
380
380
|
/**
|
|
@@ -639,11 +639,12 @@ export class ObjectLayerEngine {
|
|
|
639
639
|
|
|
640
640
|
/**
|
|
641
641
|
* Creates new ObjectLayerRenderFrames and ObjectLayer documents in MongoDB from the
|
|
642
|
-
* provided data,
|
|
642
|
+
* provided data, with cut-over consistency: all CIDs (atlas PNG, atlas metadata, data JSON)
|
|
643
|
+
* are computed and pinned to IPFS BEFORE the ObjectLayer document is created or updated in
|
|
644
|
+
* MongoDB, so the object layer is never visible in queries with empty CIDs.
|
|
643
645
|
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
* (which now includes `data.render.cid`) and persists an IPFS CID.
|
|
646
|
+
* If an existing ObjectLayer with the same `data.item.id` is found, it is atomically
|
|
647
|
+
* replaced (findByIdAndUpdate) and the old ObjectLayerRenderFrames is cleaned up.
|
|
647
648
|
*
|
|
648
649
|
* @static
|
|
649
650
|
* @param {Object} params - Parameters.
|
|
@@ -664,44 +665,95 @@ export class ObjectLayerEngine {
|
|
|
664
665
|
}) {
|
|
665
666
|
const { generateAtlas = true, atlasServiceContext = null } = createOptions;
|
|
666
667
|
|
|
667
|
-
// 1. Persist ObjectLayerRenderFrames
|
|
668
|
+
// 1. Persist ObjectLayerRenderFrames (not queried by the viewer table)
|
|
668
669
|
const objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
|
|
669
670
|
|
|
670
|
-
// 2.
|
|
671
|
+
// 2. Set up references in memory
|
|
671
672
|
objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
|
|
672
673
|
if (!objectLayerData.data.render) objectLayerData.data.render = {};
|
|
673
|
-
objectLayerData.data.render.cid =
|
|
674
|
-
objectLayerData.
|
|
674
|
+
objectLayerData.data.render.cid = '';
|
|
675
|
+
objectLayerData.data.render.metadataCid = '';
|
|
675
676
|
|
|
676
|
-
// 3.
|
|
677
|
+
// 3. Stage atlas + IPFS CIDs BEFORE creating/updating the ObjectLayer
|
|
678
|
+
if (generateAtlas && atlasServiceContext) {
|
|
679
|
+
const {
|
|
680
|
+
req,
|
|
681
|
+
res,
|
|
682
|
+
options,
|
|
683
|
+
AtlasSpriteSheetService,
|
|
684
|
+
IpfsClient: ipfsClient,
|
|
685
|
+
createPinRecord,
|
|
686
|
+
} = atlasServiceContext;
|
|
687
|
+
|
|
688
|
+
try {
|
|
689
|
+
const stagingOL = {
|
|
690
|
+
data: objectLayerData.data,
|
|
691
|
+
objectLayerRenderFramesId: objectLayerRenderFramesDoc,
|
|
692
|
+
};
|
|
693
|
+
const result = await AtlasSpriteSheetService.generate(
|
|
694
|
+
{ objectLayer: stagingOL, auth: req ? req.auth : undefined },
|
|
695
|
+
res,
|
|
696
|
+
options,
|
|
697
|
+
{ skipObjectLayerSave: true },
|
|
698
|
+
);
|
|
699
|
+
objectLayerData.data.render.cid = result.atlasCid;
|
|
700
|
+
objectLayerData.data.render.metadataCid = result.atlasMetadataCid;
|
|
701
|
+
objectLayerData.atlasSpriteSheetId = result.atlasDoc._id;
|
|
702
|
+
} catch (atlasError) {
|
|
703
|
+
logger.error('Failed to generate atlas during staging:', atlasError);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// Compute final SHA-256 (includes render CIDs)
|
|
707
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
708
|
+
|
|
709
|
+
// Pin data JSON to IPFS
|
|
710
|
+
if (ipfsClient) {
|
|
711
|
+
try {
|
|
712
|
+
const itemId = objectLayerData.data.item.id;
|
|
713
|
+
const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
|
|
714
|
+
const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayerData.data, `${itemId}_data.json`, mfsPath);
|
|
715
|
+
if (ipfsResult) {
|
|
716
|
+
objectLayerData.cid = ipfsResult.cid;
|
|
717
|
+
if (createPinRecord) {
|
|
718
|
+
await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
} catch (ipfsError) {
|
|
722
|
+
logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
} else {
|
|
726
|
+
// No atlas generation - compute SHA-256 without render CIDs
|
|
727
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// 4. Atomic create/upsert - ObjectLayer is fully populated with all CIDs
|
|
677
731
|
let objectLayer;
|
|
678
|
-
const
|
|
679
|
-
if (
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
732
|
+
const existingByItemId = await ObjectLayer.findOne({ 'data.item.id': objectLayerData.data.item.id });
|
|
733
|
+
if (existingByItemId) {
|
|
734
|
+
const oldRenderFramesId = existingByItemId.objectLayerRenderFramesId;
|
|
735
|
+
logger.info(
|
|
736
|
+
`ObjectLayer for item "${objectLayerData.data.item.id}" exists (${existingByItemId._id}), replacing atomically...`,
|
|
737
|
+
);
|
|
738
|
+
objectLayer = await ObjectLayer.findByIdAndUpdate(existingByItemId._id, objectLayerData, {
|
|
739
|
+
returnDocument: 'after',
|
|
683
740
|
}).populate('objectLayerRenderFramesId');
|
|
741
|
+
if (oldRenderFramesId && !oldRenderFramesId.equals(objectLayerRenderFramesDoc._id)) {
|
|
742
|
+
await ObjectLayerRenderFrames.findByIdAndDelete(oldRenderFramesId);
|
|
743
|
+
}
|
|
684
744
|
} else {
|
|
685
745
|
objectLayer = await (await ObjectLayer.create(objectLayerData)).populate('objectLayerRenderFramesId');
|
|
686
746
|
logger.info(`ObjectLayer created successfully with id: ${objectLayer._id}`);
|
|
687
747
|
}
|
|
688
748
|
|
|
689
|
-
// 4. Optional atlas generation + final SHA-256 / IPFS CID
|
|
690
|
-
if (generateAtlas && atlasServiceContext) {
|
|
691
|
-
objectLayer = await ObjectLayerEngine._generateAtlasAndFinalize({
|
|
692
|
-
objectLayer,
|
|
693
|
-
ObjectLayer,
|
|
694
|
-
atlasServiceContext,
|
|
695
|
-
isNew: true,
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
|
|
699
749
|
return { objectLayer, objectLayerRenderFramesDoc };
|
|
700
750
|
}
|
|
701
751
|
|
|
702
752
|
/**
|
|
703
753
|
* Updates an existing ObjectLayer and its ObjectLayerRenderFrames from the provided data,
|
|
704
|
-
*
|
|
754
|
+
* with cut-over consistency: a new ObjectLayerRenderFrames is created, then atlas and all
|
|
755
|
+
* CIDs are staged BEFORE the live ObjectLayer is touched. The live document is updated
|
|
756
|
+
* atomically via findByIdAndUpdate only after all CIDs are computed.
|
|
705
757
|
*
|
|
706
758
|
* @static
|
|
707
759
|
* @param {Object} params - Parameters.
|
|
@@ -724,49 +776,92 @@ export class ObjectLayerEngine {
|
|
|
724
776
|
}) {
|
|
725
777
|
const { generateAtlas = true, atlasServiceContext = null } = updateOptions;
|
|
726
778
|
|
|
727
|
-
// 1.
|
|
728
|
-
let objectLayerRenderFramesDoc;
|
|
779
|
+
// 1. Load existing ObjectLayer to get old references
|
|
729
780
|
const existingObjectLayer = await ObjectLayer.findById(objectLayerId);
|
|
730
|
-
if (existingObjectLayer
|
|
731
|
-
|
|
732
|
-
existingObjectLayer.objectLayerRenderFramesId,
|
|
733
|
-
objectLayerRenderFramesData,
|
|
734
|
-
{ new: true },
|
|
735
|
-
);
|
|
736
|
-
objectLayerData.objectLayerRenderFramesId = existingObjectLayer.objectLayerRenderFramesId;
|
|
737
|
-
} else {
|
|
738
|
-
objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
|
|
739
|
-
objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
|
|
781
|
+
if (!existingObjectLayer) {
|
|
782
|
+
throw new Error('ObjectLayer not found for update');
|
|
740
783
|
}
|
|
784
|
+
const oldRenderFramesId = existingObjectLayer.objectLayerRenderFramesId;
|
|
785
|
+
|
|
786
|
+
// 2. Create NEW RenderFrames (avoid mutating old doc mid-update)
|
|
787
|
+
const objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
|
|
788
|
+
objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
|
|
741
789
|
|
|
742
|
-
//
|
|
790
|
+
// 3. Set up render CIDs
|
|
743
791
|
if (!objectLayerData.data.render) objectLayerData.data.render = {};
|
|
744
|
-
objectLayerData.data.render.cid =
|
|
745
|
-
objectLayerData.
|
|
792
|
+
objectLayerData.data.render.cid = '';
|
|
793
|
+
objectLayerData.data.render.metadataCid = '';
|
|
746
794
|
|
|
747
|
-
//
|
|
795
|
+
// 4. Stage atlas + IPFS CIDs BEFORE updating the ObjectLayer
|
|
796
|
+
if (generateAtlas && atlasServiceContext) {
|
|
797
|
+
const {
|
|
798
|
+
req,
|
|
799
|
+
res,
|
|
800
|
+
options,
|
|
801
|
+
AtlasSpriteSheetService,
|
|
802
|
+
IpfsClient: ipfsClient,
|
|
803
|
+
createPinRecord,
|
|
804
|
+
} = atlasServiceContext;
|
|
805
|
+
|
|
806
|
+
try {
|
|
807
|
+
const stagingOL = {
|
|
808
|
+
data: objectLayerData.data,
|
|
809
|
+
objectLayerRenderFramesId: objectLayerRenderFramesDoc,
|
|
810
|
+
};
|
|
811
|
+
const result = await AtlasSpriteSheetService.generate(
|
|
812
|
+
{ objectLayer: stagingOL, auth: req ? req.auth : undefined },
|
|
813
|
+
res,
|
|
814
|
+
options,
|
|
815
|
+
{ skipObjectLayerSave: true },
|
|
816
|
+
);
|
|
817
|
+
objectLayerData.data.render.cid = result.atlasCid;
|
|
818
|
+
objectLayerData.data.render.metadataCid = result.atlasMetadataCid;
|
|
819
|
+
objectLayerData.atlasSpriteSheetId = result.atlasDoc._id;
|
|
820
|
+
} catch (atlasError) {
|
|
821
|
+
logger.error('Failed to generate atlas during update staging:', atlasError);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Compute final SHA-256 (includes render CIDs)
|
|
825
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
826
|
+
|
|
827
|
+
// Pin data JSON to IPFS
|
|
828
|
+
if (ipfsClient) {
|
|
829
|
+
try {
|
|
830
|
+
const itemId = objectLayerData.data.item.id;
|
|
831
|
+
const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
|
|
832
|
+
const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayerData.data, `${itemId}_data.json`, mfsPath);
|
|
833
|
+
if (ipfsResult) {
|
|
834
|
+
objectLayerData.cid = ipfsResult.cid;
|
|
835
|
+
if (createPinRecord) {
|
|
836
|
+
await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
} catch (ipfsError) {
|
|
840
|
+
logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
} else {
|
|
844
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// 5. Atomic update - ObjectLayer is fully populated with all CIDs
|
|
748
848
|
let objectLayer;
|
|
749
849
|
try {
|
|
750
850
|
objectLayer = await ObjectLayer.findByIdAndUpdate(objectLayerId, objectLayerData, {
|
|
751
|
-
|
|
851
|
+
returnDocument: 'after',
|
|
752
852
|
}).populate('objectLayerRenderFramesId');
|
|
753
853
|
if (!objectLayer) {
|
|
754
854
|
throw new Error('ObjectLayer not found for update');
|
|
755
855
|
}
|
|
756
|
-
logger.info(`ObjectLayer updated
|
|
856
|
+
logger.info(`ObjectLayer updated atomically with id: ${objectLayerId}`);
|
|
757
857
|
} catch (error) {
|
|
758
858
|
logger.error('Error updating ObjectLayer:', error);
|
|
759
859
|
throw error;
|
|
760
860
|
}
|
|
761
861
|
|
|
762
|
-
//
|
|
763
|
-
if (
|
|
764
|
-
|
|
765
|
-
objectLayer,
|
|
766
|
-
ObjectLayer,
|
|
767
|
-
atlasServiceContext,
|
|
768
|
-
isNew: false,
|
|
769
|
-
});
|
|
862
|
+
// 6. Clean up old RenderFrames
|
|
863
|
+
if (oldRenderFramesId && !oldRenderFramesId.equals(objectLayerRenderFramesDoc._id)) {
|
|
864
|
+
await ObjectLayerRenderFrames.findByIdAndDelete(oldRenderFramesId);
|
|
770
865
|
}
|
|
771
866
|
|
|
772
867
|
return { objectLayer, objectLayerRenderFramesDoc };
|
|
@@ -783,26 +878,22 @@ export class ObjectLayerEngine {
|
|
|
783
878
|
* @param {Object} params.objectLayer - The mongoose ObjectLayer document (must be populated).
|
|
784
879
|
* @param {Object} [params.ipfsClient=null] - The IpfsClient module; when `null`, IPFS pinning is skipped.
|
|
785
880
|
* @param {function} [params.createPinRecord=null] - The `createPinRecord` helper; when `null`, pin records are skipped.
|
|
786
|
-
* @param {string} [params.userId] - Authenticated user ID for IPFS pin record creation.
|
|
787
881
|
* @param {Object} [params.options] - Server options (host, path) forwarded to `createPinRecord`.
|
|
788
882
|
* @returns {Promise<Object>} The saved ObjectLayer document.
|
|
789
883
|
* @memberof CyberiaObjectLayer
|
|
790
884
|
*/
|
|
791
|
-
static async computeAndSaveFinalSha256({ objectLayer, ipfsClient = null, createPinRecord = null,
|
|
885
|
+
static async computeAndSaveFinalSha256({ objectLayer, ipfsClient = null, createPinRecord = null, options }) {
|
|
792
886
|
const finalSha256 = ObjectLayerEngine.computeSha256(objectLayer.data);
|
|
793
887
|
|
|
794
888
|
if (ipfsClient) {
|
|
795
889
|
try {
|
|
796
890
|
const itemId = objectLayer.data.item.id;
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
`${itemId}_data.json`,
|
|
800
|
-
`/object-layer/${itemId}/${itemId}_data.json`,
|
|
801
|
-
);
|
|
891
|
+
const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
|
|
892
|
+
const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayer.data, `${itemId}_data.json`, mfsPath);
|
|
802
893
|
if (ipfsResult) {
|
|
803
894
|
objectLayer.cid = ipfsResult.cid;
|
|
804
|
-
if (
|
|
805
|
-
await createPinRecord({ cid: ipfsResult.cid,
|
|
895
|
+
if (createPinRecord) {
|
|
896
|
+
await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
|
|
806
897
|
}
|
|
807
898
|
}
|
|
808
899
|
} catch (ipfsError) {
|
|
@@ -818,56 +909,72 @@ export class ObjectLayerEngine {
|
|
|
818
909
|
}
|
|
819
910
|
|
|
820
911
|
/**
|
|
821
|
-
*
|
|
912
|
+
* Resolve the canonical CID for an Object Layer item from the database.
|
|
913
|
+
*
|
|
914
|
+
* The canonical CID is the IPFS content identifier of the stable-JSON-serialised
|
|
915
|
+
* `objectLayer.data` document (produced by `fast-json-stable-stringify`). This is
|
|
916
|
+
* the CID that MUST be stored on-chain as the metadata CID so that any party can
|
|
917
|
+
* independently reproduce the hash from the same semantic payload.
|
|
918
|
+
*
|
|
919
|
+
* Resolution order:
|
|
920
|
+
* 1. If the ObjectLayer document already has a `.cid` field, use it.
|
|
921
|
+
* 2. Otherwise compute it on-the-fly via `ipfsClient.addJsonToIpfs` (pins the
|
|
922
|
+
* data to IPFS as a side-effect) and persist it back to the document.
|
|
923
|
+
* 3. If IPFS is unreachable, fall back to a local SHA-256 so the caller at
|
|
924
|
+
* least gets a content hash (prefixed with `sha256:` to distinguish it
|
|
925
|
+
* from a real IPFS CID).
|
|
926
|
+
*
|
|
822
927
|
* @static
|
|
823
|
-
* @param {Object}
|
|
824
|
-
* @param {
|
|
825
|
-
* @param {
|
|
826
|
-
* @param {Object}
|
|
827
|
-
* @param {
|
|
828
|
-
* @returns {Promise<
|
|
928
|
+
* @param {Object} params
|
|
929
|
+
* @param {string} params.itemId – human-readable item identifier.
|
|
930
|
+
* @param {import('mongoose').Model} params.ObjectLayer – Mongoose ObjectLayer model.
|
|
931
|
+
* @param {Object} [params.ipfsClient=null] – The IpfsClient module; when `null`, IPFS pinning is skipped and only SHA-256 fallback is returned.
|
|
932
|
+
* @param {Object} [params.options] – `{ host, path }` forwarded to pin helpers.
|
|
933
|
+
* @returns {Promise<{ cid: string, sha256: string, source: string }>}
|
|
829
934
|
* @memberof CyberiaObjectLayer
|
|
830
|
-
* @private
|
|
831
935
|
*/
|
|
832
|
-
static async
|
|
833
|
-
const
|
|
936
|
+
static async resolveCanonicalCid({ itemId, ObjectLayer, ipfsClient = null, options }) {
|
|
937
|
+
const objectLayer = await ObjectLayer.findOne({ 'data.item.id': itemId });
|
|
938
|
+
if (!objectLayer) {
|
|
939
|
+
throw new Error(`ObjectLayer "${itemId}" not found in database`);
|
|
940
|
+
}
|
|
834
941
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
options,
|
|
841
|
-
);
|
|
842
|
-
} catch (atlasError) {
|
|
843
|
-
logger.error(`Failed to auto-${isNew ? 'generate' : 'update'} atlas for ObjectLayer:`, atlasError);
|
|
942
|
+
const sha256 = ObjectLayerEngine.computeSha256(objectLayer.data);
|
|
943
|
+
|
|
944
|
+
// 1. Already have a canonical CID persisted
|
|
945
|
+
if (objectLayer.cid) {
|
|
946
|
+
return { cid: objectLayer.cid, sha256, source: 'db' };
|
|
844
947
|
}
|
|
845
948
|
|
|
846
|
-
//
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
949
|
+
// 2. Try to compute and persist via IPFS
|
|
950
|
+
if (ipfsClient) {
|
|
951
|
+
try {
|
|
952
|
+
const ipfsResult = await ipfsClient.addJsonToIpfs(
|
|
953
|
+
objectLayer.data,
|
|
954
|
+
`${itemId}_data.json`,
|
|
955
|
+
`/object-layer/${itemId}/${itemId}_data.json`,
|
|
956
|
+
);
|
|
957
|
+
if (ipfsResult) {
|
|
958
|
+
objectLayer.cid = ipfsResult.cid;
|
|
959
|
+
objectLayer.sha256 = sha256;
|
|
960
|
+
objectLayer.markModified('data');
|
|
961
|
+
await objectLayer.save();
|
|
962
|
+
logger.info(`Canonical CID computed and persisted for "${itemId}": ${ipfsResult.cid}`);
|
|
963
|
+
return { cid: ipfsResult.cid, sha256, source: 'ipfs' };
|
|
964
|
+
}
|
|
965
|
+
} catch (err) {
|
|
966
|
+
logger.warn(`IPFS unreachable while resolving canonical CID for "${itemId}": ${err.message}`);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
858
969
|
|
|
859
|
-
return
|
|
970
|
+
// 3. Fallback – return a sha256:-prefixed content hash
|
|
971
|
+
logger.warn(
|
|
972
|
+
`Using SHA-256 fallback for "${itemId}" (IPFS unavailable). On-chain CID will not resolve via gateway.`,
|
|
973
|
+
);
|
|
974
|
+
return { cid: `sha256:${sha256}`, sha256, source: 'sha256-fallback' };
|
|
860
975
|
}
|
|
861
976
|
}
|
|
862
977
|
|
|
863
|
-
/**
|
|
864
|
-
* Mapping of item type names to numerical IDs.
|
|
865
|
-
* @constant
|
|
866
|
-
* @type {{floor: number, skin: number, weapon: number, skill: number, coin: number}}
|
|
867
|
-
* @memberof CyberiaObjectLayer
|
|
868
|
-
*/
|
|
869
|
-
export const itemTypes = { floor: 0, skin: 1, weapon: 2, skill: 3, coin: 4 };
|
|
870
|
-
|
|
871
978
|
// ──────────────────────────────────────────────────────────────────────────
|
|
872
979
|
// Backward-compatible named exports matching the original destructured imports.
|
|
873
980
|
// ──────────────────────────────────────────────────────────────────────────
|
|
@@ -963,3 +1070,10 @@ export const computeAndSaveFinalSha256 = ObjectLayerEngine.computeAndSaveFinalSh
|
|
|
963
1070
|
* @memberof CyberiaObjectLayer
|
|
964
1071
|
*/
|
|
965
1072
|
export const writeStaticFrameAssets = ObjectLayerEngine.writeStaticFrameAssets;
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* @see {@link ObjectLayerEngine.resolveCanonicalCid}
|
|
1076
|
+
* @function resolveCanonicalCid
|
|
1077
|
+
* @memberof CyberiaObjectLayer
|
|
1078
|
+
*/
|
|
1079
|
+
export const resolveCanonicalCid = ObjectLayerEngine.resolveCanonicalCid;
|
package/src/server/peer.js
CHANGED
|
@@ -12,8 +12,6 @@ import dotenv from 'dotenv';
|
|
|
12
12
|
import { loggerFactory } from './logger.js';
|
|
13
13
|
import Underpost from '../index.js';
|
|
14
14
|
|
|
15
|
-
dotenv.config();
|
|
16
|
-
|
|
17
15
|
/**
|
|
18
16
|
* Logger instance for this module, utilizing the framework's factory.
|
|
19
17
|
* @type {function(*): void}
|
|
@@ -46,6 +44,14 @@ const logger = loggerFactory(import.meta);
|
|
|
46
44
|
*/
|
|
47
45
|
const createPeerServer = async ({ port, origins, path }) => {
|
|
48
46
|
logger.info('origins', origins);
|
|
47
|
+
|
|
48
|
+
// In development, allow the local client origin (peer runs on port+1 relative to the client)
|
|
49
|
+
if (process.env.NODE_ENV === 'development') {
|
|
50
|
+
const clientPort = port - 1;
|
|
51
|
+
const devOrigin = `http://localhost:${clientPort}`;
|
|
52
|
+
if (!origins.includes(devOrigin)) origins.push(devOrigin);
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
/** @type {import('peer').IConfig} */
|
|
50
56
|
const options = {
|
|
51
57
|
port,
|
package/src/server/process.js
CHANGED
|
@@ -8,14 +8,11 @@
|
|
|
8
8
|
// https://nodejs.org/api/process
|
|
9
9
|
|
|
10
10
|
import shell from 'shelljs';
|
|
11
|
-
import dotenv from 'dotenv';
|
|
12
11
|
import { loggerFactory } from './logger.js';
|
|
13
12
|
import clipboard from 'clipboardy';
|
|
14
13
|
import Underpost from '../index.js';
|
|
15
14
|
import { getNpmRootPath } from './conf.js';
|
|
16
15
|
|
|
17
|
-
dotenv.config();
|
|
18
|
-
|
|
19
16
|
const logger = loggerFactory(import.meta);
|
|
20
17
|
|
|
21
18
|
/**
|
|
@@ -122,52 +119,6 @@ const shellCd = (cd, options = { disableLog: false }) => {
|
|
|
122
119
|
return shell.cd(cd);
|
|
123
120
|
};
|
|
124
121
|
|
|
125
|
-
/**
|
|
126
|
-
* Opens a new GNOME terminal and executes a command.
|
|
127
|
-
* Note: This function is environment-specific (GNOME/Linux).
|
|
128
|
-
* @memberof Process
|
|
129
|
-
* @param {string} cmd - The command to execute in the new terminal.
|
|
130
|
-
* @param {Object} [options] - Options for the terminal opening.
|
|
131
|
-
* @param {boolean} [options.single=false] - If true, execute as a single session process using `setsid`.
|
|
132
|
-
* @param {string} [options.chown] - Path to change ownership to the target user.
|
|
133
|
-
* @returns {void}
|
|
134
|
-
*/
|
|
135
|
-
const openTerminal = (cmd, options = { single: false }) => {
|
|
136
|
-
// Find the graphical user's UID from /run/user (prefer non-root UID, usually 1000)
|
|
137
|
-
const IDS = shellExec(`ls -1 /run/user`, { stdout: true, silent: true })
|
|
138
|
-
.split('\n')
|
|
139
|
-
.map((v) => v.trim())
|
|
140
|
-
.filter(Boolean);
|
|
141
|
-
|
|
142
|
-
const nonRootIds = IDS.filter((id) => id !== '0');
|
|
143
|
-
const ID = nonRootIds.length > 0 ? nonRootIds[0] : IDS[0];
|
|
144
|
-
|
|
145
|
-
if (!options.chown) options.chown = `/home/dd ${getNpmRootPath()}/underpost`;
|
|
146
|
-
|
|
147
|
-
shellExec(`chown -R ${ID}:${ID} ${options.chown}`);
|
|
148
|
-
|
|
149
|
-
// Run the terminal as the graphical user and use THAT user's runtime dir/bus.
|
|
150
|
-
const confCmd = `USER_GRAPHICAL=$(getent passwd "${ID}" | cut -d: -f1); \
|
|
151
|
-
sudo -u "$USER_GRAPHICAL" env DISPLAY="$DISPLAY" \
|
|
152
|
-
XDG_RUNTIME_DIR="/run/user/${ID}" \
|
|
153
|
-
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${ID}/bus" \
|
|
154
|
-
PATH="$PATH" \
|
|
155
|
-
`;
|
|
156
|
-
|
|
157
|
-
if (options.single === true) {
|
|
158
|
-
// Run as a single session process
|
|
159
|
-
shellExec(`${confCmd} setsid gnome-terminal -- bash -ic '${cmd}; exec bash' >/dev/null 2>&1 &`, {
|
|
160
|
-
async: true,
|
|
161
|
-
});
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
// Run asynchronously and disown
|
|
165
|
-
shellExec(`${confCmd} gnome-terminal -- bash -c '${cmd}; exec bash' >/dev/null 2>&1 & disown`, {
|
|
166
|
-
async: true,
|
|
167
|
-
stdout: true,
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
|
|
171
122
|
/**
|
|
172
123
|
* Wraps a command to run it as a daemon process in a shell (keeping the process alive/terminal open).
|
|
173
124
|
* @memberof Process
|
|
@@ -198,4 +149,4 @@ function pbcopy(data) {
|
|
|
198
149
|
logger.info(`copied to clipboard`, clipboard.readSync());
|
|
199
150
|
}
|
|
200
151
|
|
|
201
|
-
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy,
|
|
152
|
+
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, getTerminalPid, daemonProcess };
|
package/src/server/proxy.js
CHANGED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
import express from 'express';
|
|
10
|
-
import dotenv from 'dotenv';
|
|
11
|
-
|
|
12
10
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
13
11
|
import { loggerFactory, loggerMiddleware } from './logger.js';
|
|
14
12
|
import { buildPortProxyRouter, buildProxyRouter, getTlsHosts, isDevProxyContext, isTlsDevProxy } from './conf.js';
|
|
@@ -17,8 +15,6 @@ import { shellExec } from './process.js';
|
|
|
17
15
|
import fs from 'fs-extra';
|
|
18
16
|
import Underpost from '../index.js';
|
|
19
17
|
|
|
20
|
-
dotenv.config();
|
|
21
|
-
|
|
22
18
|
const logger = loggerFactory(import.meta);
|
|
23
19
|
|
|
24
20
|
/**
|
|
@@ -56,11 +52,12 @@ class ProxyService {
|
|
|
56
52
|
// Proxy middleware options
|
|
57
53
|
/** @type {import('http-proxy-middleware/dist/types').Options} */
|
|
58
54
|
const options = {
|
|
55
|
+
pathFilter: proxyPath, // Use '/' as the general filter (v3 API)
|
|
59
56
|
ws: true, // Enable websocket proxying
|
|
60
57
|
target: `http://localhost:${parseInt(process.env.PORT - 1)}`, // Default target (should be overridden by router)
|
|
61
58
|
router: {},
|
|
62
59
|
// changeOrigin: true,
|
|
63
|
-
|
|
60
|
+
logger: logger,
|
|
64
61
|
xfwd: true, // Adds x-forward headers (Host, Proto, etc.)
|
|
65
62
|
onProxyReq: (proxyReq, req, res, options) => {},
|
|
66
63
|
pathRewrite: {},
|
|
@@ -74,8 +71,7 @@ class ProxyService {
|
|
|
74
71
|
devProxyContext: process.env.NODE_ENV !== 'production',
|
|
75
72
|
});
|
|
76
73
|
|
|
77
|
-
|
|
78
|
-
app.use(proxyPath, createProxyMiddleware(filter, options));
|
|
74
|
+
app.use(proxyPath, createProxyMiddleware(options));
|
|
79
75
|
|
|
80
76
|
// Determine which server to start (HTTP or HTTPS) based on port and environment
|
|
81
77
|
switch (process.env.NODE_ENV) {
|
|
@@ -115,7 +111,7 @@ class ProxyService {
|
|
|
115
111
|
break;
|
|
116
112
|
}
|
|
117
113
|
}
|
|
118
|
-
logger.info('Proxy running', { port, options });
|
|
114
|
+
logger.info('Proxy running', { port, router: options.router });
|
|
119
115
|
if (process.env.NODE_ENV === 'development')
|
|
120
116
|
logger.info(
|
|
121
117
|
Underpost.deploy.etcHostFactory(Object.keys(options.router), {
|