underpost 2.8.884 → 2.8.886

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 (82) hide show
  1. package/.env.production +3 -0
  2. package/.github/workflows/ghpkg.ci.yml +1 -1
  3. package/.github/workflows/npmpkg.ci.yml +1 -1
  4. package/.github/workflows/publish.ci.yml +5 -5
  5. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -1
  6. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  7. package/CHANGELOG.md +145 -1
  8. package/Dockerfile +1 -1
  9. package/README.md +5 -121
  10. package/bin/build.js +18 -9
  11. package/bin/deploy.js +102 -197
  12. package/bin/file.js +4 -6
  13. package/cli.md +16 -12
  14. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  15. package/manifests/deployment/dd-test-development/deployment.yaml +54 -54
  16. package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
  17. package/manifests/lxd/underpost-setup.sh +5 -5
  18. package/package.json +3 -3
  19. package/scripts/ssl.sh +164 -0
  20. package/src/cli/baremetal.js +7 -7
  21. package/src/cli/cloud-init.js +1 -1
  22. package/src/cli/cluster.js +31 -3
  23. package/src/cli/cron.js +9 -1
  24. package/src/cli/db.js +64 -2
  25. package/src/cli/deploy.js +189 -4
  26. package/src/cli/env.js +43 -0
  27. package/src/cli/fs.js +96 -2
  28. package/src/cli/image.js +15 -0
  29. package/src/cli/index.js +17 -4
  30. package/src/cli/monitor.js +33 -2
  31. package/src/cli/repository.js +95 -2
  32. package/src/cli/run.js +315 -51
  33. package/src/cli/script.js +32 -0
  34. package/src/cli/secrets.js +34 -0
  35. package/src/cli/test.js +42 -1
  36. package/src/client/components/core/Css.js +16 -8
  37. package/src/client/components/core/Docs.js +5 -13
  38. package/src/client/components/core/Modal.js +48 -29
  39. package/src/client/components/core/Router.js +6 -3
  40. package/src/client/components/core/Worker.js +205 -118
  41. package/src/client/components/core/windowGetDimensions.js +229 -162
  42. package/src/client/components/default/MenuDefault.js +1 -0
  43. package/src/client.dev.js +6 -3
  44. package/src/db/DataBaseProvider.js +65 -12
  45. package/src/db/mariadb/MariaDB.js +39 -6
  46. package/src/db/mongo/MongooseDB.js +51 -133
  47. package/src/index.js +2 -2
  48. package/src/mailer/EmailRender.js +58 -9
  49. package/src/mailer/MailerProvider.js +99 -25
  50. package/src/runtime/express/Express.js +32 -38
  51. package/src/runtime/lampp/Dockerfile +1 -1
  52. package/src/server/auth.js +9 -28
  53. package/src/server/backup.js +20 -0
  54. package/src/server/client-build-live.js +23 -12
  55. package/src/server/client-build.js +136 -91
  56. package/src/server/client-dev-server.js +35 -8
  57. package/src/server/client-icons.js +19 -0
  58. package/src/server/conf.js +543 -80
  59. package/src/server/dns.js +184 -42
  60. package/src/server/downloader.js +65 -24
  61. package/src/server/object-layer.js +260 -162
  62. package/src/server/peer.js +3 -9
  63. package/src/server/proxy.js +93 -76
  64. package/src/server/runtime.js +15 -21
  65. package/src/server/ssr.js +4 -4
  66. package/src/server/start.js +39 -0
  67. package/src/server/tls.js +251 -0
  68. package/src/server/valkey.js +11 -10
  69. package/src/ws/IoInterface.js +133 -39
  70. package/src/ws/IoServer.js +80 -31
  71. package/src/ws/core/core.ws.connection.js +50 -16
  72. package/src/ws/core/core.ws.emit.js +47 -8
  73. package/src/ws/core/core.ws.server.js +62 -10
  74. package/manifests/maas/lxd-preseed.yaml +0 -32
  75. package/src/server/ssl.js +0 -108
  76. /package/{manifests/maas → scripts}/device-scan.sh +0 -0
  77. /package/{manifests/maas → scripts}/gpu-diag.sh +0 -0
  78. /package/{manifests/maas → scripts}/maas-setup.sh +0 -0
  79. /package/{manifests/maas → scripts}/nat-iptables.sh +0 -0
  80. /package/{manifests/maas → scripts}/nvim.sh +0 -0
  81. /package/{manifests/maas → scripts}/snap-clean.sh +0 -0
  82. /package/{manifests/maas → scripts}/ssh-cluster-info.sh +0 -0
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Provides utilities for building, loading, and managing server configurations,
3
+ * deployment contexts, and service configurations (API, Client, WS).
4
+ * @module src/server/conf.js
5
+ * @namespace ServerConfBuilder
6
+ */
7
+
1
8
  import fs from 'fs-extra';
2
9
  import dotenv from 'dotenv';
3
10
  import {
@@ -22,17 +29,45 @@ dotenv.config();
22
29
 
23
30
  const logger = loggerFactory(import.meta);
24
31
 
32
+ /**
33
+ * @class Config
34
+ * @description Manages the configuration of the server.
35
+ * This class provides a set of static methods to automate various
36
+ * infrastructure operations, including NFS management, control server setup,
37
+ * and system provisioning for different architectures.
38
+ * @memberof ServerConfBuilder
39
+ */
25
40
  const Config = {
41
+ /**
42
+ * @method default
43
+ * @description The default configuration of the server.
44
+ * @memberof ServerConfBuilder
45
+ */
26
46
  default: DefaultConf,
47
+ /**
48
+ * @method build
49
+ * @description Builds the configuration of the server.
50
+ * @param {string} [deployContext='dd-default'] - The deploy context.
51
+ * @param {string} [deployList=''] - The deploy list.
52
+ * @param {string} [subConf=''] - The sub configuration.
53
+ * @memberof ServerConfBuilder
54
+ */
27
55
  build: async function (deployContext = 'dd-default', deployList, subConf) {
28
- if (typeof process.argv[2] === 'string' && process.argv[2].startsWith('dd-')) deployContext = process.argv[2];
56
+ if (process.argv[2] && typeof process.argv[2] === 'string' && process.argv[2].startsWith('dd-'))
57
+ deployContext = process.argv[2];
58
+ if (!subConf && process.argv[3] && typeof process.argv[3] === 'string') subConf = process.argv[3];
29
59
  if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`, { recursive: true });
30
60
  UnderpostRootEnv.API.set('await-deploy', new Date().toISOString());
31
- if (fs.existsSync(`./engine-private/replica/${deployContext}`))
32
- return loadConf(deployContext, process.env.NODE_ENV, subConf);
33
- else if (deployContext.startsWith('dd-')) return loadConf(deployContext, process.env.NODE_ENV, subConf);
34
- if (deployContext === 'proxy') Config.buildProxy(deployContext, deployList, subConf);
61
+ if (deployContext.startsWith('dd-')) loadConf(deployContext, subConf);
62
+ if (deployContext === 'proxy') await Config.buildProxy(deployList, subConf);
35
63
  },
64
+ /**
65
+ * @method deployIdFactory
66
+ * @description Creates a new deploy ID.
67
+ * @param {string} [deployId='dd-default'] - The deploy ID.
68
+ * @param {object} [options={ cluster: false }] - The options.
69
+ * @memberof ServerConfBuilder
70
+ */
36
71
  deployIdFactory: function (deployId = 'dd-default', options = { cluster: false }) {
37
72
  if (!deployId.startsWith('dd-')) deployId = `dd-${deployId}`;
38
73
 
@@ -101,50 +136,79 @@ const Config = {
101
136
 
102
137
  return { deployIdFolder: folder, deployId };
103
138
  },
139
+ /**
140
+ * @method buildTmpConf
141
+ * @description Builds the temporary configuration of the server.
142
+ * @param {string} [folder='./conf'] - The folder.
143
+ * @memberof ServerConfBuilder
144
+ */
104
145
  buildTmpConf: function (folder = './conf') {
105
146
  for (const confType of Object.keys(this.default))
106
147
  fs.writeFileSync(`${folder}/conf.${confType}.json`, JSON.stringify(this.default[confType], null, 4), 'utf8');
107
148
  },
108
- buildProxy: function (deployContext = 'dd-default', deployList, subConf) {
149
+ /**
150
+ * @method buildProxyByDeployId
151
+ * @description Builds the proxy by deploy ID.
152
+ * @param {string} [deployId='dd-default'] - The deploy ID.
153
+ * @param {string} [subConf=''] - The sub configuration.
154
+ * @memberof ServerConfBuilder
155
+ */
156
+ buildProxyByDeployId: function (deployId = 'dd-default', subConf = '') {
157
+ let confPath = `./engine-private/conf/${deployId}/conf.server.json`;
158
+ const privateConfDevPath = fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
159
+ ? `./engine-private/replica/${deployId}/conf.server.json`
160
+ : `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
161
+ const confDevPath = fs.existsSync(privateConfDevPath)
162
+ ? privateConfDevPath
163
+ : `./engine-private/conf/${deployId}/conf.server.dev.json`;
164
+
165
+ if (fs.existsSync(confDevPath)) confPath = confDevPath;
166
+ const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
167
+
168
+ for (const host of Object.keys(loadReplicas(serverConf)))
169
+ this.default.server[host] = {
170
+ ...this.default.server[host],
171
+ ...serverConf[host],
172
+ };
173
+ },
174
+ /**
175
+ * @method buildProxy
176
+ * @description Builds the proxy.
177
+ * @param {string} [deployList='dd-default'] - The deploy list.
178
+ * @param {string} [subConf=''] - The sub configuration.
179
+ * @memberof ServerConfBuilder
180
+ */
181
+ buildProxy: async function (deployList = 'dd-default', subConf = '') {
109
182
  if (!deployList) deployList = process.argv[3];
110
183
  if (!subConf) subConf = process.argv[4];
111
184
  this.default.server = {};
112
185
  for (const deployId of deployList.split(',')) {
113
- let confPath = `./engine-private/conf/${deployId}/conf.server.json`;
114
- const privateConfDevPath = fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
115
- ? `./engine-private/replica/${deployId}/conf.server.json`
116
- : `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
117
- const confDevPath = fs.existsSync(privateConfDevPath)
118
- ? privateConfDevPath
119
- : `./engine-private/conf/${deployId}/conf.server.dev.json`;
120
-
121
- if (process.env.NODE_ENV === 'development' && fs.existsSync(confDevPath)) confPath = confDevPath;
122
- const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
123
-
124
- for (const host of Object.keys(loadReplicas(serverConf, deployContext, subConf))) {
125
- if (serverConf[host]['/'])
126
- this.default.server[host] = {
127
- ...this.default.server[host],
128
- ...serverConf[host],
129
- };
130
- else
131
- this.default.server[host] = {
132
- ...serverConf[host],
133
- ...this.default.server[host],
134
- };
186
+ this.buildProxyByDeployId(deployId, subConf);
187
+ if (fs.existsSync(`./engine-private/replica`)) {
188
+ const singleReplicas = await fs.readdir(`./engine-private/replica`);
189
+ for (let replica of singleReplicas) {
190
+ if (replica.startsWith(deployId)) this.buildProxyByDeployId(replica, subConf);
191
+ }
135
192
  }
136
193
  }
137
194
  this.buildTmpConf();
138
195
  },
139
196
  };
140
197
 
141
- const loadConf = (deployId = 'dd-default', envInput, subConf) => {
198
+ /**
199
+ * @method loadConf
200
+ * @description Loads the configuration of the server.
201
+ * @param {string} [deployId='dd-default'] - The deploy ID.
202
+ * @param {string} [subConf=''] - The sub configuration.
203
+ * @memberof ServerConfBuilder
204
+ */
205
+ const loadConf = (deployId = 'dd-default', subConf) => {
142
206
  if (deployId === 'current') {
143
207
  console.log(process.env.DEPLOY_ID);
144
208
  return;
145
209
  }
146
210
  if (deployId === 'clean') {
147
- const path = envInput ?? '.';
211
+ const path = '.';
148
212
  fs.removeSync(`${path}/.env`);
149
213
  shellExec(`git checkout ${path}/.env.production`);
150
214
  shellExec(`git checkout ${path}/.env.development`);
@@ -163,8 +227,7 @@ const loadConf = (deployId = 'dd-default', envInput, subConf) => {
163
227
 
164
228
  for (const typeConf of Object.keys(Config.default)) {
165
229
  let srcConf = fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8');
166
- if (process.env.NODE_ENV === 'development' && typeConf === 'server') {
167
- if (!subConf) subConf = process.argv[3];
230
+ if (process.env.NODE_ENV === 'development' && typeConf === 'server' && subConf) {
168
231
  const devConfPath = `${folder}/conf.${typeConf}.dev${subConf ? `.${subConf}` : ''}.json`;
169
232
  if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
170
233
  }
@@ -174,10 +237,13 @@ const loadConf = (deployId = 'dd-default', envInput, subConf) => {
174
237
  fs.writeFileSync(`./.env.production`, fs.readFileSync(`${folder}/.env.production`, 'utf8'), 'utf8');
175
238
  fs.writeFileSync(`./.env.development`, fs.readFileSync(`${folder}/.env.development`, 'utf8'), 'utf8');
176
239
  fs.writeFileSync(`./.env.test`, fs.readFileSync(`${folder}/.env.test`, 'utf8'), 'utf8');
177
- const NODE_ENV = envInput || process.env.NODE_ENV;
240
+ const NODE_ENV = process.env.NODE_ENV;
178
241
  if (NODE_ENV) {
179
- fs.writeFileSync(`./.env`, fs.readFileSync(`${folder}/.env.${NODE_ENV}`, 'utf8'), 'utf8');
180
- const env = dotenv.parse(fs.readFileSync(`${folder}/.env.${NODE_ENV}`, 'utf8'));
242
+ const subPathEnv = fs.existsSync(`${folder}/.env.${NODE_ENV}.${subConf}`)
243
+ ? `${folder}/.env.${NODE_ENV}.${subConf}`
244
+ : `${folder}/.env.${NODE_ENV}`;
245
+ fs.writeFileSync(`./.env`, fs.readFileSync(subPathEnv, 'utf8'), 'utf8');
246
+ const env = dotenv.parse(fs.readFileSync(subPathEnv, 'utf8'));
181
247
  process.env = {
182
248
  ...process.env,
183
249
  ...env,
@@ -191,28 +257,36 @@ const loadConf = (deployId = 'dd-default', envInput, subConf) => {
191
257
  return { folder, deployId };
192
258
  };
193
259
 
194
- const loadReplicas = (confServer, deployContext, subConf) => {
195
- if (!deployContext) deployContext = process.argv[2];
196
- if (!subConf) subConf = process.argv[3];
260
+ /**
261
+ * @method loadReplicas
262
+ * @description Loads the replicas of the server.
263
+ * @param {object} confServer - The server configuration.
264
+ * @memberof ServerConfBuilder
265
+ */
266
+ const loadReplicas = (confServer) => {
197
267
  for (const host of Object.keys(confServer)) {
198
268
  for (const path of Object.keys(confServer[host])) {
199
269
  const { replicas, singleReplica } = confServer[host][path];
200
- if (
201
- replicas &&
202
- (deployContext === 'proxy' ||
203
- !singleReplica ||
204
- (singleReplica && process.env.NODE_ENV === 'development' && !subConf))
205
- )
270
+ if (replicas && !singleReplica)
206
271
  for (const replicaPath of replicas) {
207
- confServer[host][replicaPath] = newInstance(confServer[host][path]);
208
- delete confServer[host][replicaPath].replicas;
209
- delete confServer[host][replicaPath].singleReplica;
272
+ {
273
+ confServer[host][replicaPath] = newInstance(confServer[host][path]);
274
+ delete confServer[host][replicaPath].replicas;
275
+ }
210
276
  }
211
277
  }
212
278
  }
213
279
  return confServer;
214
280
  };
215
281
 
282
+ /**
283
+ * @method cloneConf
284
+ * @description Clones the configuration of the server.
285
+ * @param {object} toOptions - The options for the target configuration.
286
+ * @param {object} fromOptions - The options for the source configuration.
287
+ * @param {object} [fromDefaultOptions={ deployId: 'dd-default', clientId: 'default' }] - The default options for the source configuration.
288
+ * @memberof ServerConfBuilder
289
+ */
216
290
  const cloneConf = async (
217
291
  { toOptions, fromOptions },
218
292
  fromDefaultOptions = { deployId: 'dd-default', clientId: 'default' },
@@ -256,6 +330,14 @@ const cloneConf = async (
256
330
  fs.writeFileSync(`${confToFolder}/package.json`, JSON.stringify(packageData, null, 4), 'utf8');
257
331
  };
258
332
 
333
+ /**
334
+ * @method addClientConf
335
+ * @description Adds the client configuration to the server.
336
+ * @param {object} toOptions - The options for the target configuration.
337
+ * @param {object} fromOptions - The options for the source configuration.
338
+ * @param {object} [fromDefaultOptions={ deployId: 'dd-default', clientId: 'default' }] - The default options for the source configuration.
339
+ * @memberof ServerConfBuilder
340
+ */
259
341
  const addClientConf = async (
260
342
  { toOptions, fromOptions },
261
343
  fromDefaultOptions = { deployId: 'dd-default', clientId: 'default' },
@@ -295,6 +377,14 @@ const addClientConf = async (
295
377
  fs.writeFileSync(`${confToFolder}/conf.ssr.json`, JSON.stringify(toSsrConf, null, 4), 'utf8');
296
378
  };
297
379
 
380
+ /**
381
+ * @method buildClientSrc
382
+ * @description Builds the client source code.
383
+ * @param {object} toOptions - The options for the target configuration.
384
+ * @param {object} fromOptions - The options for the source configuration.
385
+ * @param {object} [fromDefaultOptions={ deployId: 'dd-default', clientId: 'default' }] - The default options for the source configuration.
386
+ * @memberof ServerConfBuilder
387
+ */
298
388
  const buildClientSrc = async (
299
389
  { toOptions, fromOptions },
300
390
  fromDefaultOptions = { deployId: 'dd-default', clientId: 'default' },
@@ -337,6 +427,14 @@ const buildClientSrc = async (
337
427
  fs.copySync(`./src/client/public/${fromOptions.clientId}`, `./src/client/public/${toOptions.clientId}`);
338
428
  };
339
429
 
430
+ /**
431
+ * @method buildApiSrc
432
+ * @description Builds the API source code.
433
+ * @param {object} toOptions - The options for the target configuration.
434
+ * @param {object} fromOptions - The options for the source configuration.
435
+ * @param {object} [fromDefaultOptions={ apiId: 'default', deployId: 'dd-default', clientId: 'default' }] - The default options for the source configuration.
436
+ * @memberof ServerConfBuilder
437
+ */
340
438
  const buildApiSrc = async (
341
439
  { toOptions, fromOptions },
342
440
  fromDefaultOptions = { apiId: 'default', deployId: 'dd-default', clientId: 'default' },
@@ -374,17 +472,16 @@ const buildApiSrc = async (
374
472
  ),
375
473
  'utf8',
376
474
  );
377
- return;
378
- if (fs.existsSync(`./src/client/services/${fromOptions.apiId}/${fromOptions.apiId}.management.js`))
379
- fs.writeFileSync(
380
- `./src/client/services/${toOptions.apiId}/${toOptions.apiId}.management.js`,
381
- formattedSrc(
382
- fs.readFileSync(`./src/client/services/${fromOptions.apiId}/${fromOptions.apiId}.management.js`, 'utf8'),
383
- ),
384
- 'utf8',
385
- );
386
475
  };
387
476
 
477
+ /**
478
+ * @method addApiConf
479
+ * @description Adds the API configuration to the server.
480
+ * @param {object} toOptions - The options for the target configuration.
481
+ * @param {object} fromOptions - The options for the source configuration.
482
+ * @param {object} [fromDefaultOptions={ apiId: 'default', deployId: 'dd-default', clientId: 'default' }] - The default options for the source configuration.
483
+ * @memberof ServerConfBuilder
484
+ */
388
485
  const addApiConf = async (
389
486
  { toOptions, fromOptions },
390
487
  fromDefaultOptions = { apiId: 'default', deployId: 'dd-default', clientId: 'default' },
@@ -410,6 +507,14 @@ const addApiConf = async (
410
507
  fs.writeFileSync(`${confToFolder}/conf.client.json`, JSON.stringify(confClient, null, 4), 'utf8');
411
508
  };
412
509
 
510
+ /**
511
+ * @method addWsConf
512
+ * @description Adds the WebSocket configuration to the server.
513
+ * @param {object} toOptions - The options for the target configuration.
514
+ * @param {object} fromOptions - The options for the source configuration.
515
+ * @param {object} [fromDefaultOptions={ wsId: 'default', deployId: 'dd-default', host: 'default.net', paths: '/' }] - The default options for the source configuration.
516
+ * @memberof ServerConfBuilder
517
+ */
413
518
  const addWsConf = async (
414
519
  { toOptions, fromOptions },
415
520
  fromDefaultOptions = { wsId: 'default', deployId: 'dd-default', host: 'default.net', paths: '/' },
@@ -435,6 +540,14 @@ const addWsConf = async (
435
540
  fs.writeFileSync(`${confToFolder}/conf.server.json`, JSON.stringify(confServer, null, 4), 'utf8');
436
541
  };
437
542
 
543
+ /**
544
+ * @method buildWsSrc
545
+ * @description Builds the WebSocket source code.
546
+ * @param {object} toOptions - The options for the target configuration.
547
+ * @param {object} fromOptions - The options for the source configuration.
548
+ * @param {object} [fromDefaultOptions={ wsId: 'default', deployId: 'dd-default', host: 'default.net', paths: '/' }] - The default options for the source configuration.
549
+ * @memberof ServerConfBuilder
550
+ */
438
551
  const buildWsSrc = async (
439
552
  { toOptions, fromOptions },
440
553
  fromDefaultOptions = { wsId: 'default', deployId: 'dd-default', host: 'default.net', paths: '/' },
@@ -469,6 +582,13 @@ const buildWsSrc = async (
469
582
  }
470
583
  };
471
584
 
585
+ /**
586
+ * @method cloneSrcComponents
587
+ * @description Clones the source components.
588
+ * @param {object} toOptions - The options for the target configuration.
589
+ * @param {object} fromOptions - The options for the source configuration.
590
+ * @memberof ServerConfBuilder
591
+ */
472
592
  const cloneSrcComponents = async ({ toOptions, fromOptions }) => {
473
593
  const toClientVariableName = getCapVariableName(toOptions.componentsFolder);
474
594
  const fromClientVariableName = getCapVariableName(fromOptions.componentsFolder);
@@ -492,24 +612,25 @@ const cloneSrcComponents = async ({ toOptions, fromOptions }) => {
492
612
  }
493
613
  };
494
614
 
615
+ /**
616
+ * @method buildProxyRouter
617
+ * @description Builds the proxy router.
618
+ * @memberof ServerConfBuilder
619
+ */
495
620
  const buildProxyRouter = () => {
496
621
  const confServer = JSON.parse(fs.readFileSync(`./conf/conf.server.json`, 'utf8'));
497
622
  let currentPort = parseInt(process.env.PORT) + 1;
498
623
  const proxyRouter = {};
499
- const singleReplicaHosts = [];
500
624
  for (const host of Object.keys(confServer)) {
501
625
  for (const path of Object.keys(confServer[host])) {
502
- if (confServer[host][path].singleReplica && !singleReplicaHosts.includes(host)) {
503
- singleReplicaHosts.push(host);
504
- currentPort++;
505
- continue;
506
- }
626
+ if (confServer[host][path].singleReplica) continue;
627
+
507
628
  confServer[host][path].port = newInstance(currentPort);
508
629
  for (const port of confServer[host][path].proxy) {
509
630
  if (!(port in proxyRouter)) proxyRouter[port] = {};
510
631
  proxyRouter[port][`${host}${path}`] = {
511
632
  // target: `http://${host}:${confServer[host][path].port}${path}`,
512
- target: `http://localhost:${confServer[host][path].port - singleReplicaHosts.length}`,
633
+ target: `http://localhost:${confServer[host][path].port}`,
513
634
  // target: `http://127.0.0.1:${confServer[host][path].port}`,
514
635
  proxy: confServer[host][path].proxy,
515
636
  redirect: confServer[host][path].redirect,
@@ -526,7 +647,7 @@ const buildProxyRouter = () => {
526
647
  if (!(port in proxyRouter)) proxyRouter[port] = {};
527
648
  proxyRouter[port][`${host}${peerPath}`] = {
528
649
  // target: `http://${host}:${confServer[host][peerPath].port}${peerPath}`,
529
- target: `http://localhost:${confServer[host][peerPath].port - singleReplicaHosts.length}`,
650
+ target: `http://localhost:${confServer[host][peerPath].port}`,
530
651
  // target: `http://127.0.0.1:${confServer[host][peerPath].port}`,
531
652
  proxy: confServer[host][peerPath].proxy,
532
653
  host,
@@ -541,7 +662,15 @@ const buildProxyRouter = () => {
541
662
  return proxyRouter;
542
663
  };
543
664
 
544
- const pathPortAssignmentFactory = (router, confServer) => {
665
+ /**
666
+ * @method pathPortAssignmentFactory
667
+ * @description Creates the path port assignment.
668
+ * @param {string} deployId - The deploy ID.
669
+ * @param {object} router - The router.
670
+ * @param {object} confServer - The server configuration.
671
+ * @memberof ServerConfBuilder
672
+ */
673
+ const pathPortAssignmentFactory = async (deployId, router, confServer) => {
545
674
  const pathPortAssignmentData = {};
546
675
  for (const host of Object.keys(confServer)) {
547
676
  const pathPortAssignment = [];
@@ -559,15 +688,54 @@ const pathPortAssignmentFactory = (router, confServer) => {
559
688
  // logger.info('', { host, port: port + 1, path: '/peer' });
560
689
  pathPortAssignment.push({
561
690
  port: port + 1,
562
- path: '/peer',
691
+ path: `${path === '/' ? '' : path}/peer`,
563
692
  });
564
693
  }
565
694
  }
566
695
  pathPortAssignmentData[host] = pathPortAssignment;
567
696
  }
697
+ if (fs.existsSync(`./engine-private/replica`)) {
698
+ const singleReplicas = await fs.readdir(`./engine-private/replica`);
699
+ for (let replica of singleReplicas) {
700
+ if (replica.startsWith(deployId)) {
701
+ const replicaServerConf = JSON.parse(
702
+ fs.readFileSync(`./engine-private/replica/${replica}/conf.server.json`, 'utf8'),
703
+ );
704
+ for (const host of Object.keys(replicaServerConf)) {
705
+ const pathPortAssignment = [];
706
+ for (const path of Object.keys(replicaServerConf[host])) {
707
+ const { peer } = replicaServerConf[host][path];
708
+ if (!router[`${host}${path === '/' ? '' : path}`]) continue;
709
+ const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
710
+ // logger.info('', { host, port, path });
711
+ pathPortAssignment.push({
712
+ port,
713
+ path,
714
+ });
715
+
716
+ if (peer) {
717
+ // logger.info('', { host, port: port + 1, path: '/peer' });
718
+ pathPortAssignment.push({
719
+ port: port + 1,
720
+ path: `${path === '/' ? '' : path}/peer`,
721
+ });
722
+ }
723
+ }
724
+ pathPortAssignmentData[host] = pathPortAssignmentData[host].concat(pathPortAssignment);
725
+ }
726
+ }
727
+ }
728
+ }
568
729
  return pathPortAssignmentData;
569
730
  };
570
731
 
732
+ /**
733
+ * @method deployRangePortFactory
734
+ * @description Creates the deploy range port factory.
735
+ * @param {object} router - The router.
736
+ * @returns {object} - The deploy range port factory.
737
+ * @memberof ServerConfBuilder
738
+ */
571
739
  const deployRangePortFactory = (router) => {
572
740
  const ports = Object.values(router).map((p) => parseInt(p.split(':')[2]));
573
741
  const fromPort = Math.min(...ports);
@@ -575,6 +743,14 @@ const deployRangePortFactory = (router) => {
575
743
  return { ports, fromPort, toPort };
576
744
  };
577
745
 
746
+ /**
747
+ * @method buildKindPorts
748
+ * @description Builds the kind ports.
749
+ * @param {number} from - The from port.
750
+ * @param {number} to - The to port.
751
+ * @returns {string} - The kind ports.
752
+ * @memberof ServerConfBuilder
753
+ */
578
754
  const buildKindPorts = (from, to) =>
579
755
  range(parseInt(from), parseInt(to))
580
756
  .map(
@@ -590,13 +766,21 @@ const buildKindPorts = (from, to) =>
590
766
  )
591
767
  .join('\n');
592
768
 
593
- const buildPortProxyRouter = (port, proxyRouter) => {
769
+ /**
770
+ * @method buildPortProxyRouter
771
+ * @description Builds the port proxy router.
772
+ * @param {number} port - The port.
773
+ * @param {object} proxyRouter - The proxy router.
774
+ * @param {object} [options={ orderByPathLength: false }] - The options.
775
+ * @returns {object} - The port proxy router.
776
+ * @memberof ServerConfBuilder
777
+ */
778
+ const buildPortProxyRouter = (port, proxyRouter, options = { orderByPathLength: false }) => {
594
779
  const hosts = proxyRouter[port];
595
780
  const router = {};
596
781
  // build router
597
782
  Object.keys(hosts).map((hostKey) => {
598
783
  let { host, path, target, proxy, peer } = hosts[hostKey];
599
- if (process.env.NODE_ENV === 'development' && process.argv.includes('localhost')) host = `localhost`;
600
784
 
601
785
  if (!proxy.includes(port)) {
602
786
  logger.warn('Proxy port not set on conf', { port, host, path, proxy, target });
@@ -618,15 +802,38 @@ const buildPortProxyRouter = (port, proxyRouter) => {
618
802
 
619
803
  if (Object.keys(router).length === 0) return router;
620
804
 
621
- const reOrderRouter = {};
622
- for (const absoluteHostKey of orderArrayFromAttrInt(Object.keys(router), 'length'))
623
- reOrderRouter[absoluteHostKey] = router[absoluteHostKey];
805
+ if (options.orderByPathLength === true) {
806
+ const reOrderRouter = {};
807
+ for (const absoluteHostKey of orderArrayFromAttrInt(Object.keys(router), 'length'))
808
+ reOrderRouter[absoluteHostKey] = router[absoluteHostKey];
809
+ return reOrderRouter;
810
+ }
624
811
 
625
- return reOrderRouter;
812
+ return router;
626
813
  };
627
814
 
815
+ /**
816
+ * @method buildReplicaId
817
+ * @description Builds the replica ID.
818
+ * @param {object} options - The options.
819
+ * @param {string} options.deployId - The deploy ID.
820
+ * @param {string} options.replica - The replica.
821
+ * @returns {string} - The replica ID.
822
+ * @memberof ServerConfBuilder
823
+ */
628
824
  const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1)}`;
629
825
 
826
+ /**
827
+ * @method getDataDeploy
828
+ * @description Gets the data deploy.
829
+ * @param {object} options - The options.
830
+ * @param {boolean} [options.buildSingleReplica=false] - The build single replica.
831
+ * @param {string} options.deployGroupId - The deploy group ID.
832
+ * @param {string} options.deployId - The deploy ID.
833
+ * @param {boolean} [options.disableSyncEnvPort=false] - The disable sync env port.
834
+ * @returns {object} - The data deploy.
835
+ * @memberof ServerConfBuilder
836
+ */
630
837
  const getDataDeploy = (
631
838
  options = {
632
839
  buildSingleReplica: false,
@@ -688,6 +895,13 @@ const getDataDeploy = (
688
895
  return buildDataDeploy;
689
896
  };
690
897
 
898
+ /**
899
+ * @method validateTemplatePath
900
+ * @description Validates the template path.
901
+ * @param {string} absolutePath - The absolute path.
902
+ * @returns {boolean} - The validation result.
903
+ * @memberof ServerConfBuilder
904
+ */
691
905
  const validateTemplatePath = (absolutePath = '') => {
692
906
  const host = 'default.net';
693
907
  const path = '/';
@@ -765,16 +979,40 @@ const validateTemplatePath = (absolutePath = '') => {
765
979
  return true;
766
980
  };
767
981
 
982
+ /**
983
+ * @method awaitDeployMonitor
984
+ * @description Waits for the deploy monitor.
985
+ * @param {boolean} [init=false] - The init flag.
986
+ * @param {number} [deltaMs=1000] - The delta ms.
987
+ * @returns {Promise<void>} - The await deploy monitor.
988
+ * @memberof ServerConfBuilder
989
+ */
768
990
  const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
769
991
  if (init) UnderpostRootEnv.API.set('await-deploy', new Date().toISOString());
770
992
  await timer(deltaMs);
771
993
  if (UnderpostRootEnv.API.get('await-deploy')) return await awaitDeployMonitor();
772
994
  };
773
995
 
996
+ /**
997
+ * @method getCronBackUpFolder
998
+ * @description Gets the cron back up folder.
999
+ * @param {string} host - The host.
1000
+ * @param {string} path - The path.
1001
+ * @returns {string} - The cron back up folder.
1002
+ * @memberof ServerConfBuilder
1003
+ */
774
1004
  const getCronBackUpFolder = (host = '', path = '') => {
775
1005
  return `${host}${path.replace(/\\/g, '/').replace(`/`, '-')}`;
776
1006
  };
777
1007
 
1008
+ /**
1009
+ * @method mergeFile
1010
+ * @description Merges the file.
1011
+ * @param {Array} parts - The parts.
1012
+ * @param {string} outputFilePath - The output file path.
1013
+ * @returns {Promise<void>} - The merge file.
1014
+ * @memberof ServerConfBuilder
1015
+ */
778
1016
  const mergeFile = async (parts = [], outputFilePath) => {
779
1017
  await new Promise((resolve) => {
780
1018
  splitFile
@@ -789,6 +1027,16 @@ const mergeFile = async (parts = [], outputFilePath) => {
789
1027
  });
790
1028
  };
791
1029
 
1030
+ /**
1031
+ * @method rebuildConfFactory
1032
+ * @description Rebuilds the conf factory.
1033
+ * @param {object} options - The options.
1034
+ * @param {string} options.deployId - The deploy ID.
1035
+ * @param {string} options.valkey - The valkey.
1036
+ * @param {boolean} [options.mongo=false] - The mongo.
1037
+ * @returns {object} - The rebuild conf factory.
1038
+ * @memberof ServerConfBuilder
1039
+ */
792
1040
  const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
793
1041
  const confServer = loadReplicas(
794
1042
  JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
@@ -836,6 +1084,13 @@ const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
836
1084
  return { hosts };
837
1085
  };
838
1086
 
1087
+ /**
1088
+ * @method getPathsSSR
1089
+ * @description Gets the paths SSR.
1090
+ * @param {object} conf - The conf.
1091
+ * @returns {Array} - The paths SSR.
1092
+ * @memberof ServerConfBuilder
1093
+ */
839
1094
  const getPathsSSR = (conf) => {
840
1095
  const paths = ['src/client/ssr/Render.js'];
841
1096
  for (const o of conf.head) paths.push(`src/client/ssr/head/${o}.js`);
@@ -846,19 +1101,87 @@ const getPathsSSR = (conf) => {
846
1101
  return paths;
847
1102
  };
848
1103
 
1104
+ /**
1105
+ * @method Cmd
1106
+ * @description The command factory.
1107
+ * @memberof ServerConfBuilder
1108
+ */
849
1109
  const Cmd = {
1110
+ /**
1111
+ * @method delete
1112
+ * @description Deletes the deploy.
1113
+ * @param {string} deployId - The deploy ID.
1114
+ * @returns {string} - The delete command.
1115
+ * @memberof Cmd
1116
+ */
850
1117
  delete: (deployId) => `pm2 delete ${deployId}`,
1118
+ /**
1119
+ * @method run
1120
+ * @description Runs the deploy.
1121
+ * @returns {string} - The run command.
1122
+ * @memberof Cmd
1123
+ */
851
1124
  run: () => `npm start`,
1125
+ /**
1126
+ * @method build
1127
+ * @description Builds the deploy.
1128
+ * @param {string} deployId - The deploy ID.
1129
+ * @returns {string} - The build command.
1130
+ * @memberof Cmd
1131
+ */
852
1132
  build: (deployId) => `node bin/deploy build-full-client ${deployId}${process.argv.includes('l') ? ' l' : ''}`,
1133
+ /**
1134
+ * @method conf
1135
+ * @description Configures the deploy.
1136
+ * @param {string} deployId - The deploy ID.
1137
+ * @param {string} env - The environment.
1138
+ * @returns {string} - The conf command.
1139
+ * @memberof Cmd
1140
+ */
853
1141
  conf: (deployId, env) => `node bin/deploy conf ${deployId} ${env ? env : 'production'}`,
1142
+ /**
1143
+ * @method replica
1144
+ * @description Builds the replica.
1145
+ * @param {string} deployId - The deploy ID.
1146
+ * @param {string} host - The host.
1147
+ * @param {string} path - The path.
1148
+ * @returns {string} - The replica command.
1149
+ * @memberof Cmd
1150
+ */
854
1151
  replica: (deployId, host, path) => `node bin/deploy build-single-replica ${deployId} ${host} ${path}`,
1152
+ /**
1153
+ * @method syncPorts
1154
+ * @description Syncs the ports.
1155
+ * @param {string} deployGroupId - The deploy group ID.
1156
+ * @returns {string} - The sync ports command.
1157
+ * @memberof Cmd
1158
+ */
855
1159
  syncPorts: (deployGroupId) => `node bin/deploy sync-env-port ${deployGroupId}`,
1160
+ /**
1161
+ * @method cron
1162
+ * @description Creates a cron job.
1163
+ * @param {string} deployList - The deploy list.
1164
+ * @param {string} jobList - The job list.
1165
+ * @param {string} name - The name.
1166
+ * @param {string} expression - The expression.
1167
+ * @param {object} options - The options.
1168
+ * @returns {string} - The cron command.
1169
+ * @memberof Cmd
1170
+ */
856
1171
  cron: (deployList, jobList, name, expression, options) =>
857
1172
  `pm2 start ./bin/index.js --no-autorestart --instances 1 --cron "${expression}" --name ${name} -- cron ${
858
1173
  options?.itc ? `--itc ` : ''
859
1174
  }${options?.git ? `--git ` : ''}${deployList} ${jobList}`,
860
1175
  };
861
1176
 
1177
+ /**
1178
+ * @method splitFileFactory
1179
+ * @description Splits the file factory.
1180
+ * @param {string} name - The name.
1181
+ * @param {string} _path - The path.
1182
+ * @returns {Promise<boolean>} - The split file factory.
1183
+ * @memberof ServerConfBuilder
1184
+ */
862
1185
  const splitFileFactory = async (name, _path) => {
863
1186
  const stats = fs.statSync(_path);
864
1187
  const maxSizeInBytes = 1024 * 1024 * 50; // 50 mb
@@ -887,6 +1210,12 @@ const splitFileFactory = async (name, _path) => {
887
1210
  return false;
888
1211
  };
889
1212
 
1213
+ /**
1214
+ * @method getNpmRootPath
1215
+ * @description Gets the npm root path.
1216
+ * @returns {string} - The npm root path.
1217
+ * @memberof ServerConfBuilder
1218
+ */
890
1219
  const getNpmRootPath = () =>
891
1220
  shellExec(`npm root -g`, {
892
1221
  stdout: true,
@@ -894,8 +1223,21 @@ const getNpmRootPath = () =>
894
1223
  silent: true,
895
1224
  }).trim();
896
1225
 
1226
+ /**
1227
+ * @method getUnderpostRootPath
1228
+ * @description Gets the underpost root path.
1229
+ * @returns {string} - The underpost root path.
1230
+ * @memberof ServerConfBuilder
1231
+ */
897
1232
  const getUnderpostRootPath = () => `${getNpmRootPath()}/underpost`;
898
1233
 
1234
+ /**
1235
+ * @method writeEnv
1236
+ * @description Writes the environment variables.
1237
+ * @param {string} envPath - The environment path.
1238
+ * @param {object} envObj - The environment object.
1239
+ * @memberof ServerConfBuilder
1240
+ */
899
1241
  const writeEnv = (envPath, envObj) =>
900
1242
  fs.writeFileSync(
901
1243
  envPath,
@@ -905,6 +1247,14 @@ const writeEnv = (envPath, envObj) =>
905
1247
  'utf8',
906
1248
  );
907
1249
 
1250
+ /**
1251
+ * @method buildCliDoc
1252
+ * @description Builds the CLI documentation.
1253
+ * @param {object} program - The program.
1254
+ * @param {string} oldVersion - The old version.
1255
+ * @param {string} newVersion - The new version.
1256
+ * @memberof ServerConfBuilder
1257
+ */
908
1258
  const buildCliDoc = (program, oldVersion, newVersion) => {
909
1259
  let md = shellExec(`node bin help`, { silent: true, stdout: true }).split('Options:');
910
1260
  const baseOptions =
@@ -965,13 +1315,35 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
965
1315
  );
966
1316
  };
967
1317
 
968
- const getInstanceContext = async (options = { singleReplica, replicas, redirect: '' }) => {
969
- const { singleReplica, replicas, redirect } = options;
970
-
971
- if (singleReplica && replicas && replicas.length > 0)
972
- return {
973
- singleReplicaHost: true,
974
- };
1318
+ /**
1319
+ * @method getInstanceContext
1320
+ * @description Gets the instance context.
1321
+ * @param {object} options - The options.
1322
+ * @param {string} options.deployId - The deploy ID.
1323
+ * @param {boolean} options.singleReplica - The single replica.
1324
+ * @param {Array} options.replicas - The replicas.
1325
+ * @param {string} options.redirect - The redirect.
1326
+ * @returns {object} - The instance context.
1327
+ * @memberof ServerConfBuilder
1328
+ */
1329
+ const getInstanceContext = async (options = { deployId, singleReplica, replicas, redirect: '' }) => {
1330
+ const { deployId, singleReplica, replicas, redirect } = options;
1331
+ let singleReplicaOffsetPortSum = 0;
1332
+
1333
+ if (singleReplica && replicas && replicas.length > 0) {
1334
+ for (const replica of replicas) {
1335
+ const replicaDeployId = buildReplicaId({ deployId, replica });
1336
+ const confReplicaServer = JSON.parse(
1337
+ fs.readFileSync(`./engine-private/replica/${replicaDeployId}/conf.server.json`, 'utf8'),
1338
+ );
1339
+ for (const host of Object.keys(confReplicaServer)) {
1340
+ for (const path of Object.keys(confReplicaServer[host])) {
1341
+ singleReplicaOffsetPortSum++;
1342
+ if (confReplicaServer[host][path].peer) singleReplicaOffsetPortSum++;
1343
+ }
1344
+ }
1345
+ }
1346
+ }
975
1347
 
976
1348
  const redirectTarget = redirect
977
1349
  ? redirect[redirect.length - 1] === '/'
@@ -979,9 +1351,97 @@ const getInstanceContext = async (options = { singleReplica, replicas, redirect:
979
1351
  : redirect
980
1352
  : undefined;
981
1353
 
982
- return { redirectTarget };
1354
+ return { redirectTarget, singleReplicaOffsetPortSum };
983
1355
  };
984
1356
 
1357
+ /**
1358
+ * @method buildApiConf
1359
+ * @description Builds the API configuration.
1360
+ * @param {object} options - The options.
1361
+ * @param {string} options.deployId - The deploy ID.
1362
+ * @param {string} options.subConf - The sub configuration.
1363
+ * @param {string} options.host - The host.
1364
+ * @param {string} options.path - The path.
1365
+ * @param {string} options.origin - The origin.
1366
+ * @returns {object} - The API configuration.
1367
+ * @memberof ServerConfBuilder
1368
+ */
1369
+ const buildApiConf = async (options = { deployId: '', subConf: '', host: '', path: '', origin: '' }) => {
1370
+ let { deployId, subConf, host, path, origin } = options;
1371
+ if (!deployId) deployId = process.argv[2].trim();
1372
+ if (!subConf) subConf = process.argv[3].trim();
1373
+ if (process.argv[4]) host = process.argv[4].trim();
1374
+ if (process.argv[5]) path = process.argv[5].trim();
1375
+ if (process.argv[6])
1376
+ origin = `${process.env.NODE_ENV === 'production' ? 'https' : 'http'}://${process.argv[6].trim()}`;
1377
+
1378
+ if (!origin) return;
1379
+ const confServer = JSON.parse(
1380
+ fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`, 'utf8'),
1381
+ );
1382
+ const envObj = dotenv.parse(
1383
+ fs.readFileSync(`./engine-private/conf/${deployId}/.env.${process.env.NODE_ENV}`, 'utf8'),
1384
+ );
1385
+ if (host && path) {
1386
+ confServer[host][path].origins = [origin];
1387
+ logger.info('Build api conf', { host, path, origin });
1388
+ } else return;
1389
+ writeEnv(`./engine-private/conf/${deployId}/.env.${process.env.NODE_ENV}.${subConf}-dev-api`, envObj);
1390
+ fs.writeFileSync(
1391
+ `./engine-private/conf/${deployId}/conf.server.dev.${subConf}-dev-api.json`,
1392
+ JSON.stringify(confServer, null, 4),
1393
+ 'utf8',
1394
+ );
1395
+ };
1396
+
1397
+ /**
1398
+ * @method buildClientStaticConf
1399
+ * @description Builds the client static configuration.
1400
+ * @param {object} options - The options.
1401
+ * @param {string} options.deployId - The deploy ID.
1402
+ * @param {string} options.subConf - The sub configuration.
1403
+ * @param {string} options.apiBaseHost - The API base host.
1404
+ * @param {string} options.host - The host.
1405
+ * @param {string} options.path - The path.
1406
+ * @returns {void}
1407
+ * @memberof ServerConfBuilder
1408
+ */
1409
+ const buildClientStaticConf = async (options = { deployId: '', subConf: '', apiBaseHost: '', host: '', path: '' }) => {
1410
+ let { deployId, subConf, host, path } = options;
1411
+ if (!deployId) deployId = process.argv[2].trim();
1412
+ if (!subConf) subConf = process.argv[3].trim();
1413
+ if (!host) host = process.argv[4].trim();
1414
+ if (!path) path = process.argv[5].trim();
1415
+ const confServer = JSON.parse(
1416
+ fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.dev.${subConf}-dev-api.json`, 'utf8'),
1417
+ );
1418
+ const envObj = dotenv.parse(
1419
+ fs.readFileSync(`./engine-private/conf/${deployId}/.env.${process.env.NODE_ENV}.${subConf}-dev-api`, 'utf8'),
1420
+ );
1421
+ envObj.PORT = parseInt(envObj.PORT);
1422
+ const apiBaseHost = options?.apiBaseHost ? options.apiBaseHost : `localhost:${envObj.PORT + 1}`;
1423
+ confServer[host][path].apiBaseHost = apiBaseHost;
1424
+ confServer[host][path].apiBaseProxyPath = path;
1425
+ logger.info('Build client static conf', { host, path, apiBaseHost });
1426
+ envObj.PORT = parseInt(confServer[host][path].origins[0].split(':')[2]) - 1;
1427
+ writeEnv(`./engine-private/conf/${deployId}/.env.${process.env.NODE_ENV}.${subConf}-dev-client`, envObj);
1428
+ fs.writeFileSync(
1429
+ `./engine-private/conf/${deployId}/conf.server.dev.${subConf}-dev-client.json`,
1430
+ JSON.stringify(confServer, null, 4),
1431
+ 'utf8',
1432
+ );
1433
+ };
1434
+
1435
+ /**
1436
+ * @method isDeployRunnerContext
1437
+ * @description Checks if the deploy runner context is valid.
1438
+ * @param {string} path - The path.
1439
+ * @param {object} options - The options.
1440
+ * @returns {boolean} - The deploy runner context.
1441
+ * @memberof ServerConfBuilder
1442
+ */
1443
+ const isDeployRunnerContext = (path, options) => !options.build && path && path !== 'template-deploy';
1444
+
985
1445
  export {
986
1446
  Cmd,
987
1447
  Config,
@@ -1015,4 +1475,7 @@ export {
1015
1475
  rebuildConfFactory,
1016
1476
  buildCliDoc,
1017
1477
  getInstanceContext,
1478
+ buildApiConf,
1479
+ buildClientStaticConf,
1480
+ isDeployRunnerContext,
1018
1481
  };