underpost 2.85.7 → 2.89.0

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 (36) hide show
  1. package/.github/workflows/release.cd.yml +1 -1
  2. package/README.md +2 -2
  3. package/bin/build.js +8 -10
  4. package/cli.md +3 -2
  5. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  6. package/manifests/deployment/dd-test-development/deployment.yaml +50 -50
  7. package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
  8. package/package.json +1 -1
  9. package/src/api/file/file.service.js +29 -3
  10. package/src/cli/baremetal.js +1 -2
  11. package/src/cli/index.js +1 -0
  12. package/src/cli/repository.js +8 -1
  13. package/src/cli/run.js +97 -36
  14. package/src/client/components/core/AgGrid.js +42 -3
  15. package/src/client/components/core/CommonJs.js +4 -0
  16. package/src/client/components/core/Css.js +95 -48
  17. package/src/client/components/core/CssCore.js +0 -1
  18. package/src/client/components/core/LoadingAnimation.js +2 -2
  19. package/src/client/components/core/Logger.js +2 -9
  20. package/src/client/components/core/Modal.js +22 -14
  21. package/src/client/components/core/ObjectLayerEngine.js +300 -9
  22. package/src/client/components/core/ObjectLayerEngineModal.js +686 -148
  23. package/src/client/components/core/ObjectLayerEngineViewer.js +1061 -0
  24. package/src/client/components/core/Pagination.js +15 -5
  25. package/src/client/components/core/Router.js +5 -1
  26. package/src/client/components/core/Translate.js +4 -0
  27. package/src/client/components/core/Worker.js +8 -1
  28. package/src/client/services/default/default.management.js +86 -16
  29. package/src/db/mariadb/MariaDB.js +2 -2
  30. package/src/index.js +1 -1
  31. package/src/server/client-build.js +57 -2
  32. package/src/server/object-layer.js +44 -0
  33. package/src/server/start.js +12 -0
  34. package/src/ws/IoInterface.js +2 -3
  35. package/AUTHORS.md +0 -21
  36. package/src/server/network.js +0 -72
@@ -31,6 +31,6 @@ jobs:
31
31
  underpost run pull
32
32
  underpost run secret
33
33
  cd /home/dd/engine
34
- node bin run --dev git-conf admin@underpost.net,underpostnet
34
+ node bin run --dev git-conf
35
35
  node bin run --dev template-deploy-image
36
36
  node bin run --dev ssh-deploy sync-engine-test
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  <!-- badges -->
20
20
 
21
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.85.7)](https://socket.dev/npm/package/underpost/overview/2.85.7) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
21
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.89.0)](https://socket.dev/npm/package/underpost/overview/2.89.0) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
22
22
 
23
23
  <!-- end-badges -->
24
24
 
@@ -66,7 +66,7 @@ Run dev client server
66
66
  npm run dev
67
67
  ```
68
68
  <!-- -->
69
- ## underpost ci/cd cli v2.85.7
69
+ ## underpost ci/cd cli v2.89.0
70
70
 
71
71
  ### Usage: `underpost [options] [command]`
72
72
  ```
package/bin/build.js CHANGED
@@ -53,14 +53,14 @@ if (process.argv.includes('conf')) {
53
53
  fs.removeSync(toPath);
54
54
  fs.mkdirSync(toPath, { recursive: true });
55
55
  fs.copySync(`./engine-private/conf/${_confName}`, toPath);
56
- if (process.argv.includes('remove-replica') && fs.existsSync(`../${privateRepoName}/replica`)) {
57
- fs.removeSync(`../${privateRepoName}/replica`);
58
- } else if (fs.existsSync(`./engine-private/replica`)) {
56
+ fs.removeSync(`../${privateRepoName}/replica`);
57
+ if (fs.existsSync(`./engine-private/replica`)) {
59
58
  const replicas = await fs.readdir(`./engine-private/replica`);
60
59
  for (const replica of replicas)
61
60
  if (replica.match(_confName))
62
61
  fs.copySync(`./engine-private/replica/${replica}`, `../${privateRepoName}/replica/${replica}`);
63
62
  }
63
+
64
64
  if (fs.existsSync(`./engine-private/itc-scripts`)) {
65
65
  const itcScripts = await fs.readdir(`./engine-private/itc-scripts`);
66
66
  for (const itcScript of itcScripts)
@@ -149,10 +149,6 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
149
149
  }
150
150
  }
151
151
 
152
- shellExec(`node bin/deploy update-default-conf ${confName}`);
153
-
154
- fs.copyFileSync(`./conf.${confName}.js`, `${basePath}/conf.js`);
155
-
156
152
  if (!fs.existsSync(`${basePath}/.github/workflows`))
157
153
  fs.mkdirSync(`${basePath}/.github/workflows`, {
158
154
  recursive: true,
@@ -170,11 +166,12 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
170
166
  );
171
167
  delete packageJson.bin.underpost;
172
168
  packageJson.bin.cyberia = 'bin/index.js';
173
- packageJson.keywords = ['cyberia', 'object-layer', 'game-engine', 'assets-management'];
174
-
169
+ packageJson.keywords = ['cyberia', 'object-layer', 'game-engine', 'assets-management', 'web3'];
170
+ packageJson.description = 'Cyberia Engine - Object Layer and Assets Management Microservice';
175
171
  fs.writeFileSync(`${basePath}/bin/index.js`, fs.readFileSync(`./bin/cyberia.js`, 'utf8'), 'utf8');
176
172
  fs.copyFileSync(`./src/api/object-layer/README.md`, `${basePath}/README.md`);
177
-
173
+ fs.copySync(`./hardhat`, `${basePath}/hardhat`);
174
+ fs.copySync(`./hardhat/white-paper.md`, `${basePath}/white-paper.md`);
178
175
  default:
179
176
  break;
180
177
  }
@@ -200,6 +197,7 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
200
197
  fs.copyFileSync(`./.github/workflows/${repoName}.ci.yml`, `${basePath}/.github/workflows/${repoName}.ci.yml`);
201
198
  fs.copyFileSync(`./.github/workflows/${repoName}.cd.yml`, `${basePath}/.github/workflows/${repoName}.cd.yml`);
202
199
 
200
+ // Copy conf.<deploy-id>.js to conf.js for the respective deployment
203
201
  fs.copyFileSync(`./conf.${confName}.js`, `${basePath}/conf.js`);
204
202
  fs.copyFileSync(`./manifests/deployment/${confName}-development/proxy.yaml`, `${basePath}/proxy.yaml`);
205
203
  fs.copyFileSync(`./manifests/deployment/${confName}-development/deployment.yaml`, `${basePath}/deployment.yaml`);
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.85.7
1
+ ## underpost ci/cd cli v2.89.0
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -623,7 +623,7 @@ Options:
623
623
  Runs a script from the specified path.
624
624
 
625
625
  Arguments:
626
- runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, underpost-config, gpu-env, tf-gpu-test, dev-cluster, ssh-cluster-info, dev-hosts-expose, dev-hosts-restore, cyberia-ide, engine-ide, cluster-build, template-deploy, template-deploy-image, clean, pull, release-deploy, ssh-deploy, ide, sync, ls-deployments, ls-images, host-update, dev-container, monitor, db-client, git-conf, promote, metrics, cluster, deploy, dev, service, release-cmt, sync-replica, tf-vae-test, deploy-job.
626
+ runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, underpost-config, gpu-env, tf-gpu-test, dev-cluster, ssh-cluster-info, dev-hosts-expose, dev-hosts-restore, cluster-build, template-deploy, template-deploy-image, clean, pull, release-deploy, ssh-deploy, ide, sync, tz, cron, ls-deployments, ls-images, host-update, dev-container, monitor, db-client, git-conf, promote, metrics, cluster, deploy, dev, service, sh, log, release-cmt, sync-replica, tf-vae-test, deploy-job.
627
627
  path The absolute or relative directory path where the script is located.
628
628
 
629
629
  Options:
@@ -646,6 +646,7 @@ Options:
646
646
  --reset Resets the runner state before execution.
647
647
  --terminal Enables terminal mode for interactive script execution.
648
648
  --dev-proxy-port-offset <port-offset> Sets a custom port offset for development proxy.
649
+ --conf-server-path <conf-server-path> Sets a custom configuration server path.
649
650
  -h, --help display help for command
650
651
 
651
652
  ```
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v2.85.7
20
+ image: localhost/rockylinux9-underpost:v2.89.0
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-default-development-green
103
- image: localhost/rockylinux9-underpost:v2.85.7
103
+ image: localhost/rockylinux9-underpost:v2.89.0
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-test-development-blue
20
- image: localhost/rockylinux9-underpost:v2.85.7
20
+ image: localhost/rockylinux9-underpost:v2.89.0
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "96294Ki"
@@ -49,41 +49,41 @@ spec:
49
49
  selector:
50
50
  app: dd-test-development-blue
51
51
  ports:
52
- - name: 'tcp-4041'
52
+ - name: 'tcp-4030'
53
53
  protocol: TCP
54
- port: 4041
55
- targetPort: 4041
56
- - name: 'udp-4041'
54
+ port: 4030
55
+ targetPort: 4030
56
+ - name: 'udp-4030'
57
57
  protocol: UDP
58
- port: 4041
59
- targetPort: 4041
58
+ port: 4030
59
+ targetPort: 4030
60
60
 
61
- - name: 'tcp-4042'
61
+ - name: 'tcp-4031'
62
62
  protocol: TCP
63
- port: 4042
64
- targetPort: 4042
65
- - name: 'udp-4042'
63
+ port: 4031
64
+ targetPort: 4031
65
+ - name: 'udp-4031'
66
66
  protocol: UDP
67
- port: 4042
68
- targetPort: 4042
67
+ port: 4031
68
+ targetPort: 4031
69
69
 
70
- - name: 'tcp-4043'
70
+ - name: 'tcp-4032'
71
71
  protocol: TCP
72
- port: 4043
73
- targetPort: 4043
74
- - name: 'udp-4043'
72
+ port: 4032
73
+ targetPort: 4032
74
+ - name: 'udp-4032'
75
75
  protocol: UDP
76
- port: 4043
77
- targetPort: 4043
76
+ port: 4032
77
+ targetPort: 4032
78
78
 
79
- - name: 'tcp-4044'
79
+ - name: 'tcp-4033'
80
80
  protocol: TCP
81
- port: 4044
82
- targetPort: 4044
83
- - name: 'udp-4044'
81
+ port: 4033
82
+ targetPort: 4033
83
+ - name: 'udp-4033'
84
84
  protocol: UDP
85
- port: 4044
86
- targetPort: 4044
85
+ port: 4033
86
+ targetPort: 4033
87
87
  type: LoadBalancer
88
88
  ---
89
89
  apiVersion: apps/v1
@@ -104,7 +104,7 @@ spec:
104
104
  spec:
105
105
  containers:
106
106
  - name: dd-test-development-green
107
- image: localhost/rockylinux9-underpost:v2.85.7
107
+ image: localhost/rockylinux9-underpost:v2.89.0
108
108
  # resources:
109
109
  # requests:
110
110
  # memory: "96294Ki"
@@ -136,39 +136,39 @@ spec:
136
136
  selector:
137
137
  app: dd-test-development-green
138
138
  ports:
139
- - name: 'tcp-4041'
139
+ - name: 'tcp-4030'
140
140
  protocol: TCP
141
- port: 4041
142
- targetPort: 4041
143
- - name: 'udp-4041'
141
+ port: 4030
142
+ targetPort: 4030
143
+ - name: 'udp-4030'
144
144
  protocol: UDP
145
- port: 4041
146
- targetPort: 4041
145
+ port: 4030
146
+ targetPort: 4030
147
147
 
148
- - name: 'tcp-4042'
148
+ - name: 'tcp-4031'
149
149
  protocol: TCP
150
- port: 4042
151
- targetPort: 4042
152
- - name: 'udp-4042'
150
+ port: 4031
151
+ targetPort: 4031
152
+ - name: 'udp-4031'
153
153
  protocol: UDP
154
- port: 4042
155
- targetPort: 4042
154
+ port: 4031
155
+ targetPort: 4031
156
156
 
157
- - name: 'tcp-4043'
157
+ - name: 'tcp-4032'
158
158
  protocol: TCP
159
- port: 4043
160
- targetPort: 4043
161
- - name: 'udp-4043'
159
+ port: 4032
160
+ targetPort: 4032
161
+ - name: 'udp-4032'
162
162
  protocol: UDP
163
- port: 4043
164
- targetPort: 4043
163
+ port: 4032
164
+ targetPort: 4032
165
165
 
166
- - name: 'tcp-4044'
166
+ - name: 'tcp-4033'
167
167
  protocol: TCP
168
- port: 4044
169
- targetPort: 4044
170
- - name: 'udp-4044'
168
+ port: 4033
169
+ targetPort: 4033
170
+ - name: 'udp-4033'
171
171
  protocol: UDP
172
- port: 4044
173
- targetPort: 4044
172
+ port: 4033
173
+ targetPort: 4033
174
174
  type: LoadBalancer
@@ -13,7 +13,7 @@ spec:
13
13
  enableWebsockets: true
14
14
  services:
15
15
  - name: dd-test-development-blue-service
16
- port: 4041
16
+ port: 4030
17
17
  weight: 100
18
18
 
19
19
  - conditions:
@@ -21,7 +21,7 @@ spec:
21
21
  enableWebsockets: true
22
22
  services:
23
23
  - name: dd-test-development-blue-service
24
- port: 4042
24
+ port: 4031
25
25
  weight: 100
26
26
 
27
27
  ---
@@ -38,7 +38,7 @@ spec:
38
38
  enableWebsockets: true
39
39
  services:
40
40
  - name: dd-test-development-blue-service
41
- port: 4043
41
+ port: 4032
42
42
  weight: 100
43
43
 
44
44
  - conditions:
@@ -46,6 +46,6 @@ spec:
46
46
  enableWebsockets: true
47
47
  services:
48
48
  - name: dd-test-development-blue-service
49
- port: 4044
49
+ port: 4033
50
50
  weight: 100
51
51
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.85.7",
5
+ "version": "2.89.0",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -7,9 +7,35 @@ const logger = loggerFactory(import.meta);
7
7
  const FileFactory = {
8
8
  filesExtract: (req) => {
9
9
  const files = [];
10
- if (Array.isArray(req.files.file)) for (const file of req.files.file) files.push(file);
11
- else if (Object.keys(req.files).length > 0)
12
- for (const keyFile of Object.keys(req.files)) files.push(req.files[keyFile]);
10
+ if (!req.files || Object.keys(req.files).length === 0) {
11
+ return files;
12
+ }
13
+
14
+ // Handle standard 'file' field
15
+ if (Array.isArray(req.files.file)) {
16
+ for (const file of req.files.file) files.push(file);
17
+ } else if (req.files.file) {
18
+ files.push(req.files.file);
19
+ }
20
+
21
+ // Handle all other fields (like direction codes)
22
+ for (const keyFile of Object.keys(req.files)) {
23
+ if (keyFile === 'file') continue; // Already handled above
24
+
25
+ const fileOrFiles = req.files[keyFile];
26
+ if (Array.isArray(fileOrFiles)) {
27
+ // Multiple files with same field name
28
+ for (const file of fileOrFiles) {
29
+ if (file && file.data) {
30
+ files.push(file);
31
+ }
32
+ }
33
+ } else if (fileOrFiles && fileOrFiles.data) {
34
+ // Single file
35
+ files.push(fileOrFiles);
36
+ }
37
+ }
38
+
13
39
  return files;
14
40
  },
15
41
  upload: async function (req, File) {
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Baremetal module for managing the generation and deployment of cloud-init configuration files
3
- * and associated scripts for baremetal provisioning.
2
+ * Provides baremetal provisioning and configuration functionalities.
4
3
  * @module src/cli/baremetal.js
5
4
  * @namespace UnderpostBaremetal
6
5
  */
package/src/cli/index.js CHANGED
@@ -393,6 +393,7 @@ program
393
393
  .option('--reset', 'Resets the runner state before execution.')
394
394
  .option('--terminal', 'Enables terminal mode for interactive script execution.')
395
395
  .option('--dev-proxy-port-offset <port-offset>', 'Sets a custom port offset for development proxy.')
396
+ .option('--conf-server-path <conf-server-path>', 'Sets a custom configuration server path.')
396
397
  .description('Runs a script from the specified path.')
397
398
  .action(UnderpostRun.API.callback);
398
399
 
@@ -140,13 +140,20 @@ class UnderpostRepository {
140
140
  .join('');
141
141
  if (history[0]) {
142
142
  for (const commit of history) {
143
+ console.log(
144
+ shellExec(`git show -s --format=%ci ${commit.hash}`, {
145
+ stdout: true,
146
+ silent: true,
147
+ disableLog: true,
148
+ }).trim().green,
149
+ );
143
150
  console.log(commit.hash.yellow, commit.message);
144
151
  console.log(
145
152
  shellExec(`git show --name-status --pretty="" ${commit.hash}`, {
146
153
  stdout: true,
147
154
  silent: true,
148
155
  disableLog: true,
149
- }).red,
156
+ }).trim().red,
150
157
  );
151
158
  }
152
159
  if (options.copy) pbcopy(chainCmd);
package/src/cli/run.js CHANGED
@@ -58,6 +58,8 @@ class UnderpostRun {
58
58
  * @property {string} stdin - The stdin option for the container.
59
59
  * @property {string} restartPolicy - The restart policy for the container.
60
60
  * @property {boolean} terminal - Whether to open a terminal.
61
+ * @property {number} devProxyPortOffset - The port offset for the development proxy.
62
+ * @property {string} confServerPath - The configuration server path.
61
63
  * @memberof UnderpostRun
62
64
  */
63
65
  static DEFAULT_OPTION = {
@@ -80,6 +82,7 @@ class UnderpostRun {
80
82
  restartPolicy: '',
81
83
  terminal: false,
82
84
  devProxyPortOffset: 0,
85
+ confServerPath: '',
83
86
  };
84
87
  /**
85
88
  * @static
@@ -257,30 +260,6 @@ class UnderpostRun {
257
260
  shellExec(`node bin deploy --restore-hosts`);
258
261
  },
259
262
 
260
- /**
261
- * @method cyberia-ide
262
- * @description Starts the development environment (IDE) for both `cyberia-server` and `cyberia-client` repositories.
263
- * @param {string} path - The input value, identifier, or path for the operation.
264
- * @param {Object} options - The default underpost runner options for customizing workflow
265
- * @memberof UnderpostRun
266
- */
267
- 'cyberia-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
268
- const baseCommand = options.dev ? 'node bin' : 'underpost';
269
- shellExec(`${baseCommand} run ide /home/dd/cyberia-server`);
270
- shellExec(`${baseCommand} run ide /home/dd/cyberia-client`);
271
- },
272
- /**
273
- * @method engine-ide
274
- * @description Starts the development environment (IDE) for the `engine` and `engine-private` repositories.
275
- * @param {string} path - The input value, identifier, or path for the operation.
276
- * @param {Object} options - The default underpost runner options for customizing workflow
277
- * @memberof UnderpostRun
278
- */
279
- 'engine-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
280
- const baseCommand = options.dev ? 'node bin' : 'underpost';
281
- shellExec(`${baseCommand} run ide /home/dd/engine`);
282
- shellExec(`${baseCommand} run ide /home/dd/engine/engine-private`);
283
- },
284
263
  /**
285
264
  * @method cluster-build
286
265
  * @description Build configuration for cluster deployment.
@@ -293,8 +272,12 @@ class UnderpostRun {
293
272
  shellExec(`node bin run --dev sync-replica template-deploy`);
294
273
  shellExec(`node bin run sync-replica template-deploy`);
295
274
  shellExec(`node bin env clean`);
296
- shellExec(`git add . && underpost cmt . build cluster-build`);
297
- shellExec(`cd engine-private && git add . && underpost cmt . build cluster-build`);
275
+ for (const deployId of fs.readFileSync('./engine-private/deploy/dd.router', 'utf8').split(','))
276
+ shellExec(`node bin/deploy update-default-conf ${deployId.trim()}`);
277
+ if (path === 'cmt') {
278
+ shellExec(`git add . && underpost cmt . build cluster-build`);
279
+ shellExec(`cd engine-private && git add . && underpost cmt . build cluster-build`);
280
+ }
298
281
  },
299
282
  /**
300
283
  * @method template-deploy
@@ -423,6 +406,7 @@ class UnderpostRun {
423
406
  // Dev usage: node bin run --dev --build sync dd-default
424
407
  const env = options.dev ? 'development' : 'production';
425
408
  const baseCommand = options.dev ? 'node bin' : 'underpost';
409
+ const baseClusterCommand = options.dev ? ' --dev' : '';
426
410
  const defaultPath = [
427
411
  'dd-default',
428
412
  1,
@@ -440,6 +424,8 @@ class UnderpostRun {
440
424
  if (isDeployRunnerContext(path, options)) {
441
425
  const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
442
426
  if (!validVersion) throw new Error('Version mismatch');
427
+ shellExec(`${baseCommand} run${baseClusterCommand} tz`);
428
+ shellExec(`${baseCommand} run${baseClusterCommand} cron`);
443
429
  }
444
430
 
445
431
  const currentTraffic = isDeployRunnerContext(path, options)
@@ -461,6 +447,39 @@ class UnderpostRun {
461
447
  UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
462
448
  } else logger.info('current traffic', UnderpostDeploy.API.getCurrentTraffic(deployId));
463
449
  },
450
+
451
+ /**
452
+ * @method tz
453
+ * @description Sets the system timezone using `timedatectl set-timezone` command.
454
+ * @param {string} path - The input value, identifier, or path for the operation (used as the timezone string).
455
+ * @param {Object} options - The default underpost runner options for customizing workflow
456
+ * @memberof UnderpostRun
457
+ */
458
+ tz: (path, options = UnderpostRun.DEFAULT_OPTION) => {
459
+ const tz = path
460
+ ? path
461
+ : UnderpostRootEnv.API.get('TIME_ZONE', undefined, { disableLog: true })
462
+ ? UnderpostRootEnv.API.get('TIME_ZONE')
463
+ : process.env.TIME_ZONE
464
+ ? process.env.TIME_ZONE
465
+ : 'America/New_York';
466
+ shellExec(`sudo timedatectl set-timezone ${tz}`);
467
+ },
468
+
469
+ /**
470
+ * @method cron
471
+ * @description Sets up and starts the `dd-cron` environment by writing environment variables, starting the cron service, and cleaning up.
472
+ * @param {string} path - The input value, identifier, or path for the operation.
473
+ * @param {Object} options - The default underpost runner options for customizing workflow
474
+ * @memberof UnderpostRun
475
+ */
476
+ cron: (path, options = UnderpostRun.DEFAULT_OPTION) => {
477
+ const env = options.dev ? 'development' : 'production';
478
+ shellExec(`node bin env ${path ? path : 'dd-cron'} ${env}`);
479
+ shellExec(`npm start`);
480
+ shellExec(`node bin env clean`);
481
+ },
482
+
464
483
  /**
465
484
  * @method ls-deployments
466
485
  * @description Retrieves and logs a table of Kubernetes deployments using `UnderpostDeploy.API.get`.
@@ -806,6 +825,22 @@ class UnderpostRun {
806
825
  */
807
826
  dev: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
808
827
  let [deployId, subConf, host, _path, clientHostPort] = path.split(',');
828
+ if (options.confServerPath) {
829
+ const confServer = JSON.parse(fs.readFileSync(options.confServerPath, 'utf8'));
830
+ fs.writeFileSync(
831
+ `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`,
832
+ JSON.stringify(
833
+ {
834
+ [host]: {
835
+ [_path]: confServer[host][_path],
836
+ },
837
+ },
838
+ null,
839
+ 4,
840
+ ),
841
+ 'utf8',
842
+ );
843
+ }
809
844
  if (!deployId) deployId = 'dd-default';
810
845
  if (!host) host = 'default.net';
811
846
  if (!_path) _path = '/';
@@ -820,7 +855,7 @@ class UnderpostRun {
820
855
  envObj.DEV_PROXY_PORT_OFFSET = options.devProxyPortOffset;
821
856
  writeEnv(envPath, envObj);
822
857
  }
823
- shellExec(`node bin run dev-cluster expose`);
858
+ shellExec(`node bin run dev-cluster expose`, { async: true });
824
859
  {
825
860
  const cmd = `npm run dev-api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort}${options.tls ? ' tls' : ''}`;
826
861
  options.terminal ? openTerminal(cmd) : shellExec(cmd, { async: true });
@@ -896,6 +931,34 @@ class UnderpostRun {
896
931
  }
897
932
  },
898
933
 
934
+ /**
935
+ * @method sh
936
+ * @description Enables remote control for the Kitty terminal emulator.
937
+ * @param {string} path - The input value, identifier, or path for the operation.
938
+ * @param {Object} options - The default underpost runner options for customizing workflow
939
+ * @memberof UnderpostRun
940
+ */
941
+ sh: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
942
+ shellExec(`kitty -o allow_remote_control=yes`);
943
+ },
944
+
945
+ /**
946
+ * @method log
947
+ * @description Searches and highlights keywords in a specified log file, optionally showing surrounding lines.
948
+ * @param {string} path - The input value, identifier, or path for the operation (formatted as `filePath,keywords,lines`).
949
+ * @param {Object} options - The default underpost runner options for customizing workflow
950
+ * @memberof UnderpostRun
951
+ */
952
+ log: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
953
+ const [filePath, keywords, lines] = path.split(',');
954
+ let result = shellExec(`grep -i -E ${lines ? `-C ${lines} ` : ''}'${keywords}' ${filePath}`, {
955
+ stdout: true,
956
+ silent: true,
957
+ }).replaceAll(`--`, `==============================`.green.bold);
958
+ for (const keyword of keywords.split('|')) result = result.replaceAll(keyword, keyword.bgYellow.black.bold);
959
+ console.log(result);
960
+ },
961
+
899
962
  /**
900
963
  * @method release-cmt
901
964
  * @description Commits and pushes a new release for the `engine` repository with a message indicating the new version.
@@ -927,15 +990,13 @@ class UnderpostRun {
927
990
  const _path = '/single-replica';
928
991
  const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
929
992
  shellExec(`${baseCommand} env ${deployId} ${env}`);
930
- for (const host of Object.keys(confServer)) {
931
- if (!(_path in confServer[host])) continue;
932
- shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
933
- shellExec(`node bin/deploy build-full-client ${deployId}`);
934
- const node = options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname();
935
- // deployId, replicas, versions, image, node
936
- let defaultPath = [deployId, 1, ``, ``, node];
937
- shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
938
- }
993
+ for (const host of Object.keys(confServer))
994
+ if (_path in confServer[host]) shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
995
+ const node = options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname();
996
+ // deployId, replicas, versions, image, node
997
+ let defaultPath = [deployId, 1, ``, ``, node];
998
+ shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
999
+ shellExec(`node bin/deploy build-full-client ${deployId}`);
939
1000
  }
940
1001
  if (isDeployRunnerContext(path, options)) shellExec(`${baseCommand} run promote ${path} production`);
941
1002
  },