cyberia 3.0.3 → 3.1.3

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.
Files changed (160) hide show
  1. package/{.env.production → .env.example} +20 -2
  2. package/.github/workflows/engine-cyberia.cd.yml +41 -10
  3. package/.github/workflows/engine-cyberia.ci.yml +53 -14
  4. package/.github/workflows/ghpkg.ci.yml +1 -1
  5. package/.github/workflows/gitlab.ci.yml +1 -1
  6. package/.github/workflows/hardhat.ci.yml +82 -0
  7. package/.github/workflows/npmpkg.ci.yml +37 -8
  8. package/.github/workflows/publish.ci.yml +5 -5
  9. package/.github/workflows/publish.cyberia.ci.yml +5 -5
  10. package/.github/workflows/pwa-microservices-template-page.cd.yml +3 -3
  11. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  12. package/.github/workflows/release.cd.yml +3 -2
  13. package/.vscode/extensions.json +9 -8
  14. package/.vscode/settings.json +3 -2
  15. package/CHANGELOG.md +211 -1
  16. package/CLI-HELP.md +78 -53
  17. package/WHITE-PAPER.md +1540 -0
  18. package/bin/build.js +16 -10
  19. package/bin/cyberia.js +861 -4
  20. package/bin/deploy.js +103 -270
  21. package/bin/file.js +2 -1
  22. package/bin/index.js +861 -4
  23. package/bin/vs.js +3 -3
  24. package/conf.js +105 -97
  25. package/deployment.yaml +148 -4
  26. package/hardhat/.env.example +31 -0
  27. package/hardhat/README.md +531 -0
  28. package/hardhat/WHITE-PAPER.md +1540 -0
  29. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  30. package/hardhat/deployments/.gitkeep +0 -0
  31. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  32. package/hardhat/hardhat.config.js +136 -0
  33. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  34. package/hardhat/networks/besu-object-layer.network.json +138 -0
  35. package/hardhat/package-lock.json +7628 -0
  36. package/hardhat/package.json +45 -0
  37. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  38. package/hardhat/test/ObjectLayerToken.js +590 -0
  39. package/jsdoc.dd-cyberia.json +59 -0
  40. package/jsdoc.json +20 -13
  41. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  42. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  43. package/manifests/deployment/dd-cyberia-development/deployment.yaml +490 -0
  44. package/manifests/deployment/dd-cyberia-development/proxy.yaml +261 -0
  45. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
  46. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  47. package/manifests/deployment/dd-test-development/deployment.yaml +52 -52
  48. package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
  49. package/manifests/pv-pvc-dd.yaml +1 -1
  50. package/package.json +50 -44
  51. package/proxy.yaml +79 -7
  52. package/pv-pvc.yaml +132 -0
  53. package/scripts/k3s-node-setup.sh +1 -1
  54. package/scripts/ports-ls.sh +2 -0
  55. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +3 -1
  56. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +1 -2
  57. package/src/api/document/document.service.js +1 -1
  58. package/src/api/file/file.controller.js +3 -1
  59. package/src/api/file/file.service.js +28 -5
  60. package/src/api/ipfs/ipfs.service.js +2 -2
  61. package/src/api/object-layer/object-layer.controller.js +6 -2
  62. package/src/api/object-layer/object-layer.model.js +12 -8
  63. package/src/api/object-layer/object-layer.router.js +668 -42
  64. package/src/api/object-layer/object-layer.service.js +6 -7
  65. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
  66. package/src/api/user/user.router.js +10 -5
  67. package/src/api/user/user.service.js +7 -7
  68. package/src/cli/baremetal.js +6 -10
  69. package/src/cli/cloud-init.js +0 -3
  70. package/src/cli/db.js +54 -71
  71. package/src/cli/deploy.js +64 -12
  72. package/src/cli/env.js +5 -5
  73. package/src/cli/fs.js +0 -2
  74. package/src/cli/image.js +0 -3
  75. package/src/cli/index.js +35 -13
  76. package/src/cli/monitor.js +5 -6
  77. package/src/cli/repository.js +329 -46
  78. package/src/cli/run.js +180 -120
  79. package/src/cli/secrets.js +1 -3
  80. package/src/cli/ssh.js +1 -1
  81. package/src/client/Itemledger.index.js +1 -959
  82. package/src/client/components/core/AgGrid.js +20 -5
  83. package/src/client/components/core/Alert.js +2 -2
  84. package/src/client/components/core/Content.js +22 -3
  85. package/src/client/components/core/Docs.js +30 -6
  86. package/src/client/components/core/FileExplorer.js +71 -4
  87. package/src/client/components/core/Input.js +1 -1
  88. package/src/client/components/core/Modal.js +20 -6
  89. package/src/client/components/core/RichText.js +1 -2
  90. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +1 -0
  91. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
  92. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +0 -1
  93. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +64 -2
  94. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +1 -0
  95. package/src/client/components/underpost/CssUnderpost.js +59 -0
  96. package/src/client/components/underpost/LogInUnderpost.js +3 -0
  97. package/src/client/components/underpost/LogOutUnderpost.js +2 -0
  98. package/src/client/components/underpost/MenuUnderpost.js +99 -13
  99. package/src/client/components/underpost/RoutesUnderpost.js +2 -0
  100. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  101. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  102. package/src/client/public/cryptokoyn/microdata.json +85 -0
  103. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  104. package/src/client/public/cryptokoyn/sitemap +3 -3
  105. package/src/client/public/default/sitemap +3 -3
  106. package/src/client/public/itemledger/browserconfig.xml +2 -2
  107. package/src/client/public/itemledger/manifest.webmanifest +4 -4
  108. package/src/client/public/itemledger/microdata.json +71 -0
  109. package/src/client/public/itemledger/sitemap +3 -3
  110. package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
  111. package/src/client/public/test/sitemap +3 -3
  112. package/src/client/ssr/body/404.js +15 -11
  113. package/src/client/ssr/body/500.js +15 -11
  114. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  115. package/src/client/ssr/head/PwaItemledger.js +60 -0
  116. package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
  117. package/src/client/ssr/pages/Test.js +11 -10
  118. package/src/client.build.js +0 -3
  119. package/src/client.dev.js +0 -3
  120. package/src/db/DataBaseProvider.js +17 -2
  121. package/src/db/mariadb/MariaDB.js +14 -9
  122. package/src/db/mongo/MongooseDB.js +17 -1
  123. package/src/index.js +1 -1
  124. package/src/proxy.js +0 -3
  125. package/src/runtime/express/Express.js +15 -9
  126. package/src/runtime/lampp/Lampp.js +6 -13
  127. package/src/server/auth.js +12 -14
  128. package/src/server/backup.js +2 -3
  129. package/src/server/besu-genesis-generator.js +1630 -0
  130. package/src/server/client-build-docs.js +126 -17
  131. package/src/server/client-build-live.js +9 -18
  132. package/src/server/client-build.js +203 -75
  133. package/src/server/client-dev-server.js +14 -13
  134. package/src/server/conf.js +376 -164
  135. package/src/server/cron.js +2 -1
  136. package/src/server/dns.js +28 -12
  137. package/src/server/downloader.js +0 -2
  138. package/src/server/logger.js +27 -9
  139. package/src/server/object-layer.js +79 -6
  140. package/src/server/peer.js +0 -2
  141. package/src/server/process.js +1 -50
  142. package/src/server/proxy.js +4 -8
  143. package/src/server/runtime.js +5 -8
  144. package/src/server/ssr.js +0 -3
  145. package/src/server/start.js +19 -12
  146. package/src/server/tls.js +0 -2
  147. package/src/server.js +0 -4
  148. package/.env.development +0 -43
  149. package/.env.test +0 -43
  150. package/hardhat/contracts/CryptoKoyn.sol +0 -59
  151. package/hardhat/contracts/ItemLedger.sol +0 -73
  152. package/hardhat/contracts/Lock.sol +0 -34
  153. package/hardhat/hardhat.config.cjs +0 -45
  154. package/hardhat/ignition/modules/Lock.js +0 -18
  155. package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
  156. package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
  157. package/hardhat/scripts/deployItemledger.cjs +0 -25
  158. package/hardhat/test/Lock.js +0 -126
  159. package/hardhat/white-paper.md +0 -581
  160. package/white-paper.md +0 -581
@@ -26,10 +26,235 @@ 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
+ * Loads the deployment-specific `.env` file referenced by `engine-private/deploy/dd.cron`
153
+ * into `process.env`. Uses `NODE_ENV` to select the environment variant
154
+ * (defaults to `production`).
155
+ *
156
+ * Safe to call multiple times; subsequent calls are no-ops once the env is loaded.
157
+ *
158
+ * @method loadCronDeployEnv
159
+ * @memberof ServerConfBuilder
160
+ */
161
+ function loadCronDeployEnv() {
162
+ const envName = process.env.NODE_ENV || 'production';
163
+
164
+ // 1) Load dd.cron env (takes full precedence)
165
+ const cronDeployFile = './engine-private/deploy/dd.cron';
166
+ if (fs.existsSync(cronDeployFile)) {
167
+ const cronDeployId = fs.readFileSync(cronDeployFile, 'utf8').trim();
168
+ if (cronDeployId) {
169
+ const cronEnvPath = `./engine-private/conf/${cronDeployId}/.env.${envName}`;
170
+ if (fs.existsSync(cronEnvPath)) {
171
+ const cronEnv = dotenv.parse(fs.readFileSync(cronEnvPath, 'utf8'));
172
+ process.env = { ...process.env, ...cronEnv };
173
+ }
174
+ }
175
+ }
176
+
177
+ // 2) Load dd.router envs — only keys not already present
178
+ const routerDeployFile = './engine-private/deploy/dd.router';
179
+ if (fs.existsSync(routerDeployFile)) {
180
+ const routerIds = fs.readFileSync(routerDeployFile, 'utf8').trim().split(',');
181
+ for (const deployId of routerIds) {
182
+ const id = deployId.trim();
183
+ if (!id) continue;
184
+ const envPath = `./engine-private/conf/${id}/.env.${envName}`;
185
+ if (!fs.existsSync(envPath)) continue;
186
+ const env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
187
+ for (const key of Object.keys(env)) {
188
+ if (!(key in process.env)) process.env[key] = env[key];
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Resolves the full path to a specific configuration JSON file for a deploy ID.
196
+ * For `server` configs in development mode with a subConf, it will prefer the
197
+ * dev-specific variant if it exists.
198
+ *
199
+ * @method getConfFilePath
200
+ * @param {string} deployId - The deploy ID.
201
+ * @param {string} confType - The configuration type (e.g. 'server', 'client', 'cron', 'ssr').
202
+ * @param {string} [subConf=''] - Optional sub-configuration identifier (used for dev server variants).
203
+ * @returns {string} The resolved path to the configuration JSON file.
204
+ * @memberof ServerConfBuilder
205
+ *
206
+ * @example
207
+ * getConfFilePath('dd-myapp', 'server');
208
+ * // => './engine-private/conf/dd-myapp/conf.server.json'
209
+ *
210
+ * @example
211
+ * // In development with subConf 'local':
212
+ * getConfFilePath('dd-myapp', 'server', 'local');
213
+ * // => './engine-private/conf/dd-myapp/conf.server.dev.local.json' (if it exists)
214
+ */
215
+ const getConfFilePath = (deployId, confType, subConf = '') => {
216
+ const folder = getConfFolder(deployId);
217
+ // When no explicit subConf is given, fall back to the env var set by loadConf()
218
+ const effectiveSubConf = subConf || process.env.DEPLOY_SUB_CONF || '';
219
+ if (confType === 'server' && effectiveSubConf) {
220
+ const devConfPath = `${folder}/conf.${confType}.dev.${effectiveSubConf}.json`;
221
+ if (fs.existsSync(devConfPath)) return devConfPath;
222
+ }
223
+ return `${folder}/conf.${confType}.json`;
224
+ };
225
+
226
+ /**
227
+ * Reads and parses a configuration JSON file for a given deploy ID and config type.
228
+ * Optionally resolves `env:` secret references and/or applies replica expansion.
229
+ *
230
+ * @method readConfJson
231
+ * @param {string} deployId - The deploy ID.
232
+ * @param {string} confType - The configuration type (e.g. 'server', 'client', 'cron', 'ssr').
233
+ * @param {object} [options={}] - Options.
234
+ * @param {string} [options.subConf=''] - Sub-configuration identifier for dev variants.
235
+ * @param {boolean} [options.resolve=false] - Whether to resolve `env:` references.
236
+ * @param {boolean} [options.loadReplicas=false] - Whether to expand replica entries (server configs).
237
+ * @returns {object} The parsed (and optionally resolved) configuration object.
238
+ * @memberof ServerConfBuilder
239
+ */
240
+ const readConfJson = (deployId, confType, options = {}) => {
241
+ const filePath = getConfFilePath(deployId, confType, options.subConf || '');
242
+ if (!fs.existsSync(filePath)) {
243
+ throw new Error(`readConfJson: configuration file not found: ${filePath}`);
244
+ }
245
+ let parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
246
+ if (options.loadReplicas && confType === 'server') parsed = loadReplicas(deployId, parsed);
247
+ if (options.resolve) parsed = resolveConfSecrets(parsed);
248
+ return parsed;
249
+ };
250
+
251
+ /**
252
+ * Default deploy ID used when no deploy ID is specified.
253
+ * @constant {string}
254
+ * @memberof ServerConfBuilder
255
+ */
256
+ const DEFAULT_DEPLOY_ID = 'dd-default';
257
+
33
258
  /**
34
259
  * @class Config
35
260
  * @description Manages the configuration of the server.
@@ -53,12 +278,13 @@ const Config = {
53
278
  * @param {string} [subConf=''] - The sub configuration.
54
279
  * @memberof ServerConfBuilder
55
280
  */
56
- build: async function (deployContext = 'dd-default', deployList, subConf) {
281
+ build: async function (deployContext = DEFAULT_DEPLOY_ID, deployList, subConf) {
57
282
  if (process.argv[2] && typeof process.argv[2] === 'string' && process.argv[2].startsWith('dd-'))
58
283
  deployContext = process.argv[2];
284
+ else if (deployContext !== 'proxy' && process.env.DEPLOY_ID && process.env.DEPLOY_ID.startsWith('dd-'))
285
+ deployContext = process.env.DEPLOY_ID;
59
286
  if (!subConf && process.argv[3] && typeof process.argv[3] === 'string') subConf = process.argv[3];
60
- if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`);
61
- if (!fs.existsSync(`./conf`)) fs.mkdirSync(`./conf`);
287
+
62
288
  Underpost.env.set('await-deploy', new Date().toISOString());
63
289
  if (deployContext.startsWith('dd-')) loadConf(deployContext, subConf);
64
290
  if (deployContext === 'proxy') await Config.buildProxy(deployList, subConf);
@@ -70,7 +296,7 @@ const Config = {
70
296
  * @param {object} [options={ subConf: '', cluster: false }] - The options.
71
297
  * @memberof ServerConfBuilder
72
298
  */
73
- deployIdFactory: function (deployId = 'dd-default', options = { subConf: '', cluster: false }) {
299
+ deployIdFactory: function (deployId = DEFAULT_DEPLOY_ID, options = { subConf: '', cluster: false }) {
74
300
  if (!deployId.startsWith('dd-')) deployId = `dd-${deployId}`;
75
301
 
76
302
  logger.info('Build deployId', deployId);
@@ -79,28 +305,39 @@ const Config = {
79
305
  const repoName = `engine-${deployId.split('dd-')[1]}`;
80
306
 
81
307
  if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
82
- fs.writeFileSync(
83
- `${folder}/.env.production`,
84
- fs.readFileSync('./.env.production', 'utf8').replaceAll('dd-default', deployId),
85
- 'utf8',
86
- );
87
- fs.writeFileSync(
88
- `${folder}/.env.development`,
89
- fs.readFileSync('./.env.development', 'utf8').replaceAll('dd-default', deployId),
90
- 'utf8',
91
- );
92
- fs.writeFileSync(
93
- `${folder}/.env.test`,
94
- fs.readFileSync('./.env.test', 'utf8').replaceAll('dd-default', deployId),
95
- 'utf8',
96
- );
308
+
309
+ const envTemplate = fs.existsSync('./.env.example')
310
+ ? fs.readFileSync('./.env.example', 'utf8')
311
+ : fs.existsSync('./.env.production')
312
+ ? fs.readFileSync('./.env.production', 'utf8')
313
+ : '';
314
+
315
+ if (envTemplate) {
316
+ const prodEnv = envTemplate.replaceAll('dd-default', deployId);
317
+ fs.writeFileSync(`${folder}/.env.production`, prodEnv, 'utf8');
318
+ fs.writeFileSync(
319
+ `${folder}/.env.development`,
320
+ prodEnv.replace('NODE_ENV=production', 'NODE_ENV=development').replace('PORT=3000', 'PORT=4000'),
321
+ 'utf8',
322
+ );
323
+ fs.writeFileSync(
324
+ `${folder}/.env.test`,
325
+ prodEnv.replace('NODE_ENV=production', 'NODE_ENV=test').replace('PORT=3000', 'PORT=5000'),
326
+ 'utf8',
327
+ );
328
+ }
329
+
97
330
  fs.writeFileSync(
98
331
  `${folder}/package.json`,
99
332
  fs.readFileSync('./package.json', 'utf8').replaceAll('dd-default', deployId),
100
333
  'utf8',
101
334
  );
102
335
 
103
- this.buildTmpConf(folder);
336
+ // Write default conf JSON files if they don't exist
337
+ for (const confType of Object.keys(this.default)) {
338
+ const confPath = `${folder}/conf.${confType}.json`;
339
+ if (!fs.existsSync(confPath)) fs.writeFileSync(confPath, JSON.stringify(this.default[confType], null, 4), 'utf8');
340
+ }
104
341
 
105
342
  if (options.subConf) {
106
343
  logger.info('Creating sub conf', {
@@ -127,38 +364,17 @@ const Config = {
127
364
  shellExec(`node bin new --default-conf --deploy-id ${deployId}`);
128
365
 
129
366
  if (!fs.existsSync(`./engine-private/deploy/dd.router`))
130
- fs.writeFileSync(`./engine-private/deploy/dd.router`, '', 'utf8');
131
-
132
- fs.writeFileSync(
133
- `./engine-private/deploy/dd.router`,
134
- fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').trim() + `,${deployId}`,
135
- 'utf8',
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}"`,
367
+ fs.writeFileSync(`./engine-private/deploy/dd.router`, deployId, 'utf8');
368
+ else
369
+ fs.writeFileSync(
370
+ `./engine-private/deploy/dd.router`,
371
+ fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').trim() + `,${deployId}`,
372
+ 'utf8',
141
373
  );
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
374
  }
149
375
 
150
376
  return { deployIdFolder: folder, deployId };
151
377
  },
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
378
  /**
163
379
  * @method buildProxyByDeployId
164
380
  * @description Builds the proxy by deploy ID.
@@ -178,7 +394,7 @@ const Config = {
178
394
  )
179
395
  confPath = `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
180
396
 
181
- const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
397
+ const serverConf = loadConfServerJson(confPath);
182
398
 
183
399
  for (const host of Object.keys(loadReplicas(deployId, serverConf)))
184
400
  this.default.server[host] = {
@@ -206,7 +422,6 @@ const Config = {
206
422
  }
207
423
  }
208
424
  }
209
- this.buildTmpConf();
210
425
  },
211
426
  };
212
427
 
@@ -217,7 +432,7 @@ const Config = {
217
432
  * @param {string} [subConf=''] - The sub configuration.
218
433
  * @memberof ServerConfBuilder
219
434
  */
220
- const loadConf = (deployId = 'dd-default', subConf) => {
435
+ const loadConf = (deployId = DEFAULT_DEPLOY_ID, subConf) => {
221
436
  if (deployId === 'current') {
222
437
  console.log(process.env.DEPLOY_ID);
223
438
  return;
@@ -225,20 +440,19 @@ const loadConf = (deployId = 'dd-default', subConf) => {
225
440
  if (deployId === 'clean') {
226
441
  const path = '.';
227
442
  fs.removeSync(`${path}/.env`);
228
- shellExec(`git checkout ${path}/.env.production`);
229
- shellExec(`git checkout ${path}/.env.development`);
230
- shellExec(`git checkout ${path}/.env.test`);
443
+ fs.removeSync(`${path}/.env.production`);
444
+ fs.removeSync(`${path}/.env.development`);
445
+ fs.removeSync(`${path}/.env.test`);
231
446
  if (fs.existsSync(`${path}/jsdoc.json`)) shellExec(`git checkout ${path}/jsdoc.json`);
232
447
  shellExec(`git checkout ${path}/package.json`);
233
448
  shellExec(`git checkout ${path}/package-lock.json`);
234
449
  return;
235
450
  }
236
- const folder = fs.existsSync(`./engine-private/replica/${deployId}`)
237
- ? `./engine-private/replica/${deployId}`
238
- : `./engine-private/conf/${deployId}`;
451
+ const folder = getConfFolder(deployId);
452
+
239
453
  if (!fs.existsSync(folder)) Config.deployIdFactory(deployId);
240
- if (!fs.existsSync(`./conf`)) fs.mkdirSync(`./conf`);
241
- if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`);
454
+
455
+ if (subConf) process.env.DEPLOY_SUB_CONF = subConf;
242
456
 
243
457
  for (const typeConf of Object.keys(Config.default)) {
244
458
  let srcConf = fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8');
@@ -246,13 +460,14 @@ const loadConf = (deployId = 'dd-default', subConf) => {
246
460
  const devConfPath = `${folder}/conf.${typeConf}.dev${subConf ? `.${subConf}` : ''}.json`;
247
461
  if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
248
462
  }
249
- if (typeConf === 'server') srcConf = JSON.stringify(loadReplicas(deployId, JSON.parse(srcConf)), null, 4);
250
- fs.writeFileSync(`./conf/conf.${typeConf}.json`, srcConf, 'utf8');
463
+ let parsed = JSON.parse(srcConf);
464
+ if (typeConf === 'server') parsed = loadReplicas(deployId, parsed);
465
+ Config.default[typeConf] = parsed;
251
466
  }
252
467
  fs.writeFileSync(`./.env.production`, fs.readFileSync(`${folder}/.env.production`, 'utf8'), 'utf8');
253
468
  fs.writeFileSync(`./.env.development`, fs.readFileSync(`${folder}/.env.development`, 'utf8'), 'utf8');
254
469
  fs.writeFileSync(`./.env.test`, fs.readFileSync(`${folder}/.env.test`, 'utf8'), 'utf8');
255
- const NODE_ENV = process.env.NODE_ENV;
470
+ const NODE_ENV = process.env.NODE_ENV || 'development';
256
471
  if (NODE_ENV) {
257
472
  const subPathEnv = fs.existsSync(`${folder}/.env.${NODE_ENV}.${subConf}`)
258
473
  ? `${folder}/.env.${NODE_ENV}.${subConf}`
@@ -644,7 +859,7 @@ const cloneSrcComponents = async ({ toOptions, fromOptions }) => {
644
859
  * @memberof ServerConfBuilder
645
860
  */
646
861
  const buildProxyRouter = () => {
647
- const confServer = JSON.parse(fs.readFileSync(`./conf/conf.server.json`, 'utf8'));
862
+ const confServer = newInstance(Config.default.server);
648
863
  let currentPort = parseInt(process.env.PORT) + 1;
649
864
  const proxyRouter = {};
650
865
  for (const host of Object.keys(confServer)) {
@@ -726,9 +941,7 @@ const pathPortAssignmentFactory = async (deployId, router, confServer) => {
726
941
  const singleReplicas = await fs.readdir(`./engine-private/replica`);
727
942
  for (let replica of singleReplicas) {
728
943
  if (replica.startsWith(deployId)) {
729
- const replicaServerConf = JSON.parse(
730
- fs.readFileSync(`./engine-private/replica/${replica}/conf.server.json`, 'utf8'),
731
- );
944
+ const replicaServerConf = loadConfServerJson(`./engine-private/replica/${replica}/conf.server.json`);
732
945
  for (const host of Object.keys(replicaServerConf)) {
733
946
  const pathPortAssignment = [];
734
947
  for (const path of Object.keys(replicaServerConf[host])) {
@@ -906,7 +1119,7 @@ const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1
906
1119
  * @returns {object} - The data deploy.
907
1120
  * @memberof ServerConfBuilder
908
1121
  */
909
- const getDataDeploy = (
1122
+ const getDataDeploy = async (
910
1123
  options = {
911
1124
  buildSingleReplica: false,
912
1125
  disableSyncEnvPort: false,
@@ -931,13 +1144,16 @@ const getDataDeploy = (
931
1144
  for (const deployObj of dataDeploy) {
932
1145
  const serverConf = loadReplicas(
933
1146
  deployObj.deployId,
934
- JSON.parse(fs.readFileSync(`./engine-private/conf/${deployObj.deployId}/conf.server.json`, 'utf8')),
1147
+ loadConfServerJson(`./engine-private/conf/${deployObj.deployId}/conf.server.json`),
935
1148
  );
936
1149
  let replicaDataDeploy = [];
937
1150
  for (const host of Object.keys(serverConf))
938
1151
  for (const path of Object.keys(serverConf[host])) {
939
1152
  if (serverConf[host][path].replicas && serverConf[host][path].singleReplica) {
940
- if (options && options.buildSingleReplica) shellExec(Cmd.replica(deployObj.deployId, host, path));
1153
+ if (options && options.buildSingleReplica)
1154
+ await Underpost.repo.client(deployObj.deployId, '', host, path, {
1155
+ singleReplica: true,
1156
+ });
941
1157
  replicaDataDeploy = replicaDataDeploy.concat(
942
1158
  serverConf[host][path].replicas.map((r) => {
943
1159
  return {
@@ -952,7 +1168,8 @@ const getDataDeploy = (
952
1168
  if (replicaDataDeploy.length > 0) buildDataDeploy = buildDataDeploy.concat(replicaDataDeploy);
953
1169
  }
954
1170
 
955
- if (!options.disableSyncEnvPort && options.buildSingleReplica) shellExec(Cmd.syncPorts());
1171
+ if (!options.disableSyncEnvPort && options.buildSingleReplica)
1172
+ await Underpost.repo.client(undefined, '', '', '', { syncEnvPort: true });
956
1173
 
957
1174
  logger.info('Deployments configured', buildDataDeploy);
958
1175
 
@@ -980,6 +1197,7 @@ const validateTemplatePath = (absolutePath = '') => {
980
1197
  return false;
981
1198
  }
982
1199
  if (absolutePath.match('conf.dd-') && absolutePath.match('.js')) return false;
1200
+ if (absolutePath.match('jsdoc.dd-') && absolutePath.match('.json')) return false;
983
1201
  if (
984
1202
  absolutePath.match('src/client/services/') &&
985
1203
  !clients.find((p) => absolutePath.match(`src/client/services/${p}/`))
@@ -1057,18 +1275,6 @@ const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
1057
1275
  if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor();
1058
1276
  };
1059
1277
 
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
1278
  /**
1073
1279
  * @method mergeFile
1074
1280
  * @description Merges the file.
@@ -1102,10 +1308,7 @@ const mergeFile = async (parts = [], outputFilePath) => {
1102
1308
  * @memberof ServerConfBuilder
1103
1309
  */
1104
1310
  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
- );
1311
+ const confServer = loadReplicas(deployId, loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`));
1109
1312
  const hosts = {};
1110
1313
  for (const host of Object.keys(confServer)) {
1111
1314
  hosts[host] = {};
@@ -1116,9 +1319,7 @@ const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
1116
1319
  if (singleReplica) {
1117
1320
  for (const replica of replicas) {
1118
1321
  const deployIdReplica = buildReplicaId({ replica, deployId });
1119
- const confServerReplica = JSON.parse(
1120
- fs.readFileSync(`./engine-private/replica/${deployIdReplica}/conf.server.json`, 'utf8'),
1121
- );
1322
+ const confServerReplica = loadConfServerJson(`./engine-private/replica/${deployIdReplica}/conf.server.json`);
1122
1323
  for (const _host of Object.keys(confServerReplica)) {
1123
1324
  for (const _path of Object.keys(confServerReplica[_host])) {
1124
1325
  hosts[host][_path] = { replica: { host, path } };
@@ -1166,56 +1367,6 @@ const getPathsSSR = (conf) => {
1166
1367
  return paths;
1167
1368
  };
1168
1369
 
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
1370
  /**
1220
1371
  * @method splitFileFactory
1221
1372
  * @description Splits the file factory.
@@ -1336,8 +1487,25 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
1336
1487
  md = md.replaceAll(oldVersion, newVersion);
1337
1488
  fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
1338
1489
  fs.writeFileSync(`./CLI-HELP.md`, md, 'utf8');
1339
- const readme = fs.readFileSync(`./README.md`, 'utf8');
1340
- fs.writeFileSync('./README.md', readme.replaceAll(oldVersion, newVersion), 'utf8');
1490
+
1491
+ // Update README.md: replace version and CLI index section between comment tags
1492
+ let readme = fs.readFileSync(`./README.md`, 'utf8');
1493
+ readme = readme.replaceAll(oldVersion, newVersion);
1494
+ const cliStartTag = '<!-- cli-index-start -->';
1495
+ const cliEndTag = '<!-- cli-index-end -->';
1496
+ const startIdx = readme.indexOf(cliStartTag);
1497
+ const endIdx = readme.indexOf(cliEndTag);
1498
+ if (startIdx !== -1 && endIdx !== -1) {
1499
+ readme =
1500
+ readme.substring(0, startIdx) +
1501
+ cliStartTag +
1502
+ '\n' +
1503
+ baseOptions +
1504
+ '\n' +
1505
+ cliEndTag +
1506
+ readme.substring(endIdx + cliEndTag.length);
1507
+ }
1508
+ fs.writeFileSync('./README.md', readme, 'utf8');
1341
1509
  };
1342
1510
 
1343
1511
  /**
@@ -1348,19 +1516,26 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
1348
1516
  * @param {boolean} options.singleReplica - The single replica.
1349
1517
  * @param {Array} options.replicas - The replicas.
1350
1518
  * @param {string} options.redirect - The redirect.
1519
+ * @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
1520
  * @returns {object} - The instance context.
1352
1521
  * @memberof ServerConfBuilder
1353
1522
  */
1354
- const getInstanceContext = async (options = { deployId, singleReplica, replicas, redirect: '' }) => {
1355
- const { deployId, singleReplica, replicas, redirect } = options;
1523
+ const getInstanceContext = async (options = { deployId, singleReplica, replicas, redirect: '', peer: false }) => {
1524
+ const { deployId, singleReplica, replicas, redirect, peer } = options;
1356
1525
  let singleReplicaOffsetPortSum = 0;
1357
1526
 
1358
1527
  if (singleReplica && replicas && replicas.length > 0) {
1359
1528
  for (const replica of replicas) {
1360
1529
  const replicaDeployId = buildReplicaId({ deployId, replica });
1361
- const confReplicaServer = JSON.parse(
1362
- fs.readFileSync(`./engine-private/replica/${replicaDeployId}/conf.server.json`, 'utf8'),
1363
- );
1530
+ const replicaConfPath = `./engine-private/replica/${replicaDeployId}/conf.server.json`;
1531
+ if (!fs.existsSync(replicaConfPath)) {
1532
+ // Replica folder not built yet (e.g. dev mode without prior build);
1533
+ // estimate port offset: 1 per replica path + 1 extra if peer is enabled on the parent singleReplica config
1534
+ singleReplicaOffsetPortSum++;
1535
+ if (peer) singleReplicaOffsetPortSum++;
1536
+ continue;
1537
+ }
1538
+ const confReplicaServer = loadConfServerJson(replicaConfPath);
1364
1539
  for (const host of Object.keys(confReplicaServer)) {
1365
1540
  for (const path of Object.keys(confReplicaServer[host])) {
1366
1541
  singleReplicaOffsetPortSum++;
@@ -1480,15 +1655,7 @@ const isDeployRunnerContext = (path, options) => !options.build && path && path
1480
1655
  * @returns {boolean} - The dev proxy context.
1481
1656
  * @memberof ServerConfBuilder
1482
1657
  */
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
- };
1658
+ const isDevProxyContext = () => (process.argv.find((arg) => arg === 'proxy') ? true : false);
1492
1659
 
1493
1660
  /**
1494
1661
  * @method devProxyHostFactory
@@ -1501,10 +1668,14 @@ const isDevProxyContext = () => {
1501
1668
  * @returns {string} - The dev proxy host.
1502
1669
  * @memberof ServerConfBuilder
1503
1670
  */
1504
- const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false, port: 80, tls: false }) =>
1505
- `${options.includeHttp ? (options.tls ? 'https://' : 'http://') : ''}${options.host ? options.host : 'localhost'}:${
1506
- (options.port ? options.port : options.tls ? 443 : 80) + parseInt(process.env.DEV_PROXY_PORT_OFFSET)
1507
- }`;
1671
+ const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false, port: 80, tls: false }) => {
1672
+ const resolvedPort =
1673
+ (options.port ? options.port : options.tls ? 443 : 80) + parseInt(process.env.DEV_PROXY_PORT_OFFSET);
1674
+ const isDefaultPort = (options.tls && resolvedPort === 443) || (!options.tls && resolvedPort === 80);
1675
+ const protocol = options.includeHttp ? (options.tls ? 'https://' : 'http://') : '';
1676
+ const hostname = options.host ? options.host : 'localhost';
1677
+ return `${protocol}${hostname}${isDefaultPort ? '' : `:${resolvedPort}`}`;
1678
+ };
1508
1679
 
1509
1680
  /**
1510
1681
  * @method isTlsDevProxy
@@ -1512,7 +1683,7 @@ const devProxyHostFactory = (options = { host: 'default.net', includeHttp: false
1512
1683
  * @returns {boolean} - The TLS dev proxy status.
1513
1684
  * @memberof ServerConfBuilder
1514
1685
  */
1515
- const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && process.argv[7] === 'tls';
1686
+ const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && !!process.argv.find((arg) => arg === 'tls');
1516
1687
 
1517
1688
  /**
1518
1689
  * @method getTlsHosts
@@ -1524,17 +1695,52 @@ const isTlsDevProxy = () => process.env.NODE_ENV !== 'production' && process.arg
1524
1695
  const getTlsHosts = (confServer) =>
1525
1696
  Array.from(new Set(Object.keys(confServer).map((h) => new URL('https://' + h).hostname)));
1526
1697
 
1698
+ /**
1699
+ * Reads a `conf.server.json` file from disk, parses it, and resolves all `env:` secret
1700
+ * references using {@link resolveConfSecrets}.
1701
+ *
1702
+ * Reads and parses a `conf.server.json` file from disk. The `env:` secret
1703
+ * references are **preserved** by default so that build/deploy tooling never
1704
+ * accidentally strips them. Callers that need the actual secret values
1705
+ * (e.g. database or mailer modules) should explicitly wrap the result with
1706
+ * {@link resolveConfSecrets}.
1707
+ *
1708
+ * @method loadConfServerJson
1709
+ * @param {string} jsonPath - Absolute or relative path to the `conf.server.json` file.
1710
+ * @param {object} [options] - Optional settings.
1711
+ * @param {boolean} [options.resolve=false] - When `true`, resolves `env:` references
1712
+ * via {@link resolveConfSecrets} before returning.
1713
+ * @returns {object} The parsed server configuration object (secrets unresolved unless
1714
+ * `options.resolve` is `true`).
1715
+ * @throws {Error} If the file does not exist or cannot be parsed.
1716
+ * @memberof ServerConfBuilder
1717
+ *
1718
+ * @example
1719
+ * // Structure-only read (env: strings preserved)
1720
+ * const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
1721
+ *
1722
+ * @example
1723
+ * // Resolved read (env: strings replaced with process.env values)
1724
+ * const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`, { resolve: true });
1725
+ */
1726
+ const loadConfServerJson = (jsonPath, options) => {
1727
+ if (!fs.existsSync(jsonPath)) {
1728
+ throw new Error(`loadConfServerJson: configuration file not found: ${jsonPath}`);
1729
+ }
1730
+ const raw = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
1731
+ return options && options.resolve === true ? resolveConfSecrets(raw) : raw;
1732
+ };
1733
+
1527
1734
  export {
1528
- Cmd,
1529
1735
  Config,
1530
1736
  loadConf,
1531
1737
  loadReplicas,
1532
1738
  cloneConf,
1533
1739
  getCapVariableName,
1740
+ addClientConf,
1534
1741
  buildClientSrc,
1535
1742
  buildApiSrc,
1536
1743
  addApiConf,
1537
- addClientConf,
1538
1744
  addWsConf,
1539
1745
  buildWsSrc,
1540
1746
  cloneSrcComponents,
@@ -1542,7 +1748,6 @@ export {
1542
1748
  getDataDeploy,
1543
1749
  validateTemplatePath,
1544
1750
  buildReplicaId,
1545
- getCronBackUpFolder,
1546
1751
  mergeFile,
1547
1752
  getPathsSSR,
1548
1753
  buildKindPorts,
@@ -1564,4 +1769,11 @@ export {
1564
1769
  devProxyHostFactory,
1565
1770
  isTlsDevProxy,
1566
1771
  getTlsHosts,
1772
+ resolveConfSecrets,
1773
+ loadConfServerJson,
1774
+ getConfFolder,
1775
+ getConfFilePath,
1776
+ readConfJson,
1777
+ DEFAULT_DEPLOY_ID,
1778
+ loadCronDeployEnv,
1567
1779
  };