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
package/src/server/conf.js
CHANGED
|
@@ -26,10 +26,249 @@ import Underpost from '../index.js';
|
|
|
26
26
|
|
|
27
27
|
colors.enable();
|
|
28
28
|
|
|
29
|
-
dotenv.config();
|
|
30
|
-
|
|
31
29
|
const logger = loggerFactory(import.meta);
|
|
32
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Prefix used in JSON configuration files to denote an environment variable reference.
|
|
33
|
+
* Any string value in a config object that starts with this prefix will be resolved
|
|
34
|
+
* to the corresponding `process.env` value at runtime.
|
|
35
|
+
*
|
|
36
|
+
* @constant {string}
|
|
37
|
+
* @memberof ServerConfBuilder
|
|
38
|
+
* @example
|
|
39
|
+
* // In conf.server.json:
|
|
40
|
+
* { "db": { "password": "env:MARIADB_PASSWORD" } }
|
|
41
|
+
*/
|
|
42
|
+
const ENV_REF_PREFIX = 'env:';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Recursively walks a configuration object and replaces every string value that
|
|
46
|
+
* starts with {@link ENV_REF_PREFIX} (`"env:"`) with the corresponding
|
|
47
|
+
* `process.env[VAR_NAME]` value.
|
|
48
|
+
*
|
|
49
|
+
* Non-string values and strings that do not start with the prefix are left untouched.
|
|
50
|
+
*
|
|
51
|
+
* Supports three reference formats:
|
|
52
|
+
* - `"env:VAR_NAME"` — resolves to `process.env.VAR_NAME`, returns `''` if unset.
|
|
53
|
+
* - `"env:VAR_NAME:default_value"` — resolves to `process.env.VAR_NAME`, falls back to `default_value` if unset.
|
|
54
|
+
* - Type-coerced defaults:
|
|
55
|
+
* - `"env:VAR_NAME:int:465"` — resolved value is parsed as integer (`parseInt`), falls back to `465`.
|
|
56
|
+
* - `"env:VAR_NAME:bool:true"` — resolved value is coerced to boolean (`value !== 'false'`), falls back to `true`.
|
|
57
|
+
*
|
|
58
|
+
* @method resolveConfSecrets
|
|
59
|
+
* @param {any} obj - The configuration object (or value) to resolve.
|
|
60
|
+
* @returns {any} A **new** object with all `env:` references replaced by their runtime values.
|
|
61
|
+
* @memberof ServerConfBuilder
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Given process.env.MARIADB_PASSWORD = 'supersecret'
|
|
65
|
+
* resolveConfSecrets({ db: { password: 'env:MARIADB_PASSWORD' } });
|
|
66
|
+
* // => { db: { password: 'supersecret' } }
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // With default value fallback (env var not set)
|
|
70
|
+
* resolveConfSecrets({ db: { provider: 'env:DB_PROVIDER:mongoose' } });
|
|
71
|
+
* // => { db: { provider: 'mongoose' } }
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // With int type coercion
|
|
75
|
+
* resolveConfSecrets({ port: 'env:SMTP_PORT:int:465' });
|
|
76
|
+
* // => { port: 465 }
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // With bool type coercion
|
|
80
|
+
* resolveConfSecrets({ secure: 'env:SMTP_SECURE:bool:true' });
|
|
81
|
+
* // => { secure: true }
|
|
82
|
+
*/
|
|
83
|
+
const resolveConfSecrets = (obj) => {
|
|
84
|
+
if (obj === null || obj === undefined) return obj;
|
|
85
|
+
if (typeof obj === 'string') {
|
|
86
|
+
if (obj.startsWith(ENV_REF_PREFIX)) {
|
|
87
|
+
const ref = obj.slice(ENV_REF_PREFIX.length);
|
|
88
|
+
// Support env:VAR_NAME:default_value syntax (first colon separates key from default)
|
|
89
|
+
const colonIdx = ref.indexOf(':');
|
|
90
|
+
const envKey = colonIdx !== -1 ? ref.slice(0, colonIdx) : ref;
|
|
91
|
+
const defaultValue = colonIdx !== -1 ? ref.slice(colonIdx + 1) : undefined;
|
|
92
|
+
const envValue = process.env[envKey];
|
|
93
|
+
|
|
94
|
+
let resolved;
|
|
95
|
+
if (envValue !== undefined) {
|
|
96
|
+
resolved = envValue;
|
|
97
|
+
} else if (defaultValue !== undefined) {
|
|
98
|
+
resolved = defaultValue;
|
|
99
|
+
} else {
|
|
100
|
+
logger.warn(`resolveConfSecrets: environment variable "${envKey}" is not set (referenced as "${obj}")`);
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Type coercion via prefix in default value: int:N or bool:B
|
|
105
|
+
// Also apply coercion when an env value is present and a typed default is declared
|
|
106
|
+
if (defaultValue !== undefined) {
|
|
107
|
+
if (defaultValue.startsWith('int:')) {
|
|
108
|
+
return parseInt(resolved, 10) || parseInt(defaultValue.slice(4), 10) || 0;
|
|
109
|
+
}
|
|
110
|
+
if (defaultValue.startsWith('bool:')) {
|
|
111
|
+
const boolDefault = defaultValue.slice(5);
|
|
112
|
+
if (envValue !== undefined) return envValue !== 'false';
|
|
113
|
+
return boolDefault !== 'false';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return resolved;
|
|
118
|
+
}
|
|
119
|
+
return obj;
|
|
120
|
+
}
|
|
121
|
+
if (Array.isArray(obj)) return obj.map((item) => resolveConfSecrets(item));
|
|
122
|
+
if (typeof obj === 'object') {
|
|
123
|
+
const resolved = {};
|
|
124
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
125
|
+
resolved[key] = resolveConfSecrets(value);
|
|
126
|
+
}
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
return obj;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Returns the private configuration folder for a given deploy ID.
|
|
134
|
+
* Checks for a replica folder first, then falls back to the standard conf folder.
|
|
135
|
+
*
|
|
136
|
+
* @method getConfFolder
|
|
137
|
+
* @param {string} deployId - The deploy ID.
|
|
138
|
+
* @returns {string} The path to the private configuration folder.
|
|
139
|
+
* @memberof ServerConfBuilder
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* getConfFolder('dd-myapp');
|
|
143
|
+
* // => './engine-private/conf/dd-myapp' (or './engine-private/replica/dd-myapp' if it exists)
|
|
144
|
+
*/
|
|
145
|
+
const getConfFolder = (deployId) => {
|
|
146
|
+
return fs.existsSync(`./engine-private/replica/${deployId}`)
|
|
147
|
+
? `./engine-private/replica/${deployId}`
|
|
148
|
+
: `./engine-private/conf/${deployId}`;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Reads `engine-private/deploy/dd.cron` and returns the deploy-id string,
|
|
153
|
+
* or `null` if the file does not exist or is empty.
|
|
154
|
+
*
|
|
155
|
+
* @method cronDeployIdResolve
|
|
156
|
+
* @returns {string|null} The deploy-id from dd.cron, or null.
|
|
157
|
+
* @memberof ServerConfBuilder
|
|
158
|
+
*/
|
|
159
|
+
const cronDeployIdResolve = () => {
|
|
160
|
+
const cronDeployFile = './engine-private/deploy/dd.cron';
|
|
161
|
+
if (fs.existsSync(cronDeployFile)) {
|
|
162
|
+
const id = fs.readFileSync(cronDeployFile, 'utf8').trim();
|
|
163
|
+
return id || null;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Loads the deployment-specific `.env` file referenced by `engine-private/deploy/dd.cron`
|
|
170
|
+
* into `process.env`. Uses `NODE_ENV` to select the environment variant
|
|
171
|
+
* (defaults to `production`).
|
|
172
|
+
*
|
|
173
|
+
* Safe to call multiple times; subsequent calls are no-ops once the env is loaded.
|
|
174
|
+
*
|
|
175
|
+
* @method loadCronDeployEnv
|
|
176
|
+
* @memberof ServerConfBuilder
|
|
177
|
+
*/
|
|
178
|
+
function loadCronDeployEnv() {
|
|
179
|
+
const envName = process.env.NODE_ENV || 'production';
|
|
180
|
+
|
|
181
|
+
// 1) Load dd.cron env (takes full precedence)
|
|
182
|
+
const cronDeployId = cronDeployIdResolve();
|
|
183
|
+
if (cronDeployId) {
|
|
184
|
+
const cronEnvPath = `./engine-private/conf/${cronDeployId}/.env.${envName}`;
|
|
185
|
+
if (fs.existsSync(cronEnvPath)) {
|
|
186
|
+
const cronEnv = dotenv.parse(fs.readFileSync(cronEnvPath, 'utf8'));
|
|
187
|
+
process.env = { ...process.env, ...cronEnv };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 2) Load dd.router envs — only keys not already present
|
|
192
|
+
const routerDeployFile = './engine-private/deploy/dd.router';
|
|
193
|
+
if (fs.existsSync(routerDeployFile)) {
|
|
194
|
+
const routerIds = fs.readFileSync(routerDeployFile, 'utf8').trim().split(',');
|
|
195
|
+
for (const deployId of routerIds) {
|
|
196
|
+
const id = deployId.trim();
|
|
197
|
+
if (!id) continue;
|
|
198
|
+
const envPath = `./engine-private/conf/${id}/.env.${envName}`;
|
|
199
|
+
if (!fs.existsSync(envPath)) continue;
|
|
200
|
+
const env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
201
|
+
for (const key of Object.keys(env)) {
|
|
202
|
+
if (!(key in process.env)) process.env[key] = env[key];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Resolves the full path to a specific configuration JSON file for a deploy ID.
|
|
210
|
+
* For `server` configs in development mode with a subConf, it will prefer the
|
|
211
|
+
* dev-specific variant if it exists.
|
|
212
|
+
*
|
|
213
|
+
* @method getConfFilePath
|
|
214
|
+
* @param {string} deployId - The deploy ID.
|
|
215
|
+
* @param {string} confType - The configuration type (e.g. 'server', 'client', 'cron', 'ssr').
|
|
216
|
+
* @param {string} [subConf=''] - Optional sub-configuration identifier (used for dev server variants).
|
|
217
|
+
* @returns {string} The resolved path to the configuration JSON file.
|
|
218
|
+
* @memberof ServerConfBuilder
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* getConfFilePath('dd-myapp', 'server');
|
|
222
|
+
* // => './engine-private/conf/dd-myapp/conf.server.json'
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* // In development with subConf 'local':
|
|
226
|
+
* getConfFilePath('dd-myapp', 'server', 'local');
|
|
227
|
+
* // => './engine-private/conf/dd-myapp/conf.server.dev.local.json' (if it exists)
|
|
228
|
+
*/
|
|
229
|
+
const getConfFilePath = (deployId, confType, subConf = '') => {
|
|
230
|
+
const folder = getConfFolder(deployId);
|
|
231
|
+
// When no explicit subConf is given, fall back to the env var set by loadConf()
|
|
232
|
+
const effectiveSubConf = subConf || process.env.DEPLOY_SUB_CONF || '';
|
|
233
|
+
if (confType === 'server' && effectiveSubConf) {
|
|
234
|
+
const devConfPath = `${folder}/conf.${confType}.dev.${effectiveSubConf}.json`;
|
|
235
|
+
if (fs.existsSync(devConfPath)) return devConfPath;
|
|
236
|
+
}
|
|
237
|
+
return `${folder}/conf.${confType}.json`;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Reads and parses a configuration JSON file for a given deploy ID and config type.
|
|
242
|
+
* Optionally resolves `env:` secret references and/or applies replica expansion.
|
|
243
|
+
*
|
|
244
|
+
* @method readConfJson
|
|
245
|
+
* @param {string} deployId - The deploy ID.
|
|
246
|
+
* @param {string} confType - The configuration type (e.g. 'server', 'client', 'cron', 'ssr').
|
|
247
|
+
* @param {object} [options={}] - Options.
|
|
248
|
+
* @param {string} [options.subConf=''] - Sub-configuration identifier for dev variants.
|
|
249
|
+
* @param {boolean} [options.resolve=false] - Whether to resolve `env:` references.
|
|
250
|
+
* @param {boolean} [options.loadReplicas=false] - Whether to expand replica entries (server configs).
|
|
251
|
+
* @returns {object} The parsed (and optionally resolved) configuration object.
|
|
252
|
+
* @memberof ServerConfBuilder
|
|
253
|
+
*/
|
|
254
|
+
const readConfJson = (deployId, confType, options = {}) => {
|
|
255
|
+
const filePath = getConfFilePath(deployId, confType, options.subConf || '');
|
|
256
|
+
if (!fs.existsSync(filePath)) {
|
|
257
|
+
throw new Error(`readConfJson: configuration file not found: ${filePath}`);
|
|
258
|
+
}
|
|
259
|
+
let parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
260
|
+
if (options.loadReplicas && confType === 'server') parsed = loadReplicas(deployId, parsed);
|
|
261
|
+
if (options.resolve) parsed = resolveConfSecrets(parsed);
|
|
262
|
+
return parsed;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Default deploy ID used when no deploy ID is specified.
|
|
267
|
+
* @constant {string}
|
|
268
|
+
* @memberof ServerConfBuilder
|
|
269
|
+
*/
|
|
270
|
+
const DEFAULT_DEPLOY_ID = 'dd-default';
|
|
271
|
+
|
|
33
272
|
/**
|
|
34
273
|
* @class Config
|
|
35
274
|
* @description Manages the configuration of the server.
|
|
@@ -53,12 +292,13 @@ const Config = {
|
|
|
53
292
|
* @param {string} [subConf=''] - The sub configuration.
|
|
54
293
|
* @memberof ServerConfBuilder
|
|
55
294
|
*/
|
|
56
|
-
build: async function (deployContext =
|
|
295
|
+
build: async function (deployContext = DEFAULT_DEPLOY_ID, deployList, subConf) {
|
|
57
296
|
if (process.argv[2] && typeof process.argv[2] === 'string' && process.argv[2].startsWith('dd-'))
|
|
58
297
|
deployContext = process.argv[2];
|
|
298
|
+
else if (deployContext !== 'proxy' && process.env.DEPLOY_ID && process.env.DEPLOY_ID.startsWith('dd-'))
|
|
299
|
+
deployContext = process.env.DEPLOY_ID;
|
|
59
300
|
if (!subConf && process.argv[3] && typeof process.argv[3] === 'string') subConf = process.argv[3];
|
|
60
|
-
|
|
61
|
-
if (!fs.existsSync(`./conf`)) fs.mkdirSync(`./conf`);
|
|
301
|
+
|
|
62
302
|
Underpost.env.set('await-deploy', new Date().toISOString());
|
|
63
303
|
if (deployContext.startsWith('dd-')) loadConf(deployContext, subConf);
|
|
64
304
|
if (deployContext === 'proxy') await Config.buildProxy(deployList, subConf);
|
|
@@ -70,7 +310,7 @@ const Config = {
|
|
|
70
310
|
* @param {object} [options={ subConf: '', cluster: false }] - The options.
|
|
71
311
|
* @memberof ServerConfBuilder
|
|
72
312
|
*/
|
|
73
|
-
deployIdFactory: function (deployId =
|
|
313
|
+
deployIdFactory: function (deployId = DEFAULT_DEPLOY_ID, options = { subConf: '', cluster: false }) {
|
|
74
314
|
if (!deployId.startsWith('dd-')) deployId = `dd-${deployId}`;
|
|
75
315
|
|
|
76
316
|
logger.info('Build deployId', deployId);
|
|
@@ -79,28 +319,39 @@ const Config = {
|
|
|
79
319
|
const repoName = `engine-${deployId.split('dd-')[1]}`;
|
|
80
320
|
|
|
81
321
|
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
fs.readFileSync('./.env.
|
|
85
|
-
'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
'
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
322
|
+
|
|
323
|
+
const envTemplate = fs.existsSync('./.env.example')
|
|
324
|
+
? fs.readFileSync('./.env.example', 'utf8')
|
|
325
|
+
: fs.existsSync('./.env.production')
|
|
326
|
+
? fs.readFileSync('./.env.production', 'utf8')
|
|
327
|
+
: '';
|
|
328
|
+
|
|
329
|
+
if (envTemplate) {
|
|
330
|
+
const prodEnv = envTemplate.replaceAll('dd-default', deployId);
|
|
331
|
+
fs.writeFileSync(`${folder}/.env.production`, prodEnv, 'utf8');
|
|
332
|
+
fs.writeFileSync(
|
|
333
|
+
`${folder}/.env.development`,
|
|
334
|
+
prodEnv.replace('NODE_ENV=production', 'NODE_ENV=development').replace('PORT=3000', 'PORT=4000'),
|
|
335
|
+
'utf8',
|
|
336
|
+
);
|
|
337
|
+
fs.writeFileSync(
|
|
338
|
+
`${folder}/.env.test`,
|
|
339
|
+
prodEnv.replace('NODE_ENV=production', 'NODE_ENV=test').replace('PORT=3000', 'PORT=5000'),
|
|
340
|
+
'utf8',
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
97
344
|
fs.writeFileSync(
|
|
98
345
|
`${folder}/package.json`,
|
|
99
346
|
fs.readFileSync('./package.json', 'utf8').replaceAll('dd-default', deployId),
|
|
100
347
|
'utf8',
|
|
101
348
|
);
|
|
102
349
|
|
|
103
|
-
|
|
350
|
+
// Write default conf JSON files if they don't exist
|
|
351
|
+
for (const confType of Object.keys(this.default)) {
|
|
352
|
+
const confPath = `${folder}/conf.${confType}.json`;
|
|
353
|
+
if (!fs.existsSync(confPath)) fs.writeFileSync(confPath, JSON.stringify(this.default[confType], null, 4), 'utf8');
|
|
354
|
+
}
|
|
104
355
|
|
|
105
356
|
if (options.subConf) {
|
|
106
357
|
logger.info('Creating sub conf', {
|
|
@@ -127,38 +378,17 @@ const Config = {
|
|
|
127
378
|
shellExec(`node bin new --default-conf --deploy-id ${deployId}`);
|
|
128
379
|
|
|
129
380
|
if (!fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
130
|
-
fs.writeFileSync(`./engine-private/deploy/dd.router`,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
137
|
-
const updateRepo = (stage = 1) => {
|
|
138
|
-
shellExec(`git add . && git commit -m "Add base deployId ${deployId} cluster files stage:${stage}"`);
|
|
139
|
-
shellExec(
|
|
140
|
-
`cd engine-private && git add . && git commit -m "Add base deployId ${deployId} cluster files stage:${stage}"`,
|
|
381
|
+
fs.writeFileSync(`./engine-private/deploy/dd.router`, deployId, 'utf8');
|
|
382
|
+
else
|
|
383
|
+
fs.writeFileSync(
|
|
384
|
+
`./engine-private/deploy/dd.router`,
|
|
385
|
+
fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').trim() + `,${deployId}`,
|
|
386
|
+
'utf8',
|
|
141
387
|
);
|
|
142
|
-
};
|
|
143
|
-
updateRepo(1);
|
|
144
|
-
shellExec(`node bin run --build --dev sync`);
|
|
145
|
-
updateRepo(2);
|
|
146
|
-
shellExec(`node bin run --build sync`);
|
|
147
|
-
updateRepo(3);
|
|
148
388
|
}
|
|
149
389
|
|
|
150
390
|
return { deployIdFolder: folder, deployId };
|
|
151
391
|
},
|
|
152
|
-
/**
|
|
153
|
-
* @method buildTmpConf
|
|
154
|
-
* @description Builds the temporary configuration of the server.
|
|
155
|
-
* @param {string} [folder='./conf'] - The folder.
|
|
156
|
-
* @memberof ServerConfBuilder
|
|
157
|
-
*/
|
|
158
|
-
buildTmpConf: function (folder = './conf') {
|
|
159
|
-
for (const confType of Object.keys(this.default))
|
|
160
|
-
fs.writeFileSync(`${folder}/conf.${confType}.json`, JSON.stringify(this.default[confType], null, 4), 'utf8');
|
|
161
|
-
},
|
|
162
392
|
/**
|
|
163
393
|
* @method buildProxyByDeployId
|
|
164
394
|
* @description Builds the proxy by deploy ID.
|
|
@@ -178,7 +408,7 @@ const Config = {
|
|
|
178
408
|
)
|
|
179
409
|
confPath = `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
|
|
180
410
|
|
|
181
|
-
const serverConf =
|
|
411
|
+
const serverConf = loadConfServerJson(confPath);
|
|
182
412
|
|
|
183
413
|
for (const host of Object.keys(loadReplicas(deployId, serverConf)))
|
|
184
414
|
this.default.server[host] = {
|
|
@@ -206,7 +436,6 @@ const Config = {
|
|
|
206
436
|
}
|
|
207
437
|
}
|
|
208
438
|
}
|
|
209
|
-
this.buildTmpConf();
|
|
210
439
|
},
|
|
211
440
|
};
|
|
212
441
|
|
|
@@ -217,7 +446,7 @@ const Config = {
|
|
|
217
446
|
* @param {string} [subConf=''] - The sub configuration.
|
|
218
447
|
* @memberof ServerConfBuilder
|
|
219
448
|
*/
|
|
220
|
-
const loadConf = (deployId =
|
|
449
|
+
const loadConf = (deployId = DEFAULT_DEPLOY_ID, subConf) => {
|
|
221
450
|
if (deployId === 'current') {
|
|
222
451
|
console.log(process.env.DEPLOY_ID);
|
|
223
452
|
return;
|
|
@@ -225,20 +454,19 @@ const loadConf = (deployId = 'dd-default', subConf) => {
|
|
|
225
454
|
if (deployId === 'clean') {
|
|
226
455
|
const path = '.';
|
|
227
456
|
fs.removeSync(`${path}/.env`);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
457
|
+
fs.removeSync(`${path}/.env.production`);
|
|
458
|
+
fs.removeSync(`${path}/.env.development`);
|
|
459
|
+
fs.removeSync(`${path}/.env.test`);
|
|
231
460
|
if (fs.existsSync(`${path}/jsdoc.json`)) shellExec(`git checkout ${path}/jsdoc.json`);
|
|
232
461
|
shellExec(`git checkout ${path}/package.json`);
|
|
233
462
|
shellExec(`git checkout ${path}/package-lock.json`);
|
|
234
463
|
return;
|
|
235
464
|
}
|
|
236
|
-
const folder =
|
|
237
|
-
|
|
238
|
-
: `./engine-private/conf/${deployId}`;
|
|
465
|
+
const folder = getConfFolder(deployId);
|
|
466
|
+
|
|
239
467
|
if (!fs.existsSync(folder)) Config.deployIdFactory(deployId);
|
|
240
|
-
|
|
241
|
-
if (
|
|
468
|
+
|
|
469
|
+
if (subConf) process.env.DEPLOY_SUB_CONF = subConf;
|
|
242
470
|
|
|
243
471
|
for (const typeConf of Object.keys(Config.default)) {
|
|
244
472
|
let srcConf = fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8');
|
|
@@ -246,13 +474,14 @@ const loadConf = (deployId = 'dd-default', subConf) => {
|
|
|
246
474
|
const devConfPath = `${folder}/conf.${typeConf}.dev${subConf ? `.${subConf}` : ''}.json`;
|
|
247
475
|
if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
|
|
248
476
|
}
|
|
249
|
-
|
|
250
|
-
|
|
477
|
+
let parsed = JSON.parse(srcConf);
|
|
478
|
+
if (typeConf === 'server') parsed = loadReplicas(deployId, parsed);
|
|
479
|
+
Config.default[typeConf] = parsed;
|
|
251
480
|
}
|
|
252
481
|
fs.writeFileSync(`./.env.production`, fs.readFileSync(`${folder}/.env.production`, 'utf8'), 'utf8');
|
|
253
482
|
fs.writeFileSync(`./.env.development`, fs.readFileSync(`${folder}/.env.development`, 'utf8'), 'utf8');
|
|
254
483
|
fs.writeFileSync(`./.env.test`, fs.readFileSync(`${folder}/.env.test`, 'utf8'), 'utf8');
|
|
255
|
-
const NODE_ENV = process.env.NODE_ENV;
|
|
484
|
+
const NODE_ENV = process.env.NODE_ENV || 'development';
|
|
256
485
|
if (NODE_ENV) {
|
|
257
486
|
const subPathEnv = fs.existsSync(`${folder}/.env.${NODE_ENV}.${subConf}`)
|
|
258
487
|
? `${folder}/.env.${NODE_ENV}.${subConf}`
|
|
@@ -644,7 +873,7 @@ const cloneSrcComponents = async ({ toOptions, fromOptions }) => {
|
|
|
644
873
|
* @memberof ServerConfBuilder
|
|
645
874
|
*/
|
|
646
875
|
const buildProxyRouter = () => {
|
|
647
|
-
const confServer =
|
|
876
|
+
const confServer = newInstance(Config.default.server);
|
|
648
877
|
let currentPort = parseInt(process.env.PORT) + 1;
|
|
649
878
|
const proxyRouter = {};
|
|
650
879
|
for (const host of Object.keys(confServer)) {
|
|
@@ -726,9 +955,7 @@ const pathPortAssignmentFactory = async (deployId, router, confServer) => {
|
|
|
726
955
|
const singleReplicas = await fs.readdir(`./engine-private/replica`);
|
|
727
956
|
for (let replica of singleReplicas) {
|
|
728
957
|
if (replica.startsWith(deployId)) {
|
|
729
|
-
const replicaServerConf =
|
|
730
|
-
fs.readFileSync(`./engine-private/replica/${replica}/conf.server.json`, 'utf8'),
|
|
731
|
-
);
|
|
958
|
+
const replicaServerConf = loadConfServerJson(`./engine-private/replica/${replica}/conf.server.json`);
|
|
732
959
|
for (const host of Object.keys(replicaServerConf)) {
|
|
733
960
|
const pathPortAssignment = [];
|
|
734
961
|
for (const path of Object.keys(replicaServerConf[host])) {
|
|
@@ -906,7 +1133,7 @@ const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1
|
|
|
906
1133
|
* @returns {object} - The data deploy.
|
|
907
1134
|
* @memberof ServerConfBuilder
|
|
908
1135
|
*/
|
|
909
|
-
const getDataDeploy = (
|
|
1136
|
+
const getDataDeploy = async (
|
|
910
1137
|
options = {
|
|
911
1138
|
buildSingleReplica: false,
|
|
912
1139
|
disableSyncEnvPort: false,
|
|
@@ -931,13 +1158,16 @@ const getDataDeploy = (
|
|
|
931
1158
|
for (const deployObj of dataDeploy) {
|
|
932
1159
|
const serverConf = loadReplicas(
|
|
933
1160
|
deployObj.deployId,
|
|
934
|
-
|
|
1161
|
+
loadConfServerJson(`./engine-private/conf/${deployObj.deployId}/conf.server.json`),
|
|
935
1162
|
);
|
|
936
1163
|
let replicaDataDeploy = [];
|
|
937
1164
|
for (const host of Object.keys(serverConf))
|
|
938
1165
|
for (const path of Object.keys(serverConf[host])) {
|
|
939
1166
|
if (serverConf[host][path].replicas && serverConf[host][path].singleReplica) {
|
|
940
|
-
if (options && options.buildSingleReplica)
|
|
1167
|
+
if (options && options.buildSingleReplica)
|
|
1168
|
+
await Underpost.repo.client(deployObj.deployId, '', host, path, {
|
|
1169
|
+
singleReplica: true,
|
|
1170
|
+
});
|
|
941
1171
|
replicaDataDeploy = replicaDataDeploy.concat(
|
|
942
1172
|
serverConf[host][path].replicas.map((r) => {
|
|
943
1173
|
return {
|
|
@@ -952,7 +1182,8 @@ const getDataDeploy = (
|
|
|
952
1182
|
if (replicaDataDeploy.length > 0) buildDataDeploy = buildDataDeploy.concat(replicaDataDeploy);
|
|
953
1183
|
}
|
|
954
1184
|
|
|
955
|
-
if (!options.disableSyncEnvPort && options.buildSingleReplica)
|
|
1185
|
+
if (!options.disableSyncEnvPort && options.buildSingleReplica)
|
|
1186
|
+
await Underpost.repo.client(undefined, '', '', '', { syncEnvPort: true });
|
|
956
1187
|
|
|
957
1188
|
logger.info('Deployments configured', buildDataDeploy);
|
|
958
1189
|
|
|
@@ -980,6 +1211,7 @@ const validateTemplatePath = (absolutePath = '') => {
|
|
|
980
1211
|
return false;
|
|
981
1212
|
}
|
|
982
1213
|
if (absolutePath.match('conf.dd-') && absolutePath.match('.js')) return false;
|
|
1214
|
+
if (absolutePath.match('jsdoc.dd-') && absolutePath.match('.json')) return false;
|
|
983
1215
|
if (
|
|
984
1216
|
absolutePath.match('src/client/services/') &&
|
|
985
1217
|
!clients.find((p) => absolutePath.match(`src/client/services/${p}/`))
|
|
@@ -1057,18 +1289,6 @@ const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
|
|
|
1057
1289
|
if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor();
|
|
1058
1290
|
};
|
|
1059
1291
|
|
|
1060
|
-
/**
|
|
1061
|
-
* @method getCronBackUpFolder
|
|
1062
|
-
* @description Gets the cron back up folder.
|
|
1063
|
-
* @param {string} host - The host.
|
|
1064
|
-
* @param {string} path - The path.
|
|
1065
|
-
* @returns {string} - The cron back up folder.
|
|
1066
|
-
* @memberof ServerConfBuilder
|
|
1067
|
-
*/
|
|
1068
|
-
const getCronBackUpFolder = (host = '', path = '') => {
|
|
1069
|
-
return `${host}${path.replace(/\\/g, '/').replace(`/`, '-')}`;
|
|
1070
|
-
};
|
|
1071
|
-
|
|
1072
1292
|
/**
|
|
1073
1293
|
* @method mergeFile
|
|
1074
1294
|
* @description Merges the file.
|
|
@@ -1102,10 +1322,7 @@ const mergeFile = async (parts = [], outputFilePath) => {
|
|
|
1102
1322
|
* @memberof ServerConfBuilder
|
|
1103
1323
|
*/
|
|
1104
1324
|
const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
|
|
1105
|
-
const confServer = loadReplicas(
|
|
1106
|
-
deployId,
|
|
1107
|
-
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
1108
|
-
);
|
|
1325
|
+
const confServer = loadReplicas(deployId, loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`));
|
|
1109
1326
|
const hosts = {};
|
|
1110
1327
|
for (const host of Object.keys(confServer)) {
|
|
1111
1328
|
hosts[host] = {};
|
|
@@ -1116,9 +1333,7 @@ const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
|
|
|
1116
1333
|
if (singleReplica) {
|
|
1117
1334
|
for (const replica of replicas) {
|
|
1118
1335
|
const deployIdReplica = buildReplicaId({ replica, deployId });
|
|
1119
|
-
const confServerReplica =
|
|
1120
|
-
fs.readFileSync(`./engine-private/replica/${deployIdReplica}/conf.server.json`, 'utf8'),
|
|
1121
|
-
);
|
|
1336
|
+
const confServerReplica = loadConfServerJson(`./engine-private/replica/${deployIdReplica}/conf.server.json`);
|
|
1122
1337
|
for (const _host of Object.keys(confServerReplica)) {
|
|
1123
1338
|
for (const _path of Object.keys(confServerReplica[_host])) {
|
|
1124
1339
|
hosts[host][_path] = { replica: { host, path } };
|
|
@@ -1166,56 +1381,6 @@ const getPathsSSR = (conf) => {
|
|
|
1166
1381
|
return paths;
|
|
1167
1382
|
};
|
|
1168
1383
|
|
|
1169
|
-
/**
|
|
1170
|
-
* @method CmdUnderpost
|
|
1171
|
-
* @description The command factory.
|
|
1172
|
-
* @memberof ServerConfBuilder
|
|
1173
|
-
* @namespace CmdUnderpost
|
|
1174
|
-
*/
|
|
1175
|
-
const Cmd = {
|
|
1176
|
-
/**
|
|
1177
|
-
* @method run
|
|
1178
|
-
* @description Runs the deploy.
|
|
1179
|
-
* @returns {string} - The run command.
|
|
1180
|
-
* @memberof Cmd
|
|
1181
|
-
*/
|
|
1182
|
-
run: () => `npm start`,
|
|
1183
|
-
/**
|
|
1184
|
-
* @method build
|
|
1185
|
-
* @description Builds the deploy.
|
|
1186
|
-
* @param {string} deployId - The deploy ID.
|
|
1187
|
-
* @returns {string} - The build command.
|
|
1188
|
-
* @memberof CmdUnderpost
|
|
1189
|
-
*/
|
|
1190
|
-
build: (deployId) => `node bin/deploy build-full-client ${deployId}`,
|
|
1191
|
-
/**
|
|
1192
|
-
* @method conf
|
|
1193
|
-
* @description Configures the deploy.
|
|
1194
|
-
* @param {string} deployId - The deploy ID.
|
|
1195
|
-
* @param {string} env - The environment.
|
|
1196
|
-
* @returns {string} - The conf command.
|
|
1197
|
-
* @memberof CmdUnderpost
|
|
1198
|
-
*/
|
|
1199
|
-
conf: (deployId, env) => `node bin/deploy conf ${deployId} ${env ? env : 'production'}`,
|
|
1200
|
-
/**
|
|
1201
|
-
* @method replica
|
|
1202
|
-
* @description Builds the replica.
|
|
1203
|
-
* @param {string} deployId - The deploy ID.
|
|
1204
|
-
* @param {string} host - The host.
|
|
1205
|
-
* @param {string} path - The path.
|
|
1206
|
-
* @returns {string} - The replica command.
|
|
1207
|
-
* @memberof CmdUnderpost
|
|
1208
|
-
*/
|
|
1209
|
-
replica: (deployId, host, path) => `node bin/deploy build-single-replica ${deployId} ${host} ${path}`,
|
|
1210
|
-
/**
|
|
1211
|
-
* @method syncPorts
|
|
1212
|
-
* @description Syncs the ports.
|
|
1213
|
-
* @returns {string} - The sync ports command.
|
|
1214
|
-
* @memberof CmdUnderpost
|
|
1215
|
-
*/
|
|
1216
|
-
syncPorts: () => `node bin/deploy sync-env-port`,
|
|
1217
|
-
};
|
|
1218
|
-
|
|
1219
1384
|
/**
|
|
1220
1385
|
* @method splitFileFactory
|
|
1221
1386
|
* @description Splits the file factory.
|
|
@@ -1336,8 +1501,25 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
|
|
|
1336
1501
|
md = md.replaceAll(oldVersion, newVersion);
|
|
1337
1502
|
fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
|
|
1338
1503
|
fs.writeFileSync(`./CLI-HELP.md`, md, 'utf8');
|
|
1339
|
-
|
|
1340
|
-
|
|
1504
|
+
|
|
1505
|
+
// Update README.md: replace version and CLI index section between comment tags
|
|
1506
|
+
let readme = fs.readFileSync(`./README.md`, 'utf8');
|
|
1507
|
+
readme = readme.replaceAll(oldVersion, newVersion);
|
|
1508
|
+
const cliStartTag = '<!-- cli-index-start -->';
|
|
1509
|
+
const cliEndTag = '<!-- cli-index-end -->';
|
|
1510
|
+
const startIdx = readme.indexOf(cliStartTag);
|
|
1511
|
+
const endIdx = readme.indexOf(cliEndTag);
|
|
1512
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
1513
|
+
readme =
|
|
1514
|
+
readme.substring(0, startIdx) +
|
|
1515
|
+
cliStartTag +
|
|
1516
|
+
'\n' +
|
|
1517
|
+
baseOptions +
|
|
1518
|
+
'\n' +
|
|
1519
|
+
cliEndTag +
|
|
1520
|
+
readme.substring(endIdx + cliEndTag.length);
|
|
1521
|
+
}
|
|
1522
|
+
fs.writeFileSync('./README.md', readme, 'utf8');
|
|
1341
1523
|
};
|
|
1342
1524
|
|
|
1343
1525
|
/**
|
|
@@ -1348,19 +1530,26 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
|
|
|
1348
1530
|
* @param {boolean} options.singleReplica - The single replica.
|
|
1349
1531
|
* @param {Array} options.replicas - The replicas.
|
|
1350
1532
|
* @param {string} options.redirect - The redirect.
|
|
1533
|
+
* @param {boolean} [options.peer=false] - Whether peer is enabled on the parent singleReplica path (used for port offset estimation when replica conf is not yet built).
|
|
1351
1534
|
* @returns {object} - The instance context.
|
|
1352
1535
|
* @memberof ServerConfBuilder
|
|
1353
1536
|
*/
|
|
1354
|
-
const getInstanceContext = async (options = { deployId, singleReplica, replicas, redirect: '' }) => {
|
|
1355
|
-
const { deployId, singleReplica, replicas, redirect } = options;
|
|
1537
|
+
const getInstanceContext = async (options = { deployId, singleReplica, replicas, redirect: '', peer: false }) => {
|
|
1538
|
+
const { deployId, singleReplica, replicas, redirect, peer } = options;
|
|
1356
1539
|
let singleReplicaOffsetPortSum = 0;
|
|
1357
1540
|
|
|
1358
1541
|
if (singleReplica && replicas && replicas.length > 0) {
|
|
1359
1542
|
for (const replica of replicas) {
|
|
1360
1543
|
const replicaDeployId = buildReplicaId({ deployId, replica });
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1544
|
+
const replicaConfPath = `./engine-private/replica/${replicaDeployId}/conf.server.json`;
|
|
1545
|
+
if (!fs.existsSync(replicaConfPath)) {
|
|
1546
|
+
// Replica folder not built yet (e.g. dev mode without prior build);
|
|
1547
|
+
// estimate port offset: 1 per replica path + 1 extra if peer is enabled on the parent singleReplica config
|
|
1548
|
+
singleReplicaOffsetPortSum++;
|
|
1549
|
+
if (peer) singleReplicaOffsetPortSum++;
|
|
1550
|
+
continue;
|
|
1551
|
+
}
|
|
1552
|
+
const confReplicaServer = loadConfServerJson(replicaConfPath);
|
|
1364
1553
|
for (const host of Object.keys(confReplicaServer)) {
|
|
1365
1554
|
for (const path of Object.keys(confReplicaServer[host])) {
|
|
1366
1555
|
singleReplicaOffsetPortSum++;
|
|
@@ -1480,15 +1669,7 @@ const isDeployRunnerContext = (path, options) => !options.build && path && path
|
|
|
1480
1669
|
* @returns {boolean} - The dev proxy context.
|
|
1481
1670
|
* @memberof ServerConfBuilder
|
|
1482
1671
|
*/
|
|
1483
|
-
const isDevProxyContext = () =>
|
|
1484
|
-
try {
|
|
1485
|
-
if (process.argv[2] === 'proxy') return true;
|
|
1486
|
-
if (!process.argv[6].startsWith('localhost')) return false;
|
|
1487
|
-
return new URL('http://' + process.argv[6]).hostname ? true : false;
|
|
1488
|
-
} catch {
|
|
1489
|
-
return false;
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1672
|
+
const isDevProxyContext = () => (process.argv.find((arg) => arg === 'proxy') ? true : false);
|
|
1492
1673
|
|
|
1493
1674
|
/**
|
|
1494
1675
|
* @method devProxyHostFactory
|
|
@@ -1501,10 +1682,14 @@ const isDevProxyContext = () => {
|
|
|
1501
1682
|
* @returns {string} - The dev proxy host.
|
|
1502
1683
|
* @memberof ServerConfBuilder
|
|
1503
1684
|
*/
|
|
1504
|
-
const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false, port: 80, tls: false }) =>
|
|
1505
|
-
|
|
1506
|
-
(options.port ? options.port : options.tls ? 443 : 80) + parseInt(process.env.DEV_PROXY_PORT_OFFSET)
|
|
1507
|
-
|
|
1685
|
+
const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false, port: 80, tls: false }) => {
|
|
1686
|
+
const resolvedPort =
|
|
1687
|
+
(options.port ? options.port : options.tls ? 443 : 80) + parseInt(process.env.DEV_PROXY_PORT_OFFSET);
|
|
1688
|
+
const isDefaultPort = (options.tls && resolvedPort === 443) || (!options.tls && resolvedPort === 80);
|
|
1689
|
+
const protocol = options.includeHttp ? (options.tls ? 'https://' : 'http://') : '';
|
|
1690
|
+
const hostname = options.host ? options.host : 'localhost';
|
|
1691
|
+
return `${protocol}${hostname}${isDefaultPort ? '' : `:${resolvedPort}`}`;
|
|
1692
|
+
};
|
|
1508
1693
|
|
|
1509
1694
|
/**
|
|
1510
1695
|
* @method isTlsDevProxy
|
|
@@ -1512,7 +1697,7 @@ const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false
|
|
|
1512
1697
|
* @returns {boolean} - The TLS dev proxy status.
|
|
1513
1698
|
* @memberof ServerConfBuilder
|
|
1514
1699
|
*/
|
|
1515
|
-
const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && process.argv
|
|
1700
|
+
const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && !!process.argv.find((arg) => arg === 'tls');
|
|
1516
1701
|
|
|
1517
1702
|
/**
|
|
1518
1703
|
* @method getTlsHosts
|
|
@@ -1524,17 +1709,52 @@ const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && process.arg
|
|
|
1524
1709
|
const getTlsHosts = (confServer) =>
|
|
1525
1710
|
Array.from(new Set(Object.keys(confServer).map((h) => new URL('https://' + h).hostname)));
|
|
1526
1711
|
|
|
1712
|
+
/**
|
|
1713
|
+
* Reads a `conf.server.json` file from disk, parses it, and resolves all `env:` secret
|
|
1714
|
+
* references using {@link resolveConfSecrets}.
|
|
1715
|
+
*
|
|
1716
|
+
* Reads and parses a `conf.server.json` file from disk. The `env:` secret
|
|
1717
|
+
* references are **preserved** by default so that build/deploy tooling never
|
|
1718
|
+
* accidentally strips them. Callers that need the actual secret values
|
|
1719
|
+
* (e.g. database or mailer modules) should explicitly wrap the result with
|
|
1720
|
+
* {@link resolveConfSecrets}.
|
|
1721
|
+
*
|
|
1722
|
+
* @method loadConfServerJson
|
|
1723
|
+
* @param {string} jsonPath - Absolute or relative path to the `conf.server.json` file.
|
|
1724
|
+
* @param {object} [options] - Optional settings.
|
|
1725
|
+
* @param {boolean} [options.resolve=false] - When `true`, resolves `env:` references
|
|
1726
|
+
* via {@link resolveConfSecrets} before returning.
|
|
1727
|
+
* @returns {object} The parsed server configuration object (secrets unresolved unless
|
|
1728
|
+
* `options.resolve` is `true`).
|
|
1729
|
+
* @throws {Error} If the file does not exist or cannot be parsed.
|
|
1730
|
+
* @memberof ServerConfBuilder
|
|
1731
|
+
*
|
|
1732
|
+
* @example
|
|
1733
|
+
* // Structure-only read (env: strings preserved)
|
|
1734
|
+
* const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
|
|
1735
|
+
*
|
|
1736
|
+
* @example
|
|
1737
|
+
* // Resolved read (env: strings replaced with process.env values)
|
|
1738
|
+
* const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`, { resolve: true });
|
|
1739
|
+
*/
|
|
1740
|
+
const loadConfServerJson = (jsonPath, options) => {
|
|
1741
|
+
if (!fs.existsSync(jsonPath)) {
|
|
1742
|
+
throw new Error(`loadConfServerJson: configuration file not found: ${jsonPath}`);
|
|
1743
|
+
}
|
|
1744
|
+
const raw = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
|
1745
|
+
return options && options.resolve === true ? resolveConfSecrets(raw) : raw;
|
|
1746
|
+
};
|
|
1747
|
+
|
|
1527
1748
|
export {
|
|
1528
|
-
Cmd,
|
|
1529
1749
|
Config,
|
|
1530
1750
|
loadConf,
|
|
1531
1751
|
loadReplicas,
|
|
1532
1752
|
cloneConf,
|
|
1533
1753
|
getCapVariableName,
|
|
1754
|
+
addClientConf,
|
|
1534
1755
|
buildClientSrc,
|
|
1535
1756
|
buildApiSrc,
|
|
1536
1757
|
addApiConf,
|
|
1537
|
-
addClientConf,
|
|
1538
1758
|
addWsConf,
|
|
1539
1759
|
buildWsSrc,
|
|
1540
1760
|
cloneSrcComponents,
|
|
@@ -1542,7 +1762,6 @@ export {
|
|
|
1542
1762
|
getDataDeploy,
|
|
1543
1763
|
validateTemplatePath,
|
|
1544
1764
|
buildReplicaId,
|
|
1545
|
-
getCronBackUpFolder,
|
|
1546
1765
|
mergeFile,
|
|
1547
1766
|
getPathsSSR,
|
|
1548
1767
|
buildKindPorts,
|
|
@@ -1564,4 +1783,12 @@ export {
|
|
|
1564
1783
|
devProxyHostFactory,
|
|
1565
1784
|
isTlsDevProxy,
|
|
1566
1785
|
getTlsHosts,
|
|
1786
|
+
resolveConfSecrets,
|
|
1787
|
+
loadConfServerJson,
|
|
1788
|
+
getConfFolder,
|
|
1789
|
+
getConfFilePath,
|
|
1790
|
+
readConfJson,
|
|
1791
|
+
DEFAULT_DEPLOY_ID,
|
|
1792
|
+
loadCronDeployEnv,
|
|
1793
|
+
cronDeployIdResolve,
|
|
1567
1794
|
};
|