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
package/src/cli/run.js CHANGED
@@ -4,13 +4,14 @@
4
4
  * @namespace UnderpostRun
5
5
  */
6
6
 
7
- import { daemonProcess, getTerminalPid, openTerminal, shellCd, shellExec } from '../server/process.js';
7
+ import { daemonProcess, getTerminalPid, shellCd, shellExec } from '../server/process.js';
8
8
  import {
9
9
  awaitDeployMonitor,
10
10
  buildKindPorts,
11
11
  Config,
12
12
  getNpmRootPath,
13
13
  isDeployRunnerContext,
14
+ loadConfServerJson,
14
15
  writeEnv,
15
16
  } from '../server/conf.js';
16
17
  import { actionInitLog, loggerFactory } from '../server/logger.js';
@@ -55,7 +56,6 @@ const logger = loggerFactory(import.meta);
55
56
  * @property {string} apiVersion - The API version for the container.
56
57
  * @property {string} claimName - The claim name for the volume.
57
58
  * @property {string} kindType - The kind of resource to create.
58
- * @property {boolean} terminal - Whether to open a terminal.
59
59
  * @property {number} devProxyPortOffset - The port offset for the development proxy.
60
60
  * @property {boolean} hostNetwork - Whether to use host networking.
61
61
  * @property {string} requestsMemory - The memory request for the container.
@@ -87,6 +87,7 @@ const logger = loggerFactory(import.meta);
87
87
  * @property {boolean} logs - Whether to enable logs.
88
88
  * @property {boolean} dryRun - Whether to perform a dry run.
89
89
  * @property {boolean} createJobNow - Whether to create the job immediately.
90
+ * @property {number} fromNCommit - Number of commits back to use for message propagation (default: 1, last commit only).
90
91
  * @property {string|Array<{ip: string, hostnames: string[]}>} hostAliases - Adds entries to the Pod /etc/hosts via Kubernetes hostAliases.
91
92
  * As a string (CLI): semicolon-separated entries of "ip=hostname1,hostname2" (e.g., "127.0.0.1=foo.local,bar.local;10.1.2.3=foo.remote").
92
93
  * As an array (programmatic): objects with `ip` and `hostnames` fields (e.g., [{ ip: "127.0.0.1", hostnames: ["foo.local"] }]).
@@ -120,7 +121,6 @@ const DEFAULT_OPTION = {
120
121
  apiVersion: '',
121
122
  claimName: '',
122
123
  kindType: '',
123
- terminal: false,
124
124
  devProxyPortOffset: 0,
125
125
  hostNetwork: false,
126
126
  requestsMemory: '',
@@ -152,6 +152,7 @@ const DEFAULT_OPTION = {
152
152
  logs: false,
153
153
  dryRun: false,
154
154
  createJobNow: false,
155
+ fromNCommit: 0,
155
156
  hostAliases: '',
156
157
  };
157
158
 
@@ -195,7 +196,7 @@ class UnderpostRun {
195
196
  }
196
197
 
197
198
  {
198
- // Detect MongoDB primary pod using centralized method
199
+ // Detect MongoDB primary pod using method
199
200
  let primaryMongoHost = 'mongodb-0.mongodb-service';
200
201
  try {
201
202
  const primaryPodName = Underpost.db.getMongoPrimaryPodName({
@@ -355,58 +356,87 @@ class UnderpostRun {
355
356
  },
356
357
  /**
357
358
  * @method template-deploy
358
- * @description Cleans up, pushes `engine-private` and `engine` repositories with a commit tag `ci package-pwa-microservices-template`.
359
- * @param {string} path - The input value, identifier, or path for the operation.
359
+ * @description Pushes `engine-private`, dispatches CI workflow to build `pwa-microservices-template`,
360
+ * and optionally triggers engine-<conf-id> CI with sync/init which in turn dispatches the CD workflow
361
+ * after the build chain completes (template → ghpkg → engine-<conf-id> → CD).
362
+ * @param {string} path - The deployment path identifier (e.g., 'sync-engine-core', 'init-engine-core', or empty for build-only).
360
363
  * @param {Object} options - The default underpost runner options for customizing workflow
361
364
  * @memberof UnderpostRun
362
365
  */
363
366
  'template-deploy': (path = '', options = DEFAULT_OPTION) => {
364
367
  const baseCommand = options.dev ? 'node bin' : 'underpost';
365
- const message = shellExec(`node bin cmt --changelog --changelog-no-hash`, { silent: true, stdout: true }).trim();
366
- shellExec(`${baseCommand} run clean`);
368
+ shellExec(`npm run security:secrets`);
369
+ const reportPath = './gitleaks-report.json';
370
+ if (fs.existsSync(reportPath) && JSON.parse(fs.readFileSync(reportPath, 'utf8')).length > 0) {
371
+ logger.error('Secrets detected in gitleaks-report.json, aborting template-deploy');
372
+ return;
373
+ }
374
+ shellExec(`${baseCommand} run pull`);
375
+
376
+ // Capture last N commit messages for propagation (default: last 1 commit)
377
+ const fromN = options.fromNCommit && parseInt(options.fromNCommit) > 0 ? parseInt(options.fromNCommit) : 1;
378
+ const message = shellExec(`node bin cmt --changelog ${fromN} --changelog-no-hash`, {
379
+ silent: true,
380
+ stdout: true,
381
+ }).trim();
382
+
367
383
  shellExec(
368
384
  `${baseCommand} push ./engine-private ${options.force ? '-f ' : ''}${
369
385
  process.env.GITHUB_USERNAME
370
386
  }/engine-private`,
371
387
  );
372
388
  shellCd('/home/dd/engine');
389
+
390
+ const sanitizedMessage = Underpost.repo.sanitizeChangelogMessage(message);
391
+
392
+ // Push engine repo so workflow YAML changes reach GitHub
373
393
  shellExec(`git reset`);
374
- function replaceNthNewline(str, n, replacement = ' ') {
375
- let count = 0;
376
- return str.replace(/\r\n?|\n/g, (match) => {
377
- count++;
378
- return count === n ? replacement : match;
379
- });
380
- }
381
- shellExec(
382
- `${baseCommand} cmt . --empty ci package-pwa-microservices-template${
383
- path.startsWith('sync') ? `-${path}` : ''
384
- }${
385
- message
386
- ? ` "${replaceNthNewline(
387
- message.replaceAll('"', '').replaceAll('`', '').replaceAll('#', '').replaceAll('- ', ''),
388
- 2,
389
- )}"`
390
- : ''
391
- }`,
392
- );
393
394
  shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
395
+
396
+ // Determine deploy conf and type from path (sync-engine-core, init-engine-core, etc.)
397
+ let deployConfId = '';
398
+ let deployType = '';
399
+ if (path.startsWith('sync-')) {
400
+ deployConfId = path.replace(/^sync-/, '');
401
+ deployType = 'sync-and-deploy';
402
+ } else if (path.startsWith('init-')) {
403
+ deployConfId = path.replace(/^init-/, '');
404
+ deployType = 'init';
405
+ }
406
+
407
+ // Dispatch npmpkg CI workflow — this builds pwa-microservices-template first.
408
+ // If deployConfId is set, npmpkg.ci.yml will dispatch the engine-<conf-id> CI
409
+ // with sync=true after template build completes. The engine CI then dispatches
410
+ // the CD workflow after the engine repo build finishes — ensuring correct sequence:
411
+ // npmpkg.ci → engine-<id>.ci → engine-<id>.cd
412
+ const repo = `${process.env.GITHUB_USERNAME}/engine`;
413
+ const inputs = {};
414
+ if (sanitizedMessage) inputs.message = sanitizedMessage;
415
+ if (deployConfId) inputs.deploy_conf_id = deployConfId;
416
+ if (deployType) inputs.deploy_type = deployType;
417
+
418
+ Underpost.repo.dispatchWorkflow({
419
+ repo,
420
+ workflowFile: 'npmpkg.ci.yml',
421
+ ref: 'master',
422
+ inputs,
423
+ });
394
424
  },
395
425
 
396
426
  /**
397
427
  * @method template-deploy-image
398
- * @description Commits and pushes a Docker image deployment for the `engine` repository.
428
+ * @description Dispatches the Docker image CI workflow for the `engine` repository.
399
429
  * @param {string} path - The input value, identifier, or path for the operation.
400
430
  * @param {Object} options - The default underpost runner options for customizing workflow
401
431
  * @memberof UnderpostRun
402
432
  */
403
433
  'template-deploy-image': (path, options = DEFAULT_OPTION) => {
404
- // const baseCommand = options.dev ? 'node bin' : 'underpost';
405
- shellExec(
406
- `cd /home/dd/engine && git reset && underpost cmt . --empty ci docker-image 'underpost-engine:${
407
- Underpost.version
408
- }' && underpost push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`,
409
- );
434
+ Underpost.repo.dispatchWorkflow({
435
+ repo: `${process.env.GITHUB_USERNAME}/engine`,
436
+ workflowFile: 'docker-image.ci.yml',
437
+ ref: 'master',
438
+ inputs: {},
439
+ });
410
440
  },
411
441
  /**
412
442
  * @method clean
@@ -467,18 +497,30 @@ class UnderpostRun {
467
497
  },
468
498
  /**
469
499
  * @method ssh-deploy
470
- * @description Performs a Git reset, commits with a message `cd ssh-${path}`, and pushes the `engine` repository, likely triggering an SSH-based CD pipeline.
471
- * @param {string} path - The input value, identifier, or path for the operation (used as the deployment identifier for the commit message).
500
+ * @description Dispatches the corresponding CD workflow for SSH-based deployment, replacing empty commits with workflow_dispatch.
501
+ * @param {string} path - The deployment identifier (e.g., 'engine-core', 'sync-engine-core', 'init-engine-core').
472
502
  * @param {Object} options - The default underpost runner options for customizing workflow
473
503
  * @memberof UnderpostRun
474
504
  */
475
505
  'ssh-deploy': (path, options = DEFAULT_OPTION) => {
476
506
  actionInitLog();
477
- const baseCommand = options.dev ? 'node bin' : 'underpost';
478
- shellCd('/home/dd/engine');
479
- shellExec(`git reset`);
480
- shellExec(`${baseCommand} cmt . --empty cd ssh-${path}`);
481
- shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
507
+
508
+ let job = 'deploy';
509
+ let confId = path;
510
+ if (path.startsWith('sync-')) {
511
+ job = 'sync-and-deploy';
512
+ confId = path.replace(/^sync-/, '');
513
+ } else if (path.startsWith('init-')) {
514
+ job = 'init';
515
+ confId = path.replace(/^init-/, '');
516
+ }
517
+
518
+ Underpost.repo.dispatchWorkflow({
519
+ repo: `${process.env.GITHUB_USERNAME}/engine`,
520
+ workflowFile: `${confId}.cd.yml`,
521
+ ref: 'master',
522
+ inputs: { job },
523
+ });
482
524
  },
483
525
  /**
484
526
  * @method ide
@@ -488,15 +530,25 @@ class UnderpostRun {
488
530
  * @param {Object} options - The default underpost runner options for customizing workflow
489
531
  * @memberof UnderpostRun
490
532
  */
491
- ide: (path, options = DEFAULT_OPTION) => {
492
- const { underpostRoot } = options;
493
- if (path === 'install') {
494
- shellExec(`sudo curl -f https://zed.dev/install.sh | sh`);
495
- shellExec(
496
- `sudo dnf config-manager --add-repo https://download.sublimetext.com/rpm/stable/x86_64/sublime-text.repo`,
497
- );
498
- shellExec(`sudo dnf install -y sublime-text`);
499
- } else shellExec(`node ${underpostRoot}/bin/zed ${path}`);
533
+ ide: (path = '', options = DEFAULT_OPTION) => {
534
+ const underpostRoot = options.dev ? '.' : options.underpostRoot;
535
+ const [projectPath, customIde] = path.split(',');
536
+ if (projectPath === 'install') {
537
+ if (customIde === 'zed') shellExec(`sudo curl -f https://zed.dev/install.sh | sh`);
538
+ else if (customIde === 'subl') {
539
+ shellExec(
540
+ `sudo dnf config-manager --add-repo https://download.sublimetext.com/rpm/stable/x86_64/sublime-text.repo`,
541
+ );
542
+ shellExec(`sudo dnf install -y sublime-text`);
543
+ } else {
544
+ shellExec(`sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc &&
545
+ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\nautorefresh=1\ntype=rpm-md\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/vscode.repo > /dev/null`);
546
+ shellExec(`sudo dnf install -y code`);
547
+ }
548
+ return;
549
+ }
550
+ if (customIde === 'zed') shellExec(`node ${underpostRoot}/bin/zed ${projectPath}`);
551
+ else shellExec(`node ${underpostRoot}/bin/vs ${projectPath}`);
500
552
  },
501
553
  /**
502
554
  * @method crypto-policy
@@ -525,7 +577,7 @@ class UnderpostRun {
525
577
  options.replicas,
526
578
  ``,
527
579
  ``,
528
- options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname(),
580
+ !options.kubeadm && !options.k3s ? 'kind-control-plane' : os.hostname(),
529
581
  ];
530
582
  let [deployId, replicas, versions, image, node] = path ? path.split(',') : defaultPath;
531
583
  deployId = deployId ? deployId : defaultPath[0];
@@ -559,7 +611,7 @@ class UnderpostRun {
559
611
  image ? ` --image ${image}` : ''
560
612
  }${versions ? ` --versions ${versions}` : ''}${
561
613
  options.namespace ? ` --namespace ${options.namespace}` : ''
562
- }${timeoutFlags}${cmdString} dd ${env}`,
614
+ }${timeoutFlags}${cmdString} ${deployId} ${env}`,
563
615
  );
564
616
 
565
617
  if (isDeployRunnerContext(path, options)) {
@@ -1008,9 +1060,7 @@ EOF
1008
1060
  volumeMountPath: volumeHostPath,
1009
1061
  ...(options.dev ? { volumeHostPath } : { claimName }),
1010
1062
  on: {
1011
- init: async () => {
1012
- // openTerminal(`kubectl logs -f ${podName}`);
1013
- },
1063
+ init: async () => {},
1014
1064
  },
1015
1065
  args: [daemonProcess(path ? path : `cd /home/dd/engine && npm install && npm run test`)],
1016
1066
  };
@@ -1145,7 +1195,7 @@ EOF
1145
1195
  const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
1146
1196
  let hosts = [];
1147
1197
  for (const deployId of deployList) {
1148
- const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
1198
+ const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
1149
1199
  hosts = hosts.concat(Object.keys(confServer));
1150
1200
  }
1151
1201
  shellExec(`node bin cluster --prom ${hosts.join(',')}`);
@@ -1318,34 +1368,31 @@ EOF
1318
1368
  if (!subConf) subConf = 'local';
1319
1369
  if (options.reset && fs.existsSync(`./engine-private/conf/${deployId}`))
1320
1370
  fs.removeSync(`./engine-private/conf/${deployId}`);
1321
- if (!fs.existsSync(`./engine-private/conf/${deployId}`)) Config.deployIdFactory(deployId, { subConf });
1322
1371
  if (options.devProxyPortOffset) {
1323
1372
  const envPath = `./engine-private/conf/${deployId}/.env.development`;
1324
1373
  const envObj = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
1325
1374
  envObj.DEV_PROXY_PORT_OFFSET = options.devProxyPortOffset;
1326
1375
  writeEnv(envPath, envObj);
1327
1376
  }
1377
+ dotenv.config({ path: `./engine-private/conf/${deployId}/.env.development`, override: true });
1328
1378
  shellExec(`node bin run dev-cluster --expose --namespace ${options.namespace}`, { async: true });
1329
1379
  {
1330
- const cmd = `npm run dev-api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort}${
1380
+ const cmd = `npm run dev:api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort} proxy${
1331
1381
  options.tls ? ' tls' : ''
1332
1382
  }`;
1333
- options.terminal ? openTerminal(cmd) : shellExec(cmd, { async: true });
1383
+ shellExec(cmd, { async: true });
1334
1384
  }
1335
1385
  await awaitDeployMonitor(true);
1336
1386
  {
1337
- const cmd = `npm run dev-client ${deployId} ${subConf} ${host} ${_path} proxy${options.tls ? ' tls' : ''}`;
1338
- options.terminal
1339
- ? openTerminal(cmd)
1340
- : shellExec(cmd, {
1341
- async: true,
1342
- });
1387
+ const cmd = `npm run dev:client ${deployId} ${subConf} ${host} ${_path} proxy${options.tls ? ' tls' : ''}`;
1388
+
1389
+ shellExec(cmd, {
1390
+ async: true,
1391
+ });
1343
1392
  }
1344
1393
  await awaitDeployMonitor(true);
1345
1394
  shellExec(
1346
- `./node_modules/.bin/env-cmd -f .env.development node src/proxy proxy ${deployId} ${subConf} ${host} ${_path}${
1347
- options.tls ? ' tls' : ''
1348
- }`,
1395
+ `NODE_ENV=development node src/proxy proxy ${deployId} ${subConf} ${host} ${_path}${options.tls ? ' tls' : ''}`,
1349
1396
  );
1350
1397
  },
1351
1398
 
@@ -1364,7 +1411,7 @@ EOF
1364
1411
  let [deployId, serviceId, host, _path, replicas, image, node] = path.split(',');
1365
1412
  if (!replicas) replicas = options.replicas;
1366
1413
  // const confClient = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.client.json`, 'utf8'));
1367
- const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
1414
+ const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
1368
1415
  // const confSSR = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.ssr.json`, 'utf8'));
1369
1416
  // const packageData = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/package.json`, 'utf8'));
1370
1417
  const services = fs.existsSync(`./engine-private/deploy/${deployId}/conf.services.json`)
@@ -1455,9 +1502,7 @@ EOF
1455
1502
  'etc-hosts': async (path = '', options = DEFAULT_OPTION) => {
1456
1503
  const hosts = path ? path.split(',') : [];
1457
1504
  if (options.deployId) {
1458
- const confServer = JSON.parse(
1459
- fs.readFileSync(`./engine-private/conf/${options.deployId}/conf.server.json`, 'utf8'),
1460
- );
1505
+ const confServer = loadConfServerJson(`./engine-private/conf/${options.deployId}/conf.server.json`);
1461
1506
  hosts.push(...Object.keys(confServer));
1462
1507
  }
1463
1508
  const hostListenResult = Underpost.deploy.etcHostFactory(hosts);
@@ -1527,29 +1572,75 @@ EOF
1527
1572
  },
1528
1573
 
1529
1574
  /**
1530
- * @method ptls
1531
- * @description Set on ~/.bashrc alias: ports <port> Command to list listening ports that match the given keyword.
1532
- * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter listening ports).
1575
+ * @method pid-info
1576
+ * @description Displays detailed information about a process by PID, including service details, command line, executable path, working directory, environment variables, and parent process tree.
1577
+ * @param {string} path - The PID of the process to inspect.
1533
1578
  * @param {Object} options - The default underpost runner options for customizing workflow
1534
1579
  * @memberof UnderpostRun
1535
1580
  */
1536
- ptls: async (path = '', options = DEFAULT_OPTION) => {
1537
- shellExec(`chmod +x ${options.underpostRoot}/scripts/ports-ls.sh`);
1538
- shellExec(`${options.underpostRoot}/scripts/ports-ls.sh`);
1581
+ 'pid-info': (path, options = DEFAULT_OPTION) => {
1582
+ const pid = path;
1583
+ if (!pid) {
1584
+ logger.error('PID is required. Usage: underpost run pid-info <pid>');
1585
+ return;
1586
+ }
1587
+
1588
+ // Services
1589
+ logger.info('Process info');
1590
+ shellExec(`sudo ps -p ${pid} -o pid,ppid,user,stime,etime,cmd`);
1591
+ logger.info('Command line');
1592
+ shellExec(`sudo cat /proc/${pid}/cmdline | tr '\\0' ' ' ; echo`);
1593
+ logger.info('Executable path');
1594
+ shellExec(`sudo readlink -f /proc/${pid}/exe`);
1595
+ logger.info('Working directory');
1596
+ shellExec(`sudo readlink -f /proc/${pid}/cwd`);
1597
+ logger.info('Environment variables (first 200)');
1598
+ shellExec(`sudo tr '\\0' '\\n' </proc/${pid}/environ | head -200`);
1599
+
1600
+ // Parent
1601
+ logger.info('Parent process');
1602
+ const parentInfo = shellExec(`sudo ps -o pid,ppid,user,cmd -p ${pid}`, { stdout: true, silent: true });
1603
+ console.log(parentInfo);
1604
+ const ppidMatch = parentInfo.split('\n').find((l) => l.trim().startsWith(pid));
1605
+ if (ppidMatch) {
1606
+ const ppid = ppidMatch.trim().split(/\s+/)[1];
1607
+ logger.info(`Parent PID: ${ppid}`);
1608
+ shellExec(`ps -fp ${ppid}`);
1609
+ }
1610
+ logger.info('Process tree');
1611
+ shellExec(`pstree -s ${pid}`);
1539
1612
  },
1613
+
1540
1614
  /**
1541
- * @method release-cmt
1542
- * @description Commits and pushes a new release for the `engine` repository with a message indicating the new version.
1543
- * @param {string} path - The input value, identifier, or path for the operation.
1615
+ * @method background
1616
+ * @description Runs a custom command in the background using nohup, logging output to `/var/log/<id>.log` and saving the PID to `/var/run/<id>.pid`.
1617
+ * @param {string} path - The command to run in the background (e.g. 'npm run prod:container dd-cyberia-r3').
1544
1618
  * @param {Object} options - The default underpost runner options for customizing workflow
1545
1619
  * @memberof UnderpostRun
1546
1620
  */
1547
- 'release-cmt': async (path, options = DEFAULT_OPTION) => {
1548
- shellExec(`underpost run pull`);
1549
- shellExec(`underpost run secret`);
1550
- shellCd(`/home/dd/engine`);
1551
- shellExec(`underpost cmt --empty . ci engine ' New engine release $(underpost --version)'`);
1552
- shellExec(`underpost push . ${process.env.GITHUB_USERNAME}/engine`, { silent: true });
1621
+ background: (path, options = DEFAULT_OPTION) => {
1622
+ if (!path) {
1623
+ logger.error('Command is required. Usage: underpost run background <command>');
1624
+ return;
1625
+ }
1626
+ const id = path.split(/\s+/).pop();
1627
+ const logFile = `/var/log/${id}.log`;
1628
+ const pidFile = `/var/run/${id}.pid`;
1629
+ logger.info(`Starting background process`, { id, logFile, pidFile });
1630
+ shellExec(`nohup ${path} > ${logFile} 2>&1 & pid=$!; echo $pid > ${pidFile}; disown`);
1631
+ logger.info(`Background process started for '${id}'`);
1632
+ },
1633
+
1634
+ /**
1635
+ * @method ports
1636
+ * @description Set on ~/.bashrc alias: ports <port> Command to list listening ports that match the given keyword.
1637
+ * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter listening ports).
1638
+ * @param {Object} options - The default underpost runner options for customizing workflow
1639
+ * @memberof UnderpostRun
1640
+ */
1641
+ ports: async (path = '', options = DEFAULT_OPTION) => {
1642
+ shellExec(`chmod +x ${options.underpostRoot}/scripts/ports-ls.sh`);
1643
+ shellExec(`${options.underpostRoot}/scripts/ports-ls.sh`);
1553
1644
  },
1554
1645
 
1555
1646
  /**
@@ -1572,42 +1663,11 @@ EOF
1572
1663
  `npm install -g npm@11.2.0`,
1573
1664
  `npm install -g underpost`,
1574
1665
  `${baseCommand} secret underpost --create-from-file /etc/config/.env.${env}`,
1575
- `${baseCommand} start --build --run ${deployId} ${env} --underpost-quickly-install`,
1666
+ `${baseCommand} start --build --run ${deployId} ${env}`,
1576
1667
  ];
1577
1668
  shellExec(`node bin run sync${baseClusterCommand} --deploy-id-cron-jobs none dd-test --cmd "${cmd}"`);
1578
1669
  },
1579
1670
 
1580
- /**
1581
- * @method sync-replica
1582
- * @description Syncs a replica for the dd.router
1583
- * @param {string} path - The input value, identifier, or path for the operation.
1584
- * @param {Object} options - The default underpost runner options for customizing workflow
1585
- * @memberof UnderpostRun
1586
- */
1587
- 'sync-replica': async (path, options = DEFAULT_OPTION) => {
1588
- const env = options.dev ? 'development' : 'production';
1589
- const baseCommand = options.dev ? 'node bin' : 'underpost';
1590
-
1591
- for (let deployId of fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',')) {
1592
- deployId = deployId.trim();
1593
- const _path = '/single-replica';
1594
- const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
1595
- shellExec(`${baseCommand} env ${deployId} ${env}`);
1596
- for (const host of Object.keys(confServer))
1597
- if (_path in confServer[host]) shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
1598
- const node = options.nodeName
1599
- ? options.nodeName
1600
- : options.dev || !isDeployRunnerContext(path, options)
1601
- ? 'kind-control-plane'
1602
- : os.hostname();
1603
- // deployId, replicas, versions, image, node
1604
- let defaultPath = [deployId, 1, ``, ``, node];
1605
- shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
1606
- shellExec(`node bin/deploy build-full-client ${deployId}`);
1607
- }
1608
- if (isDeployRunnerContext(path, options)) shellExec(`${baseCommand} run promote ${path} production`);
1609
- },
1610
-
1611
1671
  /**
1612
1672
  * @method tf-vae-test
1613
1673
  * @description Creates and runs a job pod (`tf-vae-test`) that installs TensorFlow dependencies, clones the TensorFlow docs, and runs the CVAE tutorial script, with a terminal monitor attached.
@@ -1680,7 +1740,7 @@ EOF
1680
1740
  shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${fromPath} ${toPath}`);
1681
1741
  }
1682
1742
 
1683
- openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
1743
+ shellExec(`firefox ${outsPaths.join(' ')}`);
1684
1744
  process.exit(0);
1685
1745
  }
1686
1746
  })();
@@ -4,13 +4,11 @@
4
4
  * @namespace UnderpostSecret
5
5
  */
6
6
 
7
- import dotenv from 'dotenv';
8
7
  import { shellExec } from '../server/process.js';
9
8
  import fs from 'fs-extra';
9
+ import dotenv from 'dotenv';
10
10
  import Underpost from '../index.js';
11
11
 
12
- dotenv.config();
13
-
14
12
  /**
15
13
  * @class UnderpostSecret
16
14
  * @description Manages the secrets of the application.
package/src/cli/ssh.js CHANGED
@@ -497,7 +497,7 @@ EOF`);
497
497
  },
498
498
 
499
499
  /**
500
- * Generic SSH remote command runner that centralizes SSH execution logic.
500
+ * Generic SSH remote command runner that SSH execution logic.
501
501
  * Executes arbitrary shell commands on a remote server via SSH with proper credential handling.
502
502
  * @async
503
503
  * @function sshRemoteRunner