cyberia 3.1.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.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 +13 -8
- package/CHANGELOG.md +433 -1
- package/CLI-HELP.md +57 -7
- package/Dockerfile +4 -2
- package/README.md +347 -22
- package/bin/build.js +5 -2
- package/bin/cyberia.js +1789 -112
- package/bin/deploy.js +177 -124
- package/bin/file.js +3 -0
- package/bin/index.js +1789 -112
- package/conf.js +64 -8
- package/deployment.yaml +92 -20
- package/hardhat/hardhat.config.js +13 -13
- package/hardhat/ignition/modules/ObjectLayerToken.js +1 -1
- package/hardhat/package-lock.json +2554 -5859
- package/hardhat/package.json +13 -22
- 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/jsdoc.dd-cyberia.json +64 -55
- package/jsdoc.json +64 -55
- 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 +92 -20
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +54 -18
- 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/nodemon.json +1 -1
- package/package.json +22 -16
- package/proxy.yaml +54 -18
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +44 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +16 -0
- 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/file/file.ref.json +18 -0
- 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 +54 -102
- package/src/api/object-layer/README.md +347 -22
- package/src/api/object-layer/object-layer.router.js +30 -0
- package/src/api/object-layer/object-layer.service.js +114 -31
- package/src/api/user/user.service.js +8 -7
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +710 -827
- package/src/cli/deploy.js +151 -93
- package/src/cli/env.js +29 -0
- package/src/cli/fs.js +5 -2
- package/src/cli/index.js +48 -2
- package/src/cli/kubectl.js +211 -0
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +438 -75
- package/src/cli/run.js +195 -35
- package/src/cli/secrets.js +73 -0
- 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 +3 -4
- package/src/client/Underpost.index.js +3 -4
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/DropDown.js +137 -17
- 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 +0 -1
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- 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 +216 -30
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -3
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +40 -7
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +4 -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/LogInUnderpost.js +3 -3
- package/src/client/components/underpost/LogOutUnderpost.js +2 -2
- package/src/client/components/underpost/MenuUnderpost.js +5 -5
- package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
- 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/pages/CyberiaServerMetrics.js +1 -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/runtime/express/Dockerfile +4 -0
- package/src/runtime/express/Express.js +18 -1
- package/src/runtime/lampp/Dockerfile +13 -2
- package/src/runtime/lampp/Lampp.js +27 -4
- package/src/runtime/wp/Dockerfile +68 -0
- package/src/runtime/wp/Wp.js +639 -0
- package/src/server/auth.js +24 -1
- package/src/server/backup.js +37 -9
- package/src/server/client-build-docs.js +9 -2
- package/src/server/client-build.js +31 -31
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +24 -9
- package/src/server/cron.js +25 -23
- package/src/server/dns.js +2 -1
- package/src/server/ipfs-client.js +24 -1
- package/src/server/object-layer.js +149 -108
- package/src/server/peer.js +8 -0
- package/src/server/runtime.js +25 -1
- 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/start.js +2 -2
- 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/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
|
@@ -244,7 +244,11 @@ const unpinCid = async (cid) => {
|
|
|
244
244
|
});
|
|
245
245
|
if (!clusterRes.ok) {
|
|
246
246
|
const text = await clusterRes.text();
|
|
247
|
-
|
|
247
|
+
if (clusterRes.status === 404) {
|
|
248
|
+
logger.info(`IPFS Cluster unpin – CID already not pinned: ${cid}`);
|
|
249
|
+
} else {
|
|
250
|
+
logger.warn(`IPFS Cluster unpin failed (${clusterRes.status}): ${text}`);
|
|
251
|
+
}
|
|
248
252
|
} else {
|
|
249
253
|
logger.info(`IPFS Cluster unpin OK – CID: ${cid}`);
|
|
250
254
|
}
|
|
@@ -428,6 +432,25 @@ const IpfsClient = {
|
|
|
428
432
|
listClusterPins,
|
|
429
433
|
listKuboPins,
|
|
430
434
|
removeMfsPath,
|
|
435
|
+
/**
|
|
436
|
+
* Check whether a single CID is currently pinned on the local Kubo node.
|
|
437
|
+
* Uses the pin/ls?arg=<cid> endpoint which returns only that one pin
|
|
438
|
+
* (much cheaper than fetching the full list).
|
|
439
|
+
*
|
|
440
|
+
* @param {string} cid - IPFS Content Identifier to check.
|
|
441
|
+
* @returns {Promise<boolean>} true when the CID is pinned.
|
|
442
|
+
*/
|
|
443
|
+
isCidPinned: async (cid) => {
|
|
444
|
+
const kuboUrl = getIpfsApiUrl();
|
|
445
|
+
try {
|
|
446
|
+
const res = await fetch(`${kuboUrl}/api/v0/pin/ls?arg=${encodeURIComponent(cid)}&type=all`, { method: 'POST' });
|
|
447
|
+
if (!res.ok) return false;
|
|
448
|
+
const json = await res.json();
|
|
449
|
+
return !!(json.Keys && json.Keys[cid]);
|
|
450
|
+
} catch {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
},
|
|
431
454
|
};
|
|
432
455
|
|
|
433
456
|
export { IpfsClient };
|
|
@@ -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
|
-
|
|
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, {
|
|
682
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,27 +776,75 @@ 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
|
-
{ returnDocument: 'after' },
|
|
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 = '';
|
|
794
|
+
|
|
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);
|
|
746
826
|
|
|
747
|
-
|
|
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, {
|
|
@@ -753,20 +853,15 @@ export class ObjectLayerEngine {
|
|
|
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) {
|
|
@@ -882,58 +973,8 @@ export class ObjectLayerEngine {
|
|
|
882
973
|
);
|
|
883
974
|
return { cid: `sha256:${sha256}`, sha256, source: 'sha256-fallback' };
|
|
884
975
|
}
|
|
885
|
-
|
|
886
|
-
/**
|
|
887
|
-
* Internal helper that generates an atlas sprite sheet and then finalizes the SHA-256 / IPFS CID.
|
|
888
|
-
* @static
|
|
889
|
-
* @param {Object} params - Parameters.
|
|
890
|
-
* @param {Object} params.objectLayer - The mongoose ObjectLayer document.
|
|
891
|
-
* @param {Object} params.ObjectLayer - Mongoose ObjectLayer model (for re-reading).
|
|
892
|
-
* @param {Object} params.atlasServiceContext - Context with `{ req, res, options, AtlasSpriteSheetService, IpfsClient, createPinRecord }`.
|
|
893
|
-
* @param {boolean} params.isNew - Whether this is a newly created object layer (used for logging).
|
|
894
|
-
* @returns {Promise<Object>} The finalized ObjectLayer document.
|
|
895
|
-
* @memberof CyberiaObjectLayer
|
|
896
|
-
* @private
|
|
897
|
-
*/
|
|
898
|
-
static async _generateAtlasAndFinalize({ objectLayer, ObjectLayer, atlasServiceContext, isNew }) {
|
|
899
|
-
const { req, res, options, AtlasSpriteSheetService, IpfsClient: ipfsClient, createPinRecord } = atlasServiceContext;
|
|
900
|
-
|
|
901
|
-
// Generate atlas sprite sheet
|
|
902
|
-
try {
|
|
903
|
-
await AtlasSpriteSheetService.generate(
|
|
904
|
-
{ params: { id: objectLayer._id }, objectLayer, auth: req ? req.auth : undefined },
|
|
905
|
-
res,
|
|
906
|
-
options,
|
|
907
|
-
);
|
|
908
|
-
} catch (atlasError) {
|
|
909
|
-
logger.error(`Failed to auto-${isNew ? 'generate' : 'update'} atlas for ObjectLayer:`, atlasError);
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
// Re-read the objectLayer so data.render.cid is up-to-date
|
|
913
|
-
objectLayer = await ObjectLayer.findById(objectLayer._id).populate('objectLayerRenderFramesId');
|
|
914
|
-
|
|
915
|
-
// Compute definitive SHA-256 and IPFS CID
|
|
916
|
-
const userId = req && req.auth && req.auth.user ? req.auth.user._id : undefined;
|
|
917
|
-
objectLayer = await ObjectLayerEngine.computeAndSaveFinalSha256({
|
|
918
|
-
objectLayer,
|
|
919
|
-
ipfsClient: ipfsClient || null,
|
|
920
|
-
createPinRecord: createPinRecord || null,
|
|
921
|
-
userId,
|
|
922
|
-
options,
|
|
923
|
-
});
|
|
924
|
-
|
|
925
|
-
return objectLayer;
|
|
926
|
-
}
|
|
927
976
|
}
|
|
928
977
|
|
|
929
|
-
/**
|
|
930
|
-
* Mapping of item type names to numerical IDs.
|
|
931
|
-
* @constant
|
|
932
|
-
* @type {{floor: number, skin: number, weapon: number, skill: number, coin: number}}
|
|
933
|
-
* @memberof CyberiaObjectLayer
|
|
934
|
-
*/
|
|
935
|
-
export const itemTypes = { floor: 0, skin: 1, weapon: 2, skill: 3, coin: 4 };
|
|
936
|
-
|
|
937
978
|
// ──────────────────────────────────────────────────────────────────────────
|
|
938
979
|
// Backward-compatible named exports matching the original destructured imports.
|
|
939
980
|
// ──────────────────────────────────────────────────────────────────────────
|
package/src/server/peer.js
CHANGED
|
@@ -44,6 +44,14 @@ const logger = loggerFactory(import.meta);
|
|
|
44
44
|
*/
|
|
45
45
|
const createPeerServer = async ({ port, origins, path }) => {
|
|
46
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
|
+
|
|
47
55
|
/** @type {import('peer').IConfig} */
|
|
48
56
|
const options = {
|
|
49
57
|
port,
|
package/src/server/runtime.js
CHANGED
|
@@ -11,6 +11,7 @@ import * as promClient from 'prom-client';
|
|
|
11
11
|
import { loggerFactory } from './logger.js';
|
|
12
12
|
import { newInstance } from '../client/components/core/CommonJs.js';
|
|
13
13
|
import { Lampp } from '../runtime/lampp/Lampp.js';
|
|
14
|
+
import { WpService } from '../runtime/wp/Wp.js';
|
|
14
15
|
import { getInstanceContext, readConfJson } from './conf.js';
|
|
15
16
|
|
|
16
17
|
import ExpressService from '../runtime/express/Express.js';
|
|
@@ -71,6 +72,9 @@ const buildRuntime = async () => {
|
|
|
71
72
|
valkey,
|
|
72
73
|
apiBaseHost,
|
|
73
74
|
useLocalSsl,
|
|
75
|
+
grpc,
|
|
76
|
+
repository,
|
|
77
|
+
wp,
|
|
74
78
|
} = confServer[host][path];
|
|
75
79
|
|
|
76
80
|
// Calculate context data
|
|
@@ -116,6 +120,7 @@ const buildRuntime = async () => {
|
|
|
116
120
|
peer,
|
|
117
121
|
valkey,
|
|
118
122
|
apiBaseHost,
|
|
123
|
+
grpc,
|
|
119
124
|
redirectTarget,
|
|
120
125
|
rootHostPath,
|
|
121
126
|
confSSR,
|
|
@@ -129,7 +134,7 @@ const buildRuntime = async () => {
|
|
|
129
134
|
|
|
130
135
|
case 'lampp':
|
|
131
136
|
{
|
|
132
|
-
const { disabled } =
|
|
137
|
+
const { disabled } = Lampp.createApp({
|
|
133
138
|
port,
|
|
134
139
|
host,
|
|
135
140
|
path,
|
|
@@ -143,6 +148,25 @@ const buildRuntime = async () => {
|
|
|
143
148
|
await Underpost.start.listenPortController(Underpost.start.listenServerFactory(), port, runningData);
|
|
144
149
|
}
|
|
145
150
|
break;
|
|
151
|
+
|
|
152
|
+
case 'wp':
|
|
153
|
+
{
|
|
154
|
+
const { disabled } = WpService.createApp({
|
|
155
|
+
port,
|
|
156
|
+
host,
|
|
157
|
+
pathRoute: path,
|
|
158
|
+
repository,
|
|
159
|
+
db,
|
|
160
|
+
wp,
|
|
161
|
+
redirect,
|
|
162
|
+
redirectTarget,
|
|
163
|
+
resetRouter: currentPort === initPort,
|
|
164
|
+
});
|
|
165
|
+
if (disabled) continue;
|
|
166
|
+
await Underpost.start.listenPortController(Underpost.start.listenServerFactory(), port, runningData);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
|
|
146
170
|
default:
|
|
147
171
|
break;
|
|
148
172
|
}
|