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
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gRPC server for the Cyberia Engine data pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Runs alongside Express on a separate port (default 50051).
|
|
5
|
+
* Provides read-only RPCs for the Go game server to fetch
|
|
6
|
+
* ObjectLayers, Instances, and Maps from MongoDB.
|
|
7
|
+
*
|
|
8
|
+
* @module src/grpc/cyberia/grpc-server.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as grpc from '@grpc/grpc-js';
|
|
12
|
+
import * as protoLoader from '@grpc/proto-loader';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { DataBaseProvider } from '../../db/DataBaseProvider.js';
|
|
16
|
+
import { loggerFactory } from '../../server/logger.js';
|
|
17
|
+
import {
|
|
18
|
+
CYBERIA_INSTANCE_CONF_DEFAULTS as FALLBACK_CONFIG_DEFAULTS,
|
|
19
|
+
ENTITY_TYPE_DEFAULTS,
|
|
20
|
+
STATUS_ICONS,
|
|
21
|
+
} from '../../api/cyberia-instance-conf/cyberia-instance-conf.defaults.js';
|
|
22
|
+
import { generateFallbackWorld } from '../../api/cyberia-instance/cyberia-fallback-world.js';
|
|
23
|
+
|
|
24
|
+
const logger = loggerFactory(import.meta);
|
|
25
|
+
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = path.dirname(__filename);
|
|
28
|
+
|
|
29
|
+
const PROTO_PATH = path.resolve(__dirname, '../../../cyberia-server/proto/cyberia.proto');
|
|
30
|
+
|
|
31
|
+
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
|
|
32
|
+
keepCase: false,
|
|
33
|
+
longs: Number,
|
|
34
|
+
enums: String,
|
|
35
|
+
defaults: true,
|
|
36
|
+
oneofs: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const proto = grpc.loadPackageDefinition(packageDefinition).cyberia;
|
|
40
|
+
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
42
|
+
// Helpers
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
function getModels(dbKey) {
|
|
46
|
+
const bucket = DataBaseProvider.instance[dbKey];
|
|
47
|
+
if (!bucket || !bucket.mongoose || !bucket.mongoose.models) {
|
|
48
|
+
throw new Error(`DataBaseProvider not loaded for key "${dbKey}"`);
|
|
49
|
+
}
|
|
50
|
+
return bucket.mongoose.models;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ── Mongoose doc → protobuf message converters ───────────────────
|
|
54
|
+
|
|
55
|
+
function toObjectLayerMsg(doc) {
|
|
56
|
+
const d = doc.data || {};
|
|
57
|
+
const item = d.item || {};
|
|
58
|
+
const stats = d.stats || {};
|
|
59
|
+
const ledger = d.ledger || {};
|
|
60
|
+
const render = d.render || {};
|
|
61
|
+
const rf = doc.objectLayerRenderFramesId;
|
|
62
|
+
let frameDuration = 250;
|
|
63
|
+
let isStateless = false;
|
|
64
|
+
if (rf && typeof rf === 'object') {
|
|
65
|
+
if (rf.frame_duration != null) frameDuration = rf.frame_duration;
|
|
66
|
+
if (rf.is_stateless != null) isStateless = rf.is_stateless;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
mongoId: String(doc._id),
|
|
70
|
+
stats: {
|
|
71
|
+
effect: stats.effect || 0,
|
|
72
|
+
resistance: stats.resistance || 0,
|
|
73
|
+
agility: stats.agility || 0,
|
|
74
|
+
range: stats.range || 0,
|
|
75
|
+
intelligence: stats.intelligence || 0,
|
|
76
|
+
utility: stats.utility || 0,
|
|
77
|
+
},
|
|
78
|
+
item: {
|
|
79
|
+
id: item.id || '',
|
|
80
|
+
type: item.type || '',
|
|
81
|
+
description: item.description || '',
|
|
82
|
+
activable: !!item.activable,
|
|
83
|
+
},
|
|
84
|
+
ledger: {
|
|
85
|
+
type: ledger.type || 'OFF_CHAIN',
|
|
86
|
+
address: ledger.address || '',
|
|
87
|
+
tokenId: ledger.tokenId || '',
|
|
88
|
+
},
|
|
89
|
+
render: {
|
|
90
|
+
cid: render.cid || '',
|
|
91
|
+
metadataCid: render.metadataCid || '',
|
|
92
|
+
},
|
|
93
|
+
sha256: doc.sha256 || '',
|
|
94
|
+
cid: doc.cid || '',
|
|
95
|
+
frameDuration,
|
|
96
|
+
isStateless,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function toEntityMsg(ent) {
|
|
101
|
+
return {
|
|
102
|
+
entityType: ent.entityType || 'floor',
|
|
103
|
+
initCellX: ent.initCellX || 0,
|
|
104
|
+
initCellY: ent.initCellY || 0,
|
|
105
|
+
dimX: ent.dimX || 1,
|
|
106
|
+
dimY: ent.dimY || 1,
|
|
107
|
+
color: ent.color || '',
|
|
108
|
+
objectLayerItemIds: ent.objectLayerItemIds || [],
|
|
109
|
+
spawnRadius: ent.spawnRadius || 0,
|
|
110
|
+
aggroRange: ent.aggroRange || 0,
|
|
111
|
+
maxLife: ent.maxLife || 0,
|
|
112
|
+
lifeRegen: ent.lifeRegen || 0,
|
|
113
|
+
portalSubtype: ent.portalSubtype || '',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function toMapMsg(doc) {
|
|
118
|
+
return {
|
|
119
|
+
mongoId: String(doc._id),
|
|
120
|
+
code: doc.code || '',
|
|
121
|
+
name: doc.name || '',
|
|
122
|
+
gridX: doc.gridX || 16,
|
|
123
|
+
gridY: doc.gridY || 16,
|
|
124
|
+
cellWidth: doc.cellWidth || 32,
|
|
125
|
+
cellHeight: doc.cellHeight || 32,
|
|
126
|
+
entities: (doc.entities || []).map(toEntityMsg),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function toInstanceMsg(doc) {
|
|
131
|
+
return {
|
|
132
|
+
mongoId: String(doc._id),
|
|
133
|
+
code: doc.code || '',
|
|
134
|
+
name: doc.name || '',
|
|
135
|
+
description: doc.description || '',
|
|
136
|
+
tags: doc.tags || [],
|
|
137
|
+
mapCodes: doc.cyberiaMapCodes || [],
|
|
138
|
+
portals: (doc.portals || []).map((p) => ({
|
|
139
|
+
sourceMapCode: p.sourceMapCode || '',
|
|
140
|
+
sourceCellX: p.sourceCellX || 0,
|
|
141
|
+
sourceCellY: p.sourceCellY || 0,
|
|
142
|
+
targetMapCode: p.targetMapCode || '',
|
|
143
|
+
targetCellX: p.targetCellX || 0,
|
|
144
|
+
targetCellY: p.targetCellY || 0,
|
|
145
|
+
portalMode: p.portalMode || 'inter-portal',
|
|
146
|
+
})),
|
|
147
|
+
topologyMode: doc.topologyMode || 'hybrid',
|
|
148
|
+
seed: doc.seed || '',
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Converts a CyberiaInstanceConf Mongoose document (or plain object) into
|
|
154
|
+
* a complete InstanceConfig proto message.
|
|
155
|
+
* Any field that is null/undefined in `gc` falls back to FALLBACK_CONFIG_DEFAULTS,
|
|
156
|
+
* so partial DB documents always produce a fully playable config.
|
|
157
|
+
*/
|
|
158
|
+
function toInstanceConfig(gc) {
|
|
159
|
+
const fb = FALLBACK_CONFIG_DEFAULTS;
|
|
160
|
+
if (!gc) return buildFallbackConfig();
|
|
161
|
+
|
|
162
|
+
const colors =
|
|
163
|
+
gc.colors && gc.colors.length > 0
|
|
164
|
+
? gc.colors.map((c) => ({
|
|
165
|
+
key: c.key || '',
|
|
166
|
+
r: c.r ?? 0,
|
|
167
|
+
g: c.g ?? 0,
|
|
168
|
+
b: c.b ?? 0,
|
|
169
|
+
a: c.a ?? 255,
|
|
170
|
+
}))
|
|
171
|
+
: fb.colors.map((c) => ({ ...c }));
|
|
172
|
+
|
|
173
|
+
// Merge entity defaults: use canonical ENTITY_TYPE_DEFAULTS as base, overlay with
|
|
174
|
+
// any instance-specific overrides stored in gc.entityDefaults.
|
|
175
|
+
const gcDefaults = gc.entityDefaults && gc.entityDefaults.length > 0 ? gc.entityDefaults : [];
|
|
176
|
+
const gcDefaultsMap = Object.fromEntries(gcDefaults.map((d) => [d.entityType, d]));
|
|
177
|
+
const entityDefaults = ENTITY_TYPE_DEFAULTS.map((canonical) => {
|
|
178
|
+
const override = gcDefaultsMap[canonical.entityType] ?? {};
|
|
179
|
+
const dols = override.defaultObjectLayers ?? canonical.defaultObjectLayers ?? [];
|
|
180
|
+
return {
|
|
181
|
+
entityType: canonical.entityType,
|
|
182
|
+
liveItemIds: override.liveItemIds ?? canonical.liveItemIds,
|
|
183
|
+
deadItemIds: override.deadItemIds ?? canonical.deadItemIds,
|
|
184
|
+
colorKey: override.colorKey ?? canonical.colorKey,
|
|
185
|
+
defaultObjectLayers: dols.map((ol) => ({
|
|
186
|
+
itemId: ol.itemId || '',
|
|
187
|
+
active: !!ol.active,
|
|
188
|
+
quantity: ol.quantity || 0,
|
|
189
|
+
})),
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
cellSize: gc.cellSize ?? fb.cellSize,
|
|
195
|
+
fps: gc.fps ?? fb.fps,
|
|
196
|
+
interpolationMs: gc.interpolationMs ?? fb.interpolationMs,
|
|
197
|
+
defaultObjWidth: gc.defaultObjWidth ?? fb.defaultObjWidth,
|
|
198
|
+
defaultObjHeight: gc.defaultObjHeight ?? fb.defaultObjHeight,
|
|
199
|
+
cameraSmoothing: gc.cameraSmoothing ?? fb.cameraSmoothing,
|
|
200
|
+
cameraZoom: gc.cameraZoom ?? fb.cameraZoom,
|
|
201
|
+
defaultWidthScreenFactor: gc.defaultWidthScreenFactor ?? fb.defaultWidthScreenFactor,
|
|
202
|
+
defaultHeightScreenFactor: gc.defaultHeightScreenFactor ?? fb.defaultHeightScreenFactor,
|
|
203
|
+
devUi: gc.devUi ?? fb.devUi,
|
|
204
|
+
colors,
|
|
205
|
+
aoiRadius: gc.aoiRadius ?? fb.aoiRadius,
|
|
206
|
+
portalHoldTimeMs: gc.portalHoldTimeMs ?? fb.portalHoldTimeMs,
|
|
207
|
+
portalSpawnRadius: gc.portalSpawnRadius ?? fb.portalSpawnRadius,
|
|
208
|
+
entityBaseSpeed: gc.entityBaseSpeed ?? fb.entityBaseSpeed,
|
|
209
|
+
entityBaseMaxLife: gc.entityBaseMaxLife ?? fb.entityBaseMaxLife,
|
|
210
|
+
entityBaseActionCooldownMs: gc.entityBaseActionCooldownMs ?? fb.entityBaseActionCooldownMs,
|
|
211
|
+
entityBaseMinActionCooldownMs: gc.entityBaseMinActionCooldownMs ?? fb.entityBaseMinActionCooldownMs,
|
|
212
|
+
botAggroRange: gc.botAggroRange ?? fb.botAggroRange,
|
|
213
|
+
defaultPlayerWidth: gc.defaultPlayerWidth ?? fb.defaultPlayerWidth,
|
|
214
|
+
defaultPlayerHeight: gc.defaultPlayerHeight ?? fb.defaultPlayerHeight,
|
|
215
|
+
playerBaseLifeRegenMin: gc.playerBaseLifeRegenMin ?? fb.playerBaseLifeRegenMin,
|
|
216
|
+
playerBaseLifeRegenMax: gc.playerBaseLifeRegenMax ?? fb.playerBaseLifeRegenMax,
|
|
217
|
+
sumStatsLimit: gc.sumStatsLimit ?? fb.sumStatsLimit,
|
|
218
|
+
maxActiveLayers: gc.maxActiveLayers ?? fb.maxActiveLayers,
|
|
219
|
+
initialLifeFraction: gc.initialLifeFraction ?? fb.initialLifeFraction,
|
|
220
|
+
respawnDurationMs: gc.respawnDurationMs ?? fb.respawnDurationMs,
|
|
221
|
+
collisionLifeLoss: gc.collisionLifeLoss ?? fb.collisionLifeLoss,
|
|
222
|
+
// Economy — Fountain & Sink (nested, mirrors EconomyRules proto message).
|
|
223
|
+
economyRules: {
|
|
224
|
+
botSpawnCoins: gc.economyRules?.botSpawnCoins ?? fb.economyRules.botSpawnCoins,
|
|
225
|
+
playerSpawnCoins: gc.economyRules?.playerSpawnCoins ?? fb.economyRules.playerSpawnCoins,
|
|
226
|
+
coinKillPercentVsBot: gc.economyRules?.coinKillPercentVsBot ?? fb.economyRules.coinKillPercentVsBot,
|
|
227
|
+
coinKillPercentVsPlayer: gc.economyRules?.coinKillPercentVsPlayer ?? fb.economyRules.coinKillPercentVsPlayer,
|
|
228
|
+
coinKillMinAmount: gc.economyRules?.coinKillMinAmount ?? fb.economyRules.coinKillMinAmount,
|
|
229
|
+
respawnCostPercent: gc.economyRules?.respawnCostPercent ?? fb.economyRules.respawnCostPercent,
|
|
230
|
+
portalFee: gc.economyRules?.portalFee ?? fb.economyRules.portalFee,
|
|
231
|
+
craftingFeePercent: gc.economyRules?.craftingFeePercent ?? fb.economyRules.craftingFeePercent,
|
|
232
|
+
},
|
|
233
|
+
lifeRegenChance: gc.lifeRegenChance ?? fb.lifeRegenChance,
|
|
234
|
+
maxChance: gc.maxChance ?? fb.maxChance,
|
|
235
|
+
entityDefaults,
|
|
236
|
+
skillConfig: (gc.skillConfig || []).map((sc) => ({
|
|
237
|
+
triggerItemId: sc.triggerItemId || '',
|
|
238
|
+
logicEventIds: sc.logicEventIds || [],
|
|
239
|
+
})),
|
|
240
|
+
skillRules: {
|
|
241
|
+
projectileSpawnChance: gc.skillRules?.projectileSpawnChance ?? fb.skillRules.projectileSpawnChance,
|
|
242
|
+
projectileLifetimeMs: gc.skillRules?.projectileLifetimeMs ?? fb.skillRules.projectileLifetimeMs,
|
|
243
|
+
projectileWidth: gc.skillRules?.projectileWidth ?? fb.skillRules.projectileWidth,
|
|
244
|
+
projectileHeight: gc.skillRules?.projectileHeight ?? fb.skillRules.projectileHeight,
|
|
245
|
+
projectileSpeedMultiplier: gc.skillRules?.projectileSpeedMultiplier ?? fb.skillRules.projectileSpeedMultiplier,
|
|
246
|
+
doppelgangerSpawnChance: gc.skillRules?.doppelgangerSpawnChance ?? fb.skillRules.doppelgangerSpawnChance,
|
|
247
|
+
doppelgangerLifetimeMs: gc.skillRules?.doppelgangerLifetimeMs ?? fb.skillRules.doppelgangerLifetimeMs,
|
|
248
|
+
doppelgangerSpawnRadius: gc.skillRules?.doppelgangerSpawnRadius ?? fb.skillRules.doppelgangerSpawnRadius,
|
|
249
|
+
doppelgangerInitialLifeFraction:
|
|
250
|
+
gc.skillRules?.doppelgangerInitialLifeFraction ?? fb.skillRules.doppelgangerInitialLifeFraction,
|
|
251
|
+
},
|
|
252
|
+
// Equipment rules — governs activation constraints (nested, mirrors EquipmentRules proto message).
|
|
253
|
+
equipmentRules: {
|
|
254
|
+
activeItemTypes: gc.equipmentRules?.activeItemTypes ?? fb.equipmentRules.activeItemTypes,
|
|
255
|
+
onePerType: gc.equipmentRules?.onePerType ?? fb.equipmentRules.onePerType,
|
|
256
|
+
requireSkin: gc.equipmentRules?.requireSkin ?? fb.equipmentRules.requireSkin,
|
|
257
|
+
},
|
|
258
|
+
// Status icon mapping — u8 ID → icon filename stem + border colour.
|
|
259
|
+
// Border colours come from the frozen STATUS_ICONS constant (canonical
|
|
260
|
+
// source of truth). DB entries may override iconId but borderColor is
|
|
261
|
+
// always canonical — the DB schema defaults are generic grey, not the
|
|
262
|
+
// actual per-status colours.
|
|
263
|
+
statusIcons: STATUS_ICONS.map((canon) => {
|
|
264
|
+
const dbEntry = (gc.statusIcons || []).find((s) => s.id === canon.id);
|
|
265
|
+
const bc = canon.borderColor || {};
|
|
266
|
+
return {
|
|
267
|
+
id: canon.id,
|
|
268
|
+
iconId: (dbEntry && dbEntry.iconId) || canon.iconId || '',
|
|
269
|
+
borderColorR: bc.r ?? 100,
|
|
270
|
+
borderColorG: bc.g ?? 100,
|
|
271
|
+
borderColorB: bc.b ?? 100,
|
|
272
|
+
borderColorA: bc.a ?? 200,
|
|
273
|
+
};
|
|
274
|
+
}),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Builds a minimal InstanceConfig with playable defaults.
|
|
280
|
+
* Derived from CYBERIA_INSTANCE_CONF_DEFAULTS (shared with the Mongoose model).
|
|
281
|
+
* Used when the requested instance does not exist in the database.
|
|
282
|
+
*/
|
|
283
|
+
function buildFallbackConfig() {
|
|
284
|
+
return JSON.parse(JSON.stringify(FALLBACK_CONFIG_DEFAULTS));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
288
|
+
// RPC handler factory
|
|
289
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
290
|
+
|
|
291
|
+
function buildHandlers(dbKey) {
|
|
292
|
+
return {
|
|
293
|
+
async ping(_call, callback) {
|
|
294
|
+
callback(null, { serverTimeMs: Date.now() });
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
// Server-streaming: streams all ObjectLayers
|
|
298
|
+
async getObjectLayerBatch(call) {
|
|
299
|
+
try {
|
|
300
|
+
const models = getModels(dbKey);
|
|
301
|
+
const filter = {};
|
|
302
|
+
if (call.request.itemTypeFilter) {
|
|
303
|
+
filter['data.item.type'] = call.request.itemTypeFilter;
|
|
304
|
+
}
|
|
305
|
+
const cursor = models.ObjectLayer.find(filter)
|
|
306
|
+
.populate('objectLayerRenderFramesId', { _id: 1, frame_duration: 1, is_stateless: 1 })
|
|
307
|
+
.lean()
|
|
308
|
+
.cursor();
|
|
309
|
+
for await (const doc of cursor) {
|
|
310
|
+
call.write(toObjectLayerMsg(doc));
|
|
311
|
+
}
|
|
312
|
+
call.end();
|
|
313
|
+
} catch (err) {
|
|
314
|
+
logger.error('getObjectLayerBatch:', err);
|
|
315
|
+
call.destroy(new Error(err.message));
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
|
|
319
|
+
async getObjectLayer(call, callback) {
|
|
320
|
+
try {
|
|
321
|
+
const models = getModels(dbKey);
|
|
322
|
+
const doc = await models.ObjectLayer.findOne({ 'data.item.id': call.request.itemId })
|
|
323
|
+
.populate('objectLayerRenderFramesId', { _id: 1, frame_duration: 1, is_stateless: 1 })
|
|
324
|
+
.lean();
|
|
325
|
+
if (!doc)
|
|
326
|
+
return callback({ code: grpc.status.NOT_FOUND, message: `ObjectLayer "${call.request.itemId}" not found` });
|
|
327
|
+
callback(null, toObjectLayerMsg(doc));
|
|
328
|
+
} catch (err) {
|
|
329
|
+
logger.error('getObjectLayer:', err);
|
|
330
|
+
callback({ code: grpc.status.INTERNAL, message: err.message });
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
async getMapData(call, callback) {
|
|
335
|
+
try {
|
|
336
|
+
const models = getModels(dbKey);
|
|
337
|
+
const { mapCode, instanceCode } = call.request;
|
|
338
|
+
const doc = await models.CyberiaMap.findOne({ code: mapCode }).lean();
|
|
339
|
+
if (!doc) return callback({ code: grpc.status.NOT_FOUND, message: `Map "${mapCode}" not found` });
|
|
340
|
+
|
|
341
|
+
// Track which instance is serving each mapCode in real time.
|
|
342
|
+
// instanceCode is provided by the Go server in every GetMapData request.
|
|
343
|
+
if (instanceCode) {
|
|
344
|
+
models.GlobalMapCodeRegistry.findOneAndUpdate(
|
|
345
|
+
{ mapCode },
|
|
346
|
+
{ instanceCode, status: 'active' },
|
|
347
|
+
{ upsert: true, new: true, timestamps: true },
|
|
348
|
+
).catch((err) => logger.warn('getMapData registry update failed:', err.message));
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
callback(null, { map: toMapMsg(doc) });
|
|
352
|
+
} catch (err) {
|
|
353
|
+
logger.error('getMapData:', err);
|
|
354
|
+
callback({ code: grpc.status.INTERNAL, message: err.message });
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
async getFullInstance(call, callback) {
|
|
359
|
+
try {
|
|
360
|
+
const models = getModels(dbKey);
|
|
361
|
+
// Normalise empty instanceCode to the canonical fallback name.
|
|
362
|
+
const instanceCode = call.request.instanceCode || 'default';
|
|
363
|
+
const inst = await models.CyberiaInstance.findOne({ code: instanceCode }).populate('conf').lean();
|
|
364
|
+
|
|
365
|
+
// ── Fallback: instance not found → return a multi-map procedural world ──
|
|
366
|
+
if (!inst) {
|
|
367
|
+
logger.info(`Instance "${instanceCode}" not found — returning fallback world.`);
|
|
368
|
+
const world = generateFallbackWorld();
|
|
369
|
+
const fallbackConf = buildFallbackConfig();
|
|
370
|
+
|
|
371
|
+
// Collect all objectLayerItemIds from the generated maps so the
|
|
372
|
+
// Go server can resolve atlases at startup.
|
|
373
|
+
const fallbackItemIds = new Set();
|
|
374
|
+
for (const m of world.maps) {
|
|
375
|
+
for (const e of m.entities || []) {
|
|
376
|
+
for (const id of e.objectLayerItemIds || []) fallbackItemIds.add(id);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// Also include system OL items from entity defaults.
|
|
380
|
+
for (const d of fallbackConf.entityDefaults || []) {
|
|
381
|
+
for (const id of d.liveItemIds || []) fallbackItemIds.add(id);
|
|
382
|
+
for (const id of d.deadItemIds || []) fallbackItemIds.add(id);
|
|
383
|
+
for (const ol of d.defaultObjectLayers || []) {
|
|
384
|
+
if (ol.itemId) fallbackItemIds.add(ol.itemId);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const fallbackOlDocs = fallbackItemIds.size
|
|
389
|
+
? await models.ObjectLayer.find({ 'data.item.id': { $in: [...fallbackItemIds] } })
|
|
390
|
+
.populate('objectLayerRenderFramesId', { _id: 1, frame_duration: 1, is_stateless: 1 })
|
|
391
|
+
.lean()
|
|
392
|
+
: [];
|
|
393
|
+
|
|
394
|
+
callback(null, {
|
|
395
|
+
instance: toInstanceMsg({
|
|
396
|
+
_id: '',
|
|
397
|
+
code: 'fallback',
|
|
398
|
+
name: 'Fallback Instance',
|
|
399
|
+
description: 'Auto-generated procedural world (not persisted)',
|
|
400
|
+
tags: ['fallback', 'procedural'],
|
|
401
|
+
cyberiaMapCodes: world.instance.cyberiaMapCodes,
|
|
402
|
+
portals: world.portals,
|
|
403
|
+
topologyMode: 'procedural',
|
|
404
|
+
seed: instanceCode,
|
|
405
|
+
}),
|
|
406
|
+
maps: world.maps.map((m) => ({
|
|
407
|
+
mongoId: '',
|
|
408
|
+
code: m.code,
|
|
409
|
+
name: m.name,
|
|
410
|
+
gridX: m.gridX,
|
|
411
|
+
gridY: m.gridY,
|
|
412
|
+
cellWidth: m.cellWidth,
|
|
413
|
+
cellHeight: m.cellHeight,
|
|
414
|
+
entities: (m.entities || []).map(toEntityMsg),
|
|
415
|
+
})),
|
|
416
|
+
objectLayers: fallbackOlDocs.map(toObjectLayerMsg),
|
|
417
|
+
config: toInstanceConfig(fallbackConf),
|
|
418
|
+
});
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// ── Instance found — load maps + entity OLs + config default OLs ──────
|
|
423
|
+
const conf = inst.conf || {};
|
|
424
|
+
const mapCodes = inst.cyberiaMapCodes || [];
|
|
425
|
+
const mapDocs = mapCodes.length ? await models.CyberiaMap.find({ code: { $in: mapCodes } }).lean() : [];
|
|
426
|
+
|
|
427
|
+
// Collect all item IDs referenced by map entities.
|
|
428
|
+
const itemIds = new Set();
|
|
429
|
+
for (const m of mapDocs) {
|
|
430
|
+
for (const e of m.entities || []) {
|
|
431
|
+
for (const id of e.objectLayerItemIds || []) itemIds.add(id);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Also include "system" item IDs from the instance config so the
|
|
436
|
+
// Go server has their OL data cached without extra round trips:
|
|
437
|
+
// Include OL item IDs from entityDefaults so the Go server has all
|
|
438
|
+
// default atlas data cached at startup without needing extra round trips.
|
|
439
|
+
for (const d of conf.entityDefaults || []) {
|
|
440
|
+
for (const id of d.liveItemIds || []) itemIds.add(id);
|
|
441
|
+
for (const id of d.deadItemIds || []) itemIds.add(id);
|
|
442
|
+
for (const ol of d.defaultObjectLayers || []) {
|
|
443
|
+
if (ol.itemId) itemIds.add(ol.itemId);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const olDocs = itemIds.size
|
|
448
|
+
? await models.ObjectLayer.find({ 'data.item.id': { $in: [...itemIds] } })
|
|
449
|
+
.populate('objectLayerRenderFramesId', { _id: 1, frame_duration: 1, is_stateless: 1 })
|
|
450
|
+
.lean()
|
|
451
|
+
: [];
|
|
452
|
+
|
|
453
|
+
callback(null, {
|
|
454
|
+
instance: toInstanceMsg(inst),
|
|
455
|
+
maps: mapDocs.map(toMapMsg),
|
|
456
|
+
objectLayers: olDocs.map(toObjectLayerMsg),
|
|
457
|
+
config: toInstanceConfig(conf),
|
|
458
|
+
});
|
|
459
|
+
} catch (err) {
|
|
460
|
+
logger.error('getFullInstance:', err);
|
|
461
|
+
callback({ code: grpc.status.INTERNAL, message: err.message });
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
async getObjectLayerManifest(_call, callback) {
|
|
466
|
+
try {
|
|
467
|
+
const models = getModels(dbKey);
|
|
468
|
+
const docs = await models.ObjectLayer.find({}, { 'data.item.id': 1, sha256: 1 }).lean();
|
|
469
|
+
callback(null, {
|
|
470
|
+
entries: docs.map((d) => ({ itemId: d.data?.item?.id || '', sha256: d.sha256 || '' })),
|
|
471
|
+
});
|
|
472
|
+
} catch (err) {
|
|
473
|
+
logger.error('getObjectLayerManifest:', err);
|
|
474
|
+
callback({ code: grpc.status.INTERNAL, message: err.message });
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
481
|
+
// Server lifecycle
|
|
482
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
483
|
+
|
|
484
|
+
const GrpcServer = {
|
|
485
|
+
_server: null,
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* @param {Object} opts
|
|
489
|
+
* @param {string} opts.host - DataBaseProvider host key
|
|
490
|
+
* @param {string} opts.path - DataBaseProvider path key
|
|
491
|
+
* @param {number} [opts.port=50051]
|
|
492
|
+
*/
|
|
493
|
+
async start({ host, path: dbPath, port = 50051 } = {}) {
|
|
494
|
+
const dbKey = `${host}${dbPath}`;
|
|
495
|
+
const server = new grpc.Server({
|
|
496
|
+
'grpc.max_send_message_length': 64 * 1024 * 1024,
|
|
497
|
+
'grpc.max_receive_message_length': 16 * 1024 * 1024,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
server.addService(proto.CyberiaDataService.service, buildHandlers(dbKey));
|
|
501
|
+
|
|
502
|
+
// gRPC runs over Kubernetes internal network (ClusterIP) — always insecure
|
|
503
|
+
const creds = grpc.ServerCredentials.createInsecure();
|
|
504
|
+
|
|
505
|
+
return new Promise((resolve, reject) => {
|
|
506
|
+
server.bindAsync(`0.0.0.0:${port}`, creds, (err) => {
|
|
507
|
+
if (err) {
|
|
508
|
+
logger.error('gRPC bind failed:', err);
|
|
509
|
+
return reject(err);
|
|
510
|
+
}
|
|
511
|
+
GrpcServer._server = server;
|
|
512
|
+
logger.info(`gRPC server listening on 0.0.0.0:${port}`);
|
|
513
|
+
resolve(server);
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
async stop() {
|
|
519
|
+
if (!GrpcServer._server) return;
|
|
520
|
+
return new Promise((resolve) => {
|
|
521
|
+
GrpcServer._server.tryShutdown(() => {
|
|
522
|
+
GrpcServer._server = null;
|
|
523
|
+
logger.info('gRPC server stopped');
|
|
524
|
+
resolve();
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
export { GrpcServer };
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import UnderpostKickStart from './cli/kickstart.js';
|
|
|
10
10
|
import UnderpostCluster from './cli/cluster.js';
|
|
11
11
|
import UnderpostDB from './cli/db.js';
|
|
12
12
|
import UnderpostDeploy from './cli/deploy.js';
|
|
13
|
+
import UnderpostKubectl from './cli/kubectl.js';
|
|
13
14
|
import UnderpostRootEnv from './cli/env.js';
|
|
14
15
|
import UnderpostFileStorage from './cli/fs.js';
|
|
15
16
|
import UnderpostIPFS from './cli/ipfs.js';
|
|
@@ -22,6 +23,7 @@ import UnderpostSecret from './cli/secrets.js';
|
|
|
22
23
|
import UnderpostSSH from './cli/ssh.js';
|
|
23
24
|
import UnderpostStatic from './cli/static.js';
|
|
24
25
|
import UnderpostTest from './cli/test.js';
|
|
26
|
+
import UnderpostRelease from './cli/release.js';
|
|
25
27
|
import UnderpostSystemProvisionig from './cli/system.js';
|
|
26
28
|
|
|
27
29
|
import UnderpostDns from './server/dns.js';
|
|
@@ -42,7 +44,7 @@ class Underpost {
|
|
|
42
44
|
* @type {String}
|
|
43
45
|
* @memberof Underpost
|
|
44
46
|
*/
|
|
45
|
-
static version = 'v3.
|
|
47
|
+
static version = 'v3.2.5';
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
50
|
* Required Node.js major version
|
|
@@ -126,6 +128,15 @@ class Underpost {
|
|
|
126
128
|
static get db() {
|
|
127
129
|
return UnderpostDB.API;
|
|
128
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Kubectl cli API
|
|
133
|
+
* @static
|
|
134
|
+
* @type {UnderpostKubectl.API}
|
|
135
|
+
* @memberof Underpost
|
|
136
|
+
*/
|
|
137
|
+
static get kubectl() {
|
|
138
|
+
return UnderpostKubectl.API;
|
|
139
|
+
}
|
|
129
140
|
/**
|
|
130
141
|
* Deployment cli API
|
|
131
142
|
* @static
|
|
@@ -280,6 +291,16 @@ class Underpost {
|
|
|
280
291
|
static get tls() {
|
|
281
292
|
return UnderpostTLS.API;
|
|
282
293
|
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Release orchestrator cli API
|
|
297
|
+
* @static
|
|
298
|
+
* @type {UnderpostRelease.API}
|
|
299
|
+
* @memberof Underpost
|
|
300
|
+
*/
|
|
301
|
+
static get release() {
|
|
302
|
+
return UnderpostRelease.API;
|
|
303
|
+
}
|
|
283
304
|
}
|
|
284
305
|
|
|
285
306
|
if (!process.version || !process.version.startsWith(`${Underpost.majorNodejsVersion}.`))
|
|
@@ -300,6 +321,7 @@ export {
|
|
|
300
321
|
UnderpostCluster,
|
|
301
322
|
UnderpostDB,
|
|
302
323
|
UnderpostDeploy,
|
|
324
|
+
UnderpostKubectl,
|
|
303
325
|
UnderpostRootEnv,
|
|
304
326
|
UnderpostFileStorage,
|
|
305
327
|
UnderpostImage,
|
|
@@ -317,6 +339,7 @@ export {
|
|
|
317
339
|
UnderpostBackup,
|
|
318
340
|
UnderpostCron,
|
|
319
341
|
UnderpostStartUp,
|
|
342
|
+
UnderpostRelease,
|
|
320
343
|
UnderpostTLS,
|
|
321
344
|
};
|
|
322
345
|
|
package/src/proxy.js
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
// https://nodejs.org/api
|
|
4
4
|
// https://expressjs.com/en/4x/api.html
|
|
5
5
|
|
|
6
|
-
import dotenv from 'dotenv';
|
|
7
6
|
import { loggerFactory } from './server/logger.js';
|
|
8
7
|
import { buildProxy } from './server/proxy.js';
|
|
9
8
|
import { ProcessController } from './server/process.js';
|
|
10
9
|
import { Config } from './server/conf.js';
|
|
11
10
|
|
|
12
|
-
dotenv.config();
|
|
13
|
-
|
|
14
11
|
await Config.build(process.argv[2], process.argv[3], process.argv[4]);
|
|
15
12
|
|
|
16
13
|
const logger = loggerFactory(import.meta);
|
|
@@ -30,6 +30,10 @@ RUN dnf clean all
|
|
|
30
30
|
RUN node --version
|
|
31
31
|
RUN npm --version
|
|
32
32
|
|
|
33
|
+
# Create non-root user for secure container execution (cron jobs, init containers)
|
|
34
|
+
# Deployment containers override to root via securityContext when npm install -g is needed
|
|
35
|
+
RUN useradd -m -u 1000 -s /bin/bash dd
|
|
36
|
+
|
|
33
37
|
# Set working directory
|
|
34
38
|
WORKDIR /home/dd
|
|
35
39
|
|