cyberia 3.0.3 → 3.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/{.env.production → .env.example} +20 -4
  2. package/.github/workflows/engine-cyberia.cd.yml +43 -10
  3. package/.github/workflows/engine-cyberia.ci.yml +48 -26
  4. package/.github/workflows/ghpkg.ci.yml +5 -5
  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 +60 -14
  8. package/.github/workflows/publish.ci.yml +26 -7
  9. package/.github/workflows/publish.cyberia.ci.yml +5 -5
  10. package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -7
  11. package/.github/workflows/pwa-microservices-template-test.ci.yml +4 -4
  12. package/.github/workflows/release.cd.yml +14 -8
  13. package/.vscode/extensions.json +9 -8
  14. package/.vscode/settings.json +3 -2
  15. package/CHANGELOG.md +643 -1
  16. package/CLI-HELP.md +132 -57
  17. package/Dockerfile +4 -2
  18. package/README.md +347 -22
  19. package/WHITE-PAPER.md +1540 -0
  20. package/bin/build.js +21 -12
  21. package/bin/cyberia.js +2640 -106
  22. package/bin/deploy.js +258 -372
  23. package/bin/file.js +5 -1
  24. package/bin/index.js +2640 -106
  25. package/bin/vs.js +3 -3
  26. package/conf.js +169 -105
  27. package/deployment.yaml +236 -20
  28. package/hardhat/.env.example +31 -0
  29. package/hardhat/README.md +531 -0
  30. package/hardhat/WHITE-PAPER.md +1540 -0
  31. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  32. package/hardhat/deployments/.gitkeep +0 -0
  33. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  34. package/hardhat/hardhat.config.js +136 -0
  35. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  36. package/hardhat/networks/besu-object-layer.network.json +138 -0
  37. package/hardhat/package-lock.json +4323 -0
  38. package/hardhat/package.json +36 -0
  39. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  40. package/hardhat/test/ObjectLayerToken.js +592 -0
  41. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  42. package/hardhat/types/ethers-contracts/common.ts +92 -0
  43. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  44. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  45. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  46. package/hardhat/types/ethers-contracts/index.ts +6 -0
  47. package/jsdoc.dd-cyberia.json +68 -0
  48. package/jsdoc.json +65 -49
  49. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
  50. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
  51. package/manifests/deployment/dd-cyberia-development/deployment.yaml +562 -0
  52. package/manifests/deployment/dd-cyberia-development/proxy.yaml +297 -0
  53. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
  54. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  55. package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
  56. package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
  57. package/manifests/deployment/playwright/deployment.yaml +1 -1
  58. package/manifests/pv-pvc-dd.yaml +1 -1
  59. package/nodemon.json +1 -1
  60. package/package.json +60 -48
  61. package/proxy.yaml +118 -10
  62. package/pv-pvc.yaml +132 -0
  63. package/scripts/k3s-node-setup.sh +1 -1
  64. package/scripts/ports-ls.sh +2 -0
  65. package/scripts/rhel-grpc-setup.sh +56 -0
  66. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +47 -1
  67. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +17 -2
  68. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  69. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
  70. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
  71. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  72. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
  73. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
  74. package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
  75. package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
  76. package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
  77. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  78. package/src/api/cyberia-instance/cyberia-fallback-world.js +368 -0
  79. package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
  80. package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
  81. package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
  82. package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
  83. package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -0
  84. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
  85. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +413 -0
  86. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -0
  87. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
  88. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +42 -0
  89. package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
  90. package/src/api/cyberia-map/cyberia-map.model.js +30 -0
  91. package/src/api/cyberia-map/cyberia-map.router.js +40 -0
  92. package/src/api/cyberia-map/cyberia-map.service.js +74 -0
  93. package/src/api/document/document.service.js +1 -1
  94. package/src/api/file/file.controller.js +3 -1
  95. package/src/api/file/file.ref.json +18 -0
  96. package/src/api/file/file.service.js +28 -5
  97. package/src/api/ipfs/ipfs.controller.js +4 -25
  98. package/src/api/ipfs/ipfs.model.js +43 -34
  99. package/src/api/ipfs/ipfs.router.js +8 -13
  100. package/src/api/ipfs/ipfs.service.js +56 -104
  101. package/src/api/object-layer/README.md +347 -22
  102. package/src/api/object-layer/object-layer.controller.js +6 -2
  103. package/src/api/object-layer/object-layer.model.js +12 -8
  104. package/src/api/object-layer/object-layer.router.js +698 -42
  105. package/src/api/object-layer/object-layer.service.js +119 -37
  106. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
  107. package/src/api/user/user.router.js +10 -5
  108. package/src/api/user/user.service.js +15 -14
  109. package/src/cli/baremetal.js +6 -10
  110. package/src/cli/cloud-init.js +0 -3
  111. package/src/cli/cluster.js +7 -7
  112. package/src/cli/db.js +723 -857
  113. package/src/cli/deploy.js +215 -105
  114. package/src/cli/env.js +34 -5
  115. package/src/cli/fs.js +5 -4
  116. package/src/cli/image.js +0 -3
  117. package/src/cli/index.js +83 -15
  118. package/src/cli/kubectl.js +211 -0
  119. package/src/cli/monitor.js +5 -6
  120. package/src/cli/release.js +284 -0
  121. package/src/cli/repository.js +708 -62
  122. package/src/cli/run.js +371 -151
  123. package/src/cli/secrets.js +73 -2
  124. package/src/cli/ssh.js +1 -1
  125. package/src/cli/test.js +3 -3
  126. package/src/client/Cryptokoyn.index.js +3 -4
  127. package/src/client/CyberiaPortal.index.js +3 -4
  128. package/src/client/Default.index.js +3 -4
  129. package/src/client/Itemledger.index.js +4 -963
  130. package/src/client/Underpost.index.js +3 -4
  131. package/src/client/components/core/AgGrid.js +20 -5
  132. package/src/client/components/core/Alert.js +2 -2
  133. package/src/client/components/core/AppStore.js +69 -0
  134. package/src/client/components/core/CalendarCore.js +2 -2
  135. package/src/client/components/core/Content.js +22 -3
  136. package/src/client/components/core/Docs.js +30 -6
  137. package/src/client/components/core/DropDown.js +137 -17
  138. package/src/client/components/core/FileExplorer.js +71 -4
  139. package/src/client/components/core/Input.js +1 -1
  140. package/src/client/components/core/Keyboard.js +2 -2
  141. package/src/client/components/core/LogIn.js +2 -2
  142. package/src/client/components/core/LogOut.js +2 -2
  143. package/src/client/components/core/Modal.js +20 -7
  144. package/src/client/components/core/Panel.js +0 -1
  145. package/src/client/components/core/PanelForm.js +19 -19
  146. package/src/client/components/core/RichText.js +1 -2
  147. package/src/client/components/core/SocketIo.js +82 -29
  148. package/src/client/components/core/SocketIoHandler.js +75 -0
  149. package/src/client/components/core/Stream.js +143 -95
  150. package/src/client/components/core/Webhook.js +40 -7
  151. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  152. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
  153. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
  154. package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
  155. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
  156. package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
  157. package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
  158. package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
  159. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
  160. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  161. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +217 -30
  162. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
  163. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -4
  164. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
  165. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +104 -9
  166. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +5 -0
  167. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
  168. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
  169. package/src/client/components/default/AppStoreDefault.js +5 -0
  170. package/src/client/components/default/LogInDefault.js +3 -3
  171. package/src/client/components/default/LogOutDefault.js +2 -2
  172. package/src/client/components/default/MenuDefault.js +5 -5
  173. package/src/client/components/default/SocketIoDefault.js +3 -51
  174. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  175. package/src/client/components/itemledger/LogInItemledger.js +3 -3
  176. package/src/client/components/itemledger/LogOutItemledger.js +2 -2
  177. package/src/client/components/itemledger/MenuItemledger.js +3 -3
  178. package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
  179. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  180. package/src/client/components/underpost/CssUnderpost.js +59 -0
  181. package/src/client/components/underpost/LogInUnderpost.js +6 -3
  182. package/src/client/components/underpost/LogOutUnderpost.js +4 -2
  183. package/src/client/components/underpost/MenuUnderpost.js +104 -18
  184. package/src/client/components/underpost/RoutesUnderpost.js +2 -0
  185. package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
  186. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  187. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  188. package/src/client/public/cryptokoyn/microdata.json +85 -0
  189. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  190. package/src/client/public/cryptokoyn/sitemap +3 -3
  191. package/src/client/public/default/sitemap +3 -3
  192. package/src/client/public/itemledger/browserconfig.xml +2 -2
  193. package/src/client/public/itemledger/manifest.webmanifest +4 -4
  194. package/src/client/public/itemledger/microdata.json +71 -0
  195. package/src/client/public/itemledger/sitemap +3 -3
  196. package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
  197. package/src/client/public/test/sitemap +3 -3
  198. package/src/client/services/core/core.service.js +20 -8
  199. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
  200. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  201. package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
  202. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  203. package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
  204. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
  205. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  206. package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
  207. package/src/client/services/instance/instance.management.js +2 -2
  208. package/src/client/services/ipfs/ipfs.service.js +3 -23
  209. package/src/client/services/object-layer/object-layer.management.js +3 -3
  210. package/src/client/services/object-layer/object-layer.service.js +21 -0
  211. package/src/client/services/user/user.management.js +2 -2
  212. package/src/client/ssr/body/404.js +15 -11
  213. package/src/client/ssr/body/500.js +15 -11
  214. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  215. package/src/client/ssr/head/PwaItemledger.js +60 -0
  216. package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
  217. package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
  218. package/src/client/ssr/pages/Test.js +11 -10
  219. package/src/client.build.js +0 -3
  220. package/src/client.dev.js +0 -3
  221. package/src/db/DataBaseProvider.js +17 -2
  222. package/src/db/mariadb/MariaDB.js +14 -9
  223. package/src/db/mongo/MongooseDB.js +17 -1
  224. package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
  225. package/src/grpc/cyberia/README.md +326 -0
  226. package/src/grpc/cyberia/grpc-server.js +530 -0
  227. package/src/index.js +24 -1
  228. package/src/proxy.js +0 -3
  229. package/src/runtime/express/Dockerfile +4 -0
  230. package/src/runtime/express/Express.js +33 -10
  231. package/src/runtime/lampp/Dockerfile +13 -2
  232. package/src/runtime/lampp/Lampp.js +33 -17
  233. package/src/runtime/wp/Dockerfile +68 -0
  234. package/src/runtime/wp/Wp.js +639 -0
  235. package/src/server/auth.js +36 -15
  236. package/src/server/backup.js +39 -12
  237. package/src/server/besu-genesis-generator.js +1630 -0
  238. package/src/server/client-build-docs.js +133 -17
  239. package/src/server/client-build-live.js +9 -18
  240. package/src/server/client-build.js +229 -101
  241. package/src/server/client-dev-server.js +14 -13
  242. package/src/server/client-formatted.js +109 -57
  243. package/src/server/conf.js +391 -164
  244. package/src/server/cron.js +27 -24
  245. package/src/server/dns.js +29 -12
  246. package/src/server/downloader.js +0 -2
  247. package/src/server/ipfs-client.js +24 -1
  248. package/src/server/logger.js +27 -9
  249. package/src/server/object-layer.js +217 -103
  250. package/src/server/peer.js +8 -2
  251. package/src/server/process.js +1 -50
  252. package/src/server/proxy.js +4 -8
  253. package/src/server/runtime.js +30 -9
  254. package/src/server/semantic-layer-generator-floor.js +359 -0
  255. package/src/server/semantic-layer-generator-skin.js +1294 -0
  256. package/src/server/semantic-layer-generator.js +116 -555
  257. package/src/server/ssr.js +0 -3
  258. package/src/server/start.js +19 -12
  259. package/src/server/tls.js +0 -2
  260. package/src/server.js +0 -4
  261. package/src/ws/IoInterface.js +1 -10
  262. package/src/ws/IoServer.js +14 -33
  263. package/src/ws/core/channels/core.ws.chat.js +65 -20
  264. package/src/ws/core/channels/core.ws.mailer.js +113 -32
  265. package/src/ws/core/channels/core.ws.stream.js +90 -31
  266. package/src/ws/core/core.ws.connection.js +12 -33
  267. package/src/ws/core/core.ws.emit.js +10 -26
  268. package/src/ws/core/core.ws.server.js +25 -58
  269. package/src/ws/default/channels/default.ws.main.js +53 -12
  270. package/src/ws/default/default.ws.connection.js +26 -13
  271. package/src/ws/default/default.ws.server.js +30 -12
  272. package/.env.development +0 -43
  273. package/.env.test +0 -43
  274. package/hardhat/contracts/CryptoKoyn.sol +0 -59
  275. package/hardhat/contracts/ItemLedger.sol +0 -73
  276. package/hardhat/contracts/Lock.sol +0 -34
  277. package/hardhat/hardhat.config.cjs +0 -45
  278. package/hardhat/ignition/modules/Lock.js +0 -18
  279. package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
  280. package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
  281. package/hardhat/scripts/deployItemledger.cjs +0 -25
  282. package/hardhat/test/Lock.js +0 -126
  283. package/hardhat/white-paper.md +0 -581
  284. package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
  285. package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
  286. package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
  287. package/src/client/components/default/ElementsDefault.js +0 -38
  288. package/src/client/components/itemledger/CommonItemledger.js +0 -29
  289. package/src/client/components/itemledger/ElementsItemledger.js +0 -38
  290. package/src/client/components/underpost/CommonUnderpost.js +0 -29
  291. package/src/client/components/underpost/ElementsUnderpost.js +0 -38
  292. package/src/ws/core/management/core.ws.chat.js +0 -8
  293. package/src/ws/core/management/core.ws.mailer.js +0 -16
  294. package/src/ws/core/management/core.ws.stream.js +0 -8
  295. package/src/ws/default/management/default.ws.main.js +0 -8
  296. package/white-paper.md +0 -581
package/src/cli/fs.js CHANGED
@@ -6,14 +6,12 @@
6
6
 
7
7
  import { v2 as cloudinary } from 'cloudinary';
8
8
  import { loggerFactory } from '../server/logger.js';
9
- import dotenv from 'dotenv';
10
9
  import AdmZip from 'adm-zip';
11
10
  import * as dir from 'path';
12
11
  import fs from 'fs-extra';
13
12
  import Downloader from '../server/downloader.js';
14
13
  import { shellExec } from '../server/process.js';
15
14
  import Underpost from '../index.js';
16
- dotenv.config();
17
15
 
18
16
  const logger = loggerFactory(import.meta);
19
17
 
@@ -103,13 +101,16 @@ class UnderpostFileStorage {
103
101
  }
104
102
  }
105
103
  if (options.pull === true) {
104
+ let pullSkipCount = 0;
106
105
  for (const _path of Object.keys(storage)) {
107
106
  if (!fs.existsSync(_path) || options.force === true) {
108
107
  if (options.force === true && fs.existsSync(_path)) fs.removeSync(_path);
109
108
  await Underpost.fs.pull(_path, options);
110
- } else logger.warn(`Pull path already exists`, _path);
109
+ } else pullSkipCount++;
111
110
  }
112
- shellExec(`cd ${path} && git init && git add . && git commit -m "Base pull state"`);
111
+ if (pullSkipCount > 0) logger.warn(`Pull skipped ${pullSkipCount} files that already exist`);
112
+ Underpost.repo.initLocalRepo({ path });
113
+ shellExec(`cd ${path} && git add . && git commit -m "Base pull state"`);
113
114
  } else {
114
115
  const files =
115
116
  options.git === true ? Underpost.repo.getChangedFiles(path) : await fs.readdir(path, { recursive: true });
package/src/cli/image.js CHANGED
@@ -5,14 +5,11 @@
5
5
  */
6
6
 
7
7
  import fs from 'fs-extra';
8
- import dotenv from 'dotenv';
9
8
  import { loggerFactory } from '../server/logger.js';
10
9
  import Underpost from '../index.js';
11
10
  import { getNpmRootPath, getUnderpostRootPath } from '../server/conf.js';
12
11
  import { shellExec } from '../server/process.js';
13
12
 
14
- dotenv.config();
15
-
16
13
  const logger = loggerFactory(import.meta);
17
14
 
18
15
  /**
package/src/cli/index.js CHANGED
@@ -7,11 +7,10 @@ import { commitData } from '../client/components/core/CommonJs.js';
7
7
 
8
8
  import Underpost from '../index.js';
9
9
 
10
- const underpostRootPath = getUnderpostRootPath();
10
+ const underpostGlobalEnv = `${getUnderpostRootPath()}/.env`;
11
11
 
12
- fs.existsSync(`${underpostRootPath}/.env`)
13
- ? dotenv.config({ path: `${underpostRootPath}/.env`, override: true })
14
- : dotenv.config();
12
+ if (fs.existsSync(underpostGlobalEnv)) dotenv.config({ path: underpostGlobalEnv, override: true, quiet: true });
13
+ else dotenv.config({ quiet: true });
15
14
 
16
15
  const program = new Command();
17
16
 
@@ -27,6 +26,10 @@ program
27
26
  .option('--build', 'Build the deployment to pwa-microservices-template (requires --deploy-id)')
28
27
  .option('--clean-template', 'Clean the build directory (pwa-microservices-template)')
29
28
  .option('--sync-conf', 'Sync configuration to private repositories (requires --deploy-id)')
29
+ .option(
30
+ '--sync-start',
31
+ "Sync start scripts in deploy ID package.json with root package.json (use 'dd' as --deploy-id to sync all dd.router)",
32
+ )
30
33
  .option('--purge', 'Remove deploy ID conf and all related repositories (requires --deploy-id)')
31
34
  .option('--dev', 'Sets the development cli context')
32
35
  .option('--default-conf', 'Create default deploy ID conf env files')
@@ -34,6 +37,20 @@ program
34
37
  .description('Initializes a new Underpost project, service, or configuration.')
35
38
  .action(Underpost.repo.new);
36
39
 
40
+ program
41
+ .command('client')
42
+ .argument('[deploy-id]', 'The deployment ID to build.', 'dd-default')
43
+ .argument('[sub-conf]', 'The sub-configuration for the build.', '')
44
+ .argument('[host]', 'Comma-separated hosts to filter the build.', '')
45
+ .argument('[path]', 'Comma-separated paths to filter the build.', '')
46
+ .option('--sync-env-port', 'Sync environment port assignments across all deploy IDs')
47
+ .option('--single-replica', 'Build single replica folders instead of full client')
48
+ .option('--build-zip', 'Create zip files of the builds')
49
+ .option('--lite-build', 'Skip full build (default is full build)')
50
+ .option('--icons-build', 'Build icons')
51
+ .description('Builds client assets, single replicas, and/or syncs environment ports.')
52
+ .action(Underpost.repo.client);
53
+
37
54
  program
38
55
  .command('start')
39
56
  .argument('<deploy-id>', 'The unique identifier for the deployment configuration.')
@@ -44,6 +61,7 @@ program
44
61
  .option('--run', 'Starts application servers and monitors their health.')
45
62
  .option('--build', 'Triggers the client-side application build process.')
46
63
  .option('--underpost-quickly-install', 'Uses Underpost Quickly Install for dependency installation.')
64
+ .option('--skip-pull-base', 'Skips cloning repositories, uses current workspace code directly.')
47
65
  .action(Underpost.start.callback)
48
66
  .description('Initiates application servers, build pipelines, or other defined services based on the deployment ID.');
49
67
 
@@ -51,7 +69,7 @@ program
51
69
  .command('clone')
52
70
  .argument(`<uri>`, 'The URI of the GitHub repository (e.g., "username/repository").')
53
71
  .option('--bare', 'Performs a bare clone, downloading only the .git files.')
54
- .option('-g8', 'Uses the g8 repository extension for cloning.')
72
+ .option('--g8', 'Uses the g8 repository extension for cloning.')
55
73
  .description('Clones a specified GitHub repository into the current directory.')
56
74
  .action(Underpost.repo.clone);
57
75
 
@@ -60,7 +78,7 @@ program
60
78
  .argument('<path>', 'The absolute or relative directory path where the repository is located.')
61
79
  .argument(`<uri>`, 'The URI of the GitHub repository (e.g., "username/repository").')
62
80
  .description('Pulls the latest changes from a specified GitHub repository.')
63
- .option('-g8', 'Uses the g8 repository extension for pulling.')
81
+ .option('--g8', 'Uses the g8 repository extension for pulling.')
64
82
  .action(Underpost.repo.pull);
65
83
 
66
84
  program
@@ -69,7 +87,7 @@ program
69
87
  .argument(`[commit-type]`, `The type of commit to perform. Options: ${Object.keys(commitData).join(', ')}.`)
70
88
  .argument(`[module-tag]`, 'Optional: Sets a specific module tag for the commit.')
71
89
  .argument(`[message]`, 'Optional: Provides an additional custom message for the commit.')
72
- .option(`--log <latest-n>`, 'Shows commit history from the specified number of latest n path commits.')
90
+ .option(`--log [latest-n]`, 'Shows commit history from the specified number of latest n path commits.')
73
91
  .option('--last-msg <latest-n>', 'Displays the last n commit message.')
74
92
  .option('--empty', 'Allows committing with empty files.')
75
93
  .option('--copy', 'Copies the generated commit message to the clipboard.')
@@ -90,6 +108,14 @@ program
90
108
  '--changelog-no-hash',
91
109
  'Excludes commit hashes from the generated changelog entries (used with --changelog-build).',
92
110
  )
111
+ .option('--unpush', 'With --log, automatically sets range to unpushed commits ahead of remote.')
112
+ .option('-b', 'Shows the current Git branch name.')
113
+ .option('-p [branch]', 'Shows the reflog for the specified branch.')
114
+ .option('--bc <commit-hash>', 'Shows branches that contain the specified commit.')
115
+ .option(
116
+ '--is-remote-repo <url-repo>',
117
+ 'Checks whether a remote Git repository URL is reachable. Prints true or false.',
118
+ )
93
119
  .description('Manages commits to a GitHub repository, supporting various commit types and options.')
94
120
  .action(Underpost.repo.commit);
95
121
 
@@ -98,7 +124,7 @@ program
98
124
  .argument('<path>', 'The absolute or relative directory path of the repository.')
99
125
  .argument(`<uri>`, 'The URI of the GitHub repository (e.g., "username/repository").')
100
126
  .option('-f', 'Forces the push, overwriting the remote repository history.')
101
- .option('-g8', 'Uses the g8 repository extension for pushing.')
127
+ .option('--g8', 'Uses the g8 repository extension for pushing.')
102
128
  .description('Pushes committed changes from a local repository to a remote GitHub repository.')
103
129
  .action(Underpost.repo.push);
104
130
 
@@ -112,11 +138,11 @@ program
112
138
  .argument('[subConf]', 'Optional: The sub configuration to set.')
113
139
  .description('Sets environment variables and configurations related to a specific deployment ID.')
114
140
  .action((deployId, env, subConf) => {
115
- if (fs.existsSync(`./engine-private/conf/${deployId}/.env.${env}`))
116
- dotenv.config({ path: `./engine-private/conf/${deployId}/.env.${env}`, override: true });
117
- else if (deployId === 'root') {
118
- deployId = Underpost.env.get('DEPLOY_ID');
119
- } else dotenv.config({ path: `./.env`, override: true });
141
+ if (deployId === 'root') {
142
+ const underpostRootDeployId = Underpost.env.get('DEPLOY_ID');
143
+ if (underpostRootDeployId) deployId = underpostRootDeployId;
144
+ }
145
+ if (env) process.env.NODE_ENV = env;
120
146
  loadConf(deployId, subConf);
121
147
  });
122
148
 
@@ -289,6 +315,9 @@ program
289
315
  'Retrieves current network traffic data from resource deployments and the host machine network configuration.',
290
316
  )
291
317
  .option('--kubeadm', 'Enables the kubeadm context for deployment operations.')
318
+ .option('--k3s', 'Enables the k3s context for deployment operations.')
319
+ .option('--kind', 'Enables the kind context for deployment operations.')
320
+ .option('--git-clean', 'Runs git clean on volume mount paths before copying.')
292
321
  .option('--etc-hosts', 'Enables the etc-hosts context for deployment operations.')
293
322
  .option('--restore-hosts', 'Restores default `/etc/hosts` entries.')
294
323
  .option('--disable-update-underpost-config', 'Disables updates to Underpost configuration during deployment.')
@@ -308,10 +337,14 @@ program
308
337
  .argument('<platform>', `The secret management platform. Options: ${Object.keys(Underpost.secret).join(', ')}.`)
309
338
  .option('--init', 'Initializes the secrets platform environment.')
310
339
  .option('--create-from-file <path-env-file>', 'Creates secrets from a specified environment file.')
340
+ .option('--create-from-env', 'Creates secrets from container environment variables (envFrom: secretRef).')
341
+ .option('--global-clean', 'Removes all filesystem traces of secrets (engine-private, .env, conf cache).')
311
342
  .option('--list', 'Lists all available secrets for the platform.')
312
343
  .description(`Manages secrets for various platforms.`)
313
344
  .action((...args) => {
345
+ if (args[1].globalClean) return Underpost.secret.globalSecretClean();
314
346
  if (args[1].createFromFile) return Underpost.secret[args[0]].createFromEnvFile(args[1].createFromFile);
347
+ if (args[1].createFromEnv) return Underpost.secret[args[0]].createFromContainerEnv();
315
348
  if (args[1].list) return Underpost.secret[args[0]].list();
316
349
  if (args[1].init) return Underpost.secret[args[0]].init();
317
350
  });
@@ -394,6 +427,7 @@ program
394
427
  .option('--kubeadm', 'Enables the kubeadm context for database operations.')
395
428
  .option('--kind', 'Enables the kind context for database operations.')
396
429
  .option('--k3s', 'Enables the k3s context for database operations.')
430
+ .option('--repo-backup', 'Backs up repositories (git commit+push) inside deployment pods via kubectl exec.')
397
431
  .description(
398
432
  'Manages database operations with support for MariaDB and MongoDB, including import/export, multi-pod targeting, and Git integration.',
399
433
  )
@@ -410,6 +444,7 @@ program
410
444
  .option('--instances', 'Apply to instance data collection')
411
445
  .option('--generate', 'Generate cluster metadata')
412
446
  .option('--itc', 'Apply under container execution context')
447
+ .option('--dev', 'Sets the development cli context')
413
448
  .description('Manages cluster metadata operations, including import and export.')
414
449
  .action(Underpost.db.clusterMetadataBackupCallback);
415
450
 
@@ -439,7 +474,6 @@ program
439
474
  '--create-job-now',
440
475
  'After applying manifests, immediately create a Job from each CronJob (requires --apply).',
441
476
  )
442
- .option('--ssh', 'Execute backup commands via SSH on the remote node instead of locally.')
443
477
  .description('Manages cron jobs: execute jobs directly or generate and apply K8s CronJob manifests.')
444
478
  .action(Underpost.cron.callback);
445
479
 
@@ -556,7 +590,6 @@ program
556
590
  .option('--force', 'Forces operation, overriding any warnings or conflicts.')
557
591
  .option('--tls', 'Enables TLS for the runner execution.')
558
592
  .option('--reset', 'Resets the runner state before execution.')
559
- .option('--terminal', 'Enables terminal mode for interactive script execution.')
560
593
  .option('--dev-proxy-port-offset <port-offset>', 'Sets a custom port offset for development proxy.')
561
594
  .option('--host-network', 'Enables host network mode for the runner execution.')
562
595
  .option('--requests-memory <requests-memory>', 'Requests memory limit for the runner execution.')
@@ -579,6 +612,7 @@ program
579
612
  .option('--kubeadm', 'Sets the kubeadm cluster context for the runner execution.')
580
613
  .option('--k3s', 'Sets the k3s cluster context for the runner execution.')
581
614
  .option('--kind', 'Sets the kind cluster context for the runner execution.')
615
+ .option('--git-clean', 'Runs git clean on volume mount paths before copying.')
582
616
  .option('--log-type <log-type>', 'Sets the log type for the runner execution.')
583
617
  .option('--deploy-id <deploy-id>', 'Sets deploy id context for the runner execution.')
584
618
  .option('--user <user>', 'Sets user context for the runner execution.')
@@ -608,6 +642,10 @@ program
608
642
  'Sets the maximum number of status check attempts (default: 600).',
609
643
  )
610
644
  .option('--dry-run', 'Preview operations without executing them.')
645
+ .option(
646
+ '--from-n-commit <n>',
647
+ 'Number of commits back to use for message propagation in template-deploy (default: 1, last commit only).',
648
+ )
611
649
  .option(
612
650
  '--create-job-now',
613
651
  'After applying cron manifests, immediately create a Job from each CronJob (forwarded to cron runner).',
@@ -618,6 +656,7 @@ program
618
656
  'Format: semicolon-separated entries of "ip=hostname1,hostname2" ' +
619
657
  '(e.g., "127.0.0.1=foo.local,bar.local;10.1.2.3=foo.remote,bar.remote").',
620
658
  )
659
+ .option('--copy', 'Copies the runner output to the clipboard (supported by: generate-pass, template-deploy-local).')
621
660
  .description('Runs specified scripts using various runners.')
622
661
  .action(Underpost.run.callback);
623
662
 
@@ -742,4 +781,33 @@ program
742
781
  )
743
782
  .action(Underpost.baremetal.callback);
744
783
 
784
+ program
785
+ .command('release')
786
+ .argument('[version]', 'The new version string to set (e.g., "3.1.4"). Defaults to current version.')
787
+ .option('--build', 'Builds a new version: tests template, bumps versions, rebuilds manifests and configs.')
788
+ .option('--deploy', 'Deploys the release: syncs secrets, commits, and pushes to remote repositories.')
789
+ .option(
790
+ '--ci-push <deploy-id>',
791
+ 'Local equivalent of engine-*.ci.yml: builds dd-{deploy-id} and pushes to the engine-{deploy-id} repository. ' +
792
+ 'Accepts the suffix (e.g., "cyberia"), "dd-cyberia", or "engine-cyberia".',
793
+ )
794
+ .option(
795
+ '--message <message>',
796
+ 'Commit message for --ci-push or --pwa-build (defaults to last commit of the engine repository).',
797
+ )
798
+ .option(
799
+ '--pwa-build',
800
+ 'Runs the pwa-microservices-template update flow: always re-clones, syncs engine sources, installs, builds, and pushes.',
801
+ )
802
+ .description('Release orchestrator for building new versions and deploying releases of the Underpost CLI.')
803
+ .action(async (version, options) => {
804
+ if (options.build) return Underpost.release.build(version, options);
805
+ if (options.deploy) return Underpost.release.deploy(version, options);
806
+ if (options.ciPush) return Underpost.release.ci(options.ciPush, options.message, options);
807
+ if (options.pwaBuild) return Underpost.release.pwa(options.message, options);
808
+ console.log(
809
+ 'Please specify --build, --deploy, --ci-push, or --pwa-build. Use "underpost release --help" for details.',
810
+ );
811
+ });
812
+
745
813
  export { program };
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Kubectl module providing low-level Kubernetes resource management primitives.
3
+ * Centralises pod querying, file transfer, and in-container execution operations
4
+ * that were previously scattered across db, deploy, and cluster modules.
5
+ * @module src/cli/kubectl.js
6
+ * @namespace UnderpostKubectl
7
+ */
8
+
9
+ import { loggerFactory } from '../server/logger.js';
10
+ import { shellExec } from '../server/process.js';
11
+ import Underpost from '../index.js';
12
+
13
+ const logger = loggerFactory(import.meta);
14
+
15
+ /**
16
+ * Redacts credentials from shell command strings before logging.
17
+ * Masks passwords in `-p<password>`, `--password=<password>`, and `-P <password>` patterns.
18
+ * @param {string} cmd - The raw command string.
19
+ * @returns {string} The command with credentials replaced by `***`.
20
+ * @memberof UnderpostKubectl
21
+ */
22
+ const sanitizeCommand = (cmd) => {
23
+ if (typeof cmd !== 'string') return cmd;
24
+ return cmd
25
+ .replace(/-p['"]?[^\s'"]+/g, '-p***')
26
+ .replace(/--password=['"]?[^\s'"]+/g, '--password=***')
27
+ .replace(/-P\s+['"]?[^\s'"]+/g, '-P ***');
28
+ };
29
+
30
+ /**
31
+ * @class UnderpostKubectl
32
+ * @description Kubernetes cluster resource management primitives.
33
+ * Provides a unified interface for kubectl operations: resource listing, in-pod
34
+ * command execution, file transfer, and pod discovery/filtering.
35
+ * All methods are stateless and safe to call from any other CLI module.
36
+ * @memberof UnderpostKubectl
37
+ */
38
+ class UnderpostKubectl {
39
+ static API = {
40
+ /**
41
+ * Lists Kubernetes resources matching `deployId`, parsed into plain objects.
42
+ * Equivalent to `kubectl get <kindType> -o wide`, filtered by name substring.
43
+ * @param {string} deployId - Substring to match against resource names. Empty string returns all.
44
+ * @param {string} [kindType='pods'] - Resource kind: pods, deployments, svc, nodes, …
45
+ * @param {string} [namespace=''] - Namespace to query; empty string → --all-namespaces.
46
+ * @returns {Array<object>} Parsed rows keyed by column header (NAME, STATUS, NODE, …).
47
+ * @memberof UnderpostKubectl
48
+ */
49
+ get(deployId, kindType = 'pods', namespace = '') {
50
+ const raw = shellExec(
51
+ `sudo kubectl get ${kindType}${namespace ? ` -n ${namespace}` : ` --all-namespaces`} -o wide`,
52
+ { stdout: true, disableLog: true, silent: true },
53
+ );
54
+
55
+ const heads = raw
56
+ .split(`\n`)[0]
57
+ .split(' ')
58
+ .filter((_r) => _r.trim());
59
+
60
+ const pods = raw
61
+ .split(`\n`)
62
+ .filter((r) => (deployId ? r.match(deployId) : r.trim() && !r.match('NAME')))
63
+ .map((r) => r.split(' ').filter((_r) => _r.trim()));
64
+
65
+ const result = [];
66
+ for (const row of pods) {
67
+ const pod = {};
68
+ let index = -1;
69
+ for (const head of heads) {
70
+ index++;
71
+ pod[head] = row[index];
72
+ }
73
+ result.push(pod);
74
+ }
75
+ return result;
76
+ },
77
+
78
+ /**
79
+ * Executes a kubectl command with credential-safe logging and error propagation.
80
+ * @param {string} command - Full kubectl command string.
81
+ * @param {object} [options={}] - Execution options.
82
+ * @param {string} [options.context=''] - Human-readable label for log messages.
83
+ * @returns {string} stdout output from the command.
84
+ * @throws {Error} Re-throws any execution error after logging.
85
+ * @memberof UnderpostKubectl
86
+ */
87
+ run(command, options = {}) {
88
+ const { context = '' } = options;
89
+ try {
90
+ logger.info(`Executing kubectl command`, { command: sanitizeCommand(command), context });
91
+ return shellExec(command, { stdout: true, disableLog: true });
92
+ } catch (error) {
93
+ logger.error(`kubectl command failed`, { command: sanitizeCommand(command), error: error.message, context });
94
+ throw error;
95
+ }
96
+ },
97
+
98
+ /**
99
+ * Runs a shell command inside a pod container via `kubectl exec`.
100
+ * @param {object} params
101
+ * @param {string} params.podName - Target pod name.
102
+ * @param {string} params.namespace - Pod namespace.
103
+ * @param {string} params.command - Shell command to run inside the container.
104
+ * @returns {string} stdout output from the in-pod command.
105
+ * @throws {Error} Re-throws any execution error after logging.
106
+ * @memberof UnderpostKubectl
107
+ */
108
+ exec({ podName, namespace, command }) {
109
+ try {
110
+ const kubectlCmd = `sudo kubectl exec -n ${namespace} -i ${podName} -- sh -c "${command}"`;
111
+ return Underpost.kubectl.run(kubectlCmd, { context: `exec in pod ${podName}` });
112
+ } catch (error) {
113
+ logger.error('Failed to execute command in pod', {
114
+ podName,
115
+ command: sanitizeCommand(command),
116
+ error: error.message,
117
+ });
118
+ throw error;
119
+ }
120
+ },
121
+
122
+ /**
123
+ * Copies a local file into a pod via `kubectl cp`.
124
+ * @param {object} params
125
+ * @param {string} params.sourcePath - Local source path.
126
+ * @param {string} params.podName - Target pod name.
127
+ * @param {string} params.namespace - Pod namespace.
128
+ * @param {string} params.destPath - Destination path inside the container.
129
+ * @returns {boolean} `true` on success, `false` on error.
130
+ * @memberof UnderpostKubectl
131
+ */
132
+ cpTo({ sourcePath, podName, namespace, destPath }) {
133
+ try {
134
+ const command = `sudo kubectl cp ${sourcePath} ${namespace}/${podName}:${destPath}`;
135
+ Underpost.kubectl.run(command, { context: `copy to pod ${podName}` });
136
+ return true;
137
+ } catch (error) {
138
+ logger.error('Failed to copy file to pod', { sourcePath, podName, destPath, error: error.message });
139
+ return false;
140
+ }
141
+ },
142
+
143
+ /**
144
+ * Copies a file from a pod to the local filesystem via `kubectl cp`.
145
+ * @param {object} params
146
+ * @param {string} params.podName - Source pod name.
147
+ * @param {string} params.namespace - Pod namespace.
148
+ * @param {string} params.sourcePath - Source path inside the container.
149
+ * @param {string} params.destPath - Local destination path.
150
+ * @returns {boolean} `true` on success, `false` on error.
151
+ * @memberof UnderpostKubectl
152
+ */
153
+ cpFrom({ podName, namespace, sourcePath, destPath }) {
154
+ try {
155
+ const command = `sudo kubectl cp ${namespace}/${podName}:${sourcePath} ${destPath}`;
156
+ Underpost.kubectl.run(command, { context: `copy from pod ${podName}` });
157
+ return true;
158
+ } catch (error) {
159
+ logger.error('Failed to copy file from pod', { podName, sourcePath, destPath, error: error.message });
160
+ return false;
161
+ }
162
+ },
163
+
164
+ /**
165
+ * Checks whether a file exists inside a pod container.
166
+ * @param {object} params
167
+ * @param {string} params.podName - Pod name.
168
+ * @param {string} params.path - Absolute path inside the container to test.
169
+ * @returns {boolean} `true` if the file exists.
170
+ * @memberof UnderpostKubectl
171
+ */
172
+ existsFile({ podName, path }) {
173
+ const result = shellExec(`kubectl exec ${podName} -- test -f ${path} && echo "true" || echo "false"`, {
174
+ stdout: true,
175
+ disableLog: true,
176
+ silent: true,
177
+ }).trim();
178
+ return result === 'true';
179
+ },
180
+
181
+ /**
182
+ * Returns a filtered list of pods from the cluster.
183
+ * Supports wildcard glob patterns on pod names and optional deployId substring filtering.
184
+ * @param {object} [criteria={}] - Filter criteria.
185
+ * @param {string} [criteria.deployId] - Substring to match against pod names (forwards to `get`).
186
+ * @param {string} [criteria.podNames] - Comma-separated glob patterns (supports `*`).
187
+ * @param {string} [criteria.namespace='default'] - Kubernetes namespace to query.
188
+ * @returns {Array<object>} Filtered pod rows from `get`.
189
+ * @memberof UnderpostKubectl
190
+ */
191
+ getFilteredPods(criteria = {}) {
192
+ const { podNames, namespace = 'default', deployId } = criteria;
193
+ try {
194
+ let pods = Underpost.kubectl.get(deployId || '', 'pods', namespace);
195
+ if (podNames) {
196
+ const patterns = podNames.split(',').map((p) => p.trim());
197
+ pods = pods.filter((pod) =>
198
+ patterns.some((pattern) => new RegExp('^' + pattern.replace(/\*/g, '.*') + '$').test(pod.NAME)),
199
+ );
200
+ }
201
+ logger.info(`Found ${pods.length} pod(s) matching criteria`, { criteria, podNames: pods.map((p) => p.NAME) });
202
+ return pods;
203
+ } catch (error) {
204
+ logger.error('Error filtering pods', { error: error.message, criteria });
205
+ return [];
206
+ }
207
+ },
208
+ };
209
+ }
210
+
211
+ export default UnderpostKubectl;
@@ -4,7 +4,7 @@
4
4
  * @namespace UnderpostMonitor
5
5
  */
6
6
 
7
- import { loadReplicas, pathPortAssignmentFactory } from '../server/conf.js';
7
+ import { loadReplicas, pathPortAssignmentFactory, loadConfServerJson, loadCronDeployEnv } from '../server/conf.js';
8
8
  import { loggerFactory } from '../server/logger.js';
9
9
  import axios from 'axios';
10
10
  import fs from 'fs-extra';
@@ -71,6 +71,7 @@ class UnderpostMonitor {
71
71
  commanderOptions,
72
72
  auxRouter,
73
73
  ) {
74
+ loadCronDeployEnv();
74
75
  if (!options.namespace) options.namespace = 'default';
75
76
  if (!options.replicas) options.replicas = '1';
76
77
  if (deployId === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`)) {
@@ -100,7 +101,7 @@ class UnderpostMonitor {
100
101
 
101
102
  const confServer = loadReplicas(
102
103
  deployId,
103
- JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
104
+ loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`),
104
105
  );
105
106
 
106
107
  const pathPortAssignmentData = await pathPortAssignmentFactory(deployId, router, confServer);
@@ -127,7 +128,7 @@ class UnderpostMonitor {
127
128
 
128
129
  const switchTraffic = (targetTraffic) => {
129
130
  const nextTraffic = targetTraffic ?? (traffic === 'blue' ? 'green' : 'blue');
130
- // Delegate traffic switching to centralized deploy implementation so behavior is consistent
131
+ // Delegate traffic switching to deploy implementation so behavior is consistent
131
132
  Underpost.deploy.switchTraffic(deployId, env, nextTraffic, options.replicas, options.namespace, options);
132
133
  // Keep local traffic in sync with the environment
133
134
  traffic = nextTraffic;
@@ -168,9 +169,7 @@ class UnderpostMonitor {
168
169
  switch (options.type) {
169
170
  case 'blue-green':
170
171
  default: {
171
- const confServer = JSON.parse(
172
- fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
173
- );
172
+ const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
174
173
 
175
174
  const namespace = options.namespace;
176
175
  Underpost.deploy.configMap(env, namespace);