underpost 3.1.3 → 3.2.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 (87) hide show
  1. package/.env.example +0 -2
  2. package/.github/workflows/ghpkg.ci.yml +4 -4
  3. package/.github/workflows/npmpkg.ci.yml +28 -11
  4. package/.github/workflows/pwa-microservices-template-page.cd.yml +3 -4
  5. package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
  6. package/.github/workflows/release.cd.yml +4 -4
  7. package/CHANGELOG.md +324 -1
  8. package/CLI-HELP.md +49 -3
  9. package/README.md +3 -2
  10. package/bin/build.js +18 -12
  11. package/bin/deploy.js +177 -124
  12. package/bin/file.js +3 -0
  13. package/conf.js +3 -2
  14. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  15. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  16. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  17. package/manifests/deployment/dd-test-development/deployment.yaml +72 -50
  18. package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
  19. package/manifests/deployment/playwright/deployment.yaml +1 -1
  20. package/nodemon.json +1 -1
  21. package/package.json +22 -15
  22. package/scripts/rhel-grpc-setup.sh +56 -0
  23. package/src/api/file/file.ref.json +18 -0
  24. package/src/api/user/user.service.js +8 -7
  25. package/src/cli/cluster.js +7 -7
  26. package/src/cli/db.js +76 -242
  27. package/src/cli/deploy.js +104 -65
  28. package/src/cli/env.js +1 -0
  29. package/src/cli/fs.js +2 -1
  30. package/src/cli/index.js +42 -1
  31. package/src/cli/kubectl.js +211 -0
  32. package/src/cli/release.js +284 -0
  33. package/src/cli/repository.js +291 -75
  34. package/src/cli/run.js +188 -33
  35. package/src/cli/test.js +3 -3
  36. package/src/client/Default.index.js +3 -4
  37. package/src/client/components/core/AppStore.js +69 -0
  38. package/src/client/components/core/CalendarCore.js +2 -2
  39. package/src/client/components/core/DropDown.js +129 -17
  40. package/src/client/components/core/Keyboard.js +2 -2
  41. package/src/client/components/core/LogIn.js +2 -2
  42. package/src/client/components/core/LogOut.js +2 -2
  43. package/src/client/components/core/Modal.js +0 -1
  44. package/src/client/components/core/Panel.js +0 -1
  45. package/src/client/components/core/PanelForm.js +19 -19
  46. package/src/client/components/core/SocketIo.js +82 -29
  47. package/src/client/components/core/SocketIoHandler.js +75 -0
  48. package/src/client/components/core/Stream.js +143 -95
  49. package/src/client/components/core/Webhook.js +40 -7
  50. package/src/client/components/default/AppStoreDefault.js +5 -0
  51. package/src/client/components/default/LogInDefault.js +3 -3
  52. package/src/client/components/default/LogOutDefault.js +2 -2
  53. package/src/client/components/default/MenuDefault.js +5 -5
  54. package/src/client/components/default/SocketIoDefault.js +3 -51
  55. package/src/client/services/core/core.service.js +20 -8
  56. package/src/client/services/user/user.management.js +2 -2
  57. package/src/index.js +24 -1
  58. package/src/runtime/express/Express.js +18 -1
  59. package/src/runtime/lampp/Dockerfile +9 -2
  60. package/src/runtime/lampp/Lampp.js +4 -3
  61. package/src/runtime/wp/Dockerfile +64 -0
  62. package/src/runtime/wp/Wp.js +497 -0
  63. package/src/server/auth.js +24 -1
  64. package/src/server/backup.js +19 -1
  65. package/src/server/client-build-docs.js +9 -2
  66. package/src/server/client-build.js +31 -31
  67. package/src/server/client-formatted.js +109 -57
  68. package/src/server/ipfs-client.js +24 -1
  69. package/src/server/peer.js +8 -0
  70. package/src/server/runtime.js +25 -1
  71. package/src/server/start.js +6 -0
  72. package/src/ws/IoInterface.js +1 -10
  73. package/src/ws/IoServer.js +14 -33
  74. package/src/ws/core/channels/core.ws.chat.js +65 -20
  75. package/src/ws/core/channels/core.ws.mailer.js +113 -32
  76. package/src/ws/core/channels/core.ws.stream.js +90 -31
  77. package/src/ws/core/core.ws.connection.js +12 -33
  78. package/src/ws/core/core.ws.emit.js +10 -26
  79. package/src/ws/core/core.ws.server.js +25 -58
  80. package/src/ws/default/channels/default.ws.main.js +53 -12
  81. package/src/ws/default/default.ws.connection.js +26 -13
  82. package/src/ws/default/default.ws.server.js +30 -12
  83. package/src/client/components/default/ElementsDefault.js +0 -38
  84. package/src/ws/core/management/core.ws.chat.js +0 -8
  85. package/src/ws/core/management/core.ws.mailer.js +0 -16
  86. package/src/ws/core/management/core.ws.stream.js +0 -8
  87. package/src/ws/default/management/default.ws.main.js +0 -8
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  <div align="center">
18
18
 
19
- [![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.ci.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/3.1.3)](https://socket.dev/npm/package/underpost/overview/3.1.3) [![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)
19
+ [![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.ci.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/3.2.0)](https://socket.dev/npm/package/underpost/overview/3.2.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)
20
20
 
21
21
  </div>
22
22
 
@@ -61,7 +61,7 @@ npm run dev
61
61
  <a target="_top" href="https://www.nexodev.org/docs?cid=src">See Docs here.</a>
62
62
 
63
63
  <!-- cli-index-start -->
64
- ## underpost ci/cd cli v3.1.3
64
+ ## underpost ci/cd cli v3.2.0
65
65
 
66
66
  ### Usage: `underpost [options] [command]`
67
67
  ```
@@ -97,6 +97,7 @@ Commands:
97
97
  run [options] <runner-id> [path] Runs specified scripts using various runners.
98
98
  lxd [options] Manages LXD virtual machines as K3s nodes (control plane or workers).
99
99
  baremetal [options] [workflow-id] Manages baremetal server operations, including installation, database setup, commissioning, and user management.
100
+ release [options] [version] Release orchestrator for building new versions and deploying releases of the Underpost CLI.
100
101
  help [command] display help for command
101
102
 
102
103
  ```
package/bin/build.js CHANGED
@@ -169,21 +169,22 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
169
169
  packageJson.description = 'Cyberia Engine - Object Layer and Assets Management Microservice';
170
170
  const { CyberiaDependencies } = await import(`../src/client/components/cyberia-portal/CommonCyberiaPortal.js`);
171
171
  packageJson.dependencies = {
172
- ...packageJson.dependencies,
172
+ ...originPackageJson.dependencies,
173
173
  ...CyberiaDependencies,
174
174
  };
175
- packageJson.overrides = originPackageJson.overrides;
176
175
  fs.writeFileSync(`${basePath}/bin/index.js`, fs.readFileSync(`./bin/cyberia.js`, 'utf8'), 'utf8');
177
176
  fs.copyFileSync(`./src/api/object-layer/README.md`, `${basePath}/README.md`);
178
177
  fs.copySync(`./hardhat`, `${basePath}/hardhat`);
179
178
  fs.copySync(`./hardhat/WHITE-PAPER.md`, `${basePath}/WHITE-PAPER.md`);
180
- fs.copyFileSync(`./jsdoc.${confName}.json`, `${basePath}/jsdoc.json`);
181
179
  for (const path of [
180
+ '/src/grpc/cyberia',
182
181
  '/src/client/ssr/pages/CyberiaServerMetrics.js',
183
182
  '/src/server/object-layer.js',
184
183
  '/src/server/atlas-sprite-sheet-generator.js',
185
184
  '/src/server/shape-generator.js',
186
185
  '/src/server/semantic-layer-generator.js',
186
+ '/src/server/semantic-layer-generator-floor.js',
187
+ '/src/server/semantic-layer-generator-skin.js',
187
188
  '/test/shape-generator.test.js',
188
189
  '/src/server/besu-genesis-generator.js',
189
190
  '/.github/workflows/hardhat.ci.yml',
@@ -203,25 +204,30 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
203
204
  fs.copySync(`./src/cli`, `${basePath}/src/cli`);
204
205
  if (!fs.existsSync(`${basePath}/images`)) fs.mkdirSync(`${basePath}/images`);
205
206
 
206
- const env = process.argv.includes('development') ? 'development' : 'production';
207
- const deploymentsFiles = ['proxy.yaml', 'deployment.yaml', 'secret.yaml'];
208
- // remove engine-private of .dockerignore for local testing
209
- for (const file of deploymentsFiles) {
210
- if (fs.existsSync(`./manifests/deployment/${confName}-${env}/${file}`)) {
211
- fs.copyFileSync(`./manifests/deployment/${confName}-${env}/${file}`, `${basePath}/${file}`);
212
- }
213
- }
214
-
215
207
  fs.copyFileSync(`./.github/workflows/${repoName}.ci.yml`, `${basePath}/.github/workflows/${repoName}.ci.yml`);
216
208
  fs.copyFileSync(`./.github/workflows/${repoName}.cd.yml`, `${basePath}/.github/workflows/${repoName}.cd.yml`);
217
209
 
210
+ if (fs.existsSync(`./jsdoc.${confName}.json`)) {
211
+ fs.copyFileSync(`./jsdoc.${confName}.json`, `${basePath}/jsdoc.json`);
212
+ fs.copyFileSync(`./jsdoc.${confName}.json`, `${basePath}/jsdoc.${confName}.json`);
213
+ }
214
+
215
+ if (fs.existsSync(`./manifests/deployment/${confName}-development`))
216
+ fs.copySync(
217
+ `./manifests/deployment/${confName}-development`,
218
+ `${basePath}/manifests/deployment/${confName}-development`,
219
+ );
220
+
218
221
  // Copy conf.<deploy-id>.js to conf.js for the respective deployment
219
222
  fs.copyFileSync(`./conf.${confName}.js`, `${basePath}/conf.js`);
220
223
  fs.copyFileSync(`./manifests/deployment/${confName}-development/proxy.yaml`, `${basePath}/proxy.yaml`);
221
224
  fs.copyFileSync(`./manifests/deployment/${confName}-development/deployment.yaml`, `${basePath}/deployment.yaml`);
225
+ const pvPvcPath = `./manifests/deployment/${confName}-development/pv-pvc.yaml`;
226
+ if (fs.existsSync(pvPvcPath)) fs.copyFileSync(pvPvcPath, `${basePath}/pv-pvc.yaml`);
222
227
 
223
228
  if (fs.existsSync(`./src/ws/${confName.split('-')[1]}`)) {
224
229
  fs.copySync(`./src/ws/${confName.split('-')[1]}`, `${basePath}/src/ws/${confName.split('-')[1]}`);
225
230
  }
231
+ fs.copyFileSync(`.gitignore`, `${basePath}/.gitignore`);
226
232
  shellExec(`cd ${basePath} && npm install --ignore-scripts`);
227
233
  }
package/bin/deploy.js CHANGED
@@ -3,7 +3,7 @@ import axios from 'axios';
3
3
 
4
4
  import dotenv from 'dotenv';
5
5
 
6
- import { pbcopy, shellCd, shellExec } from '../src/server/process.js';
6
+ import { pbcopy, shellExec } from '../src/server/process.js';
7
7
  import { loggerFactory } from '../src/server/logger.js';
8
8
  import {
9
9
  addApiConf,
@@ -218,115 +218,6 @@ try {
218
218
  break;
219
219
  }
220
220
 
221
- case 'version-build': {
222
- dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
223
- shellCd(`/home/dd/engine`);
224
- Underpost.repo.clean({ paths: ['/home/dd/engine', '/home/dd/engine/engine-private '] });
225
- shellExec(`node bin pull . ${process.env.GITHUB_USERNAME}/engine`);
226
- shellExec(`node bin run kill 4001`);
227
- shellExec(`node bin run kill 4002`);
228
- shellExec(`node bin run kill 4003`);
229
- shellExec(`npm run update:template`);
230
- shellExec(`cd ../pwa-microservices-template && npm install && npm run build`);
231
- console.log(fs.existsSync(`../pwa-microservices-template/engine-private/conf/dd-default`));
232
- shellExec(`cd ../pwa-microservices-template && ENABLE_FILE_LOGS=true timeout 5s npm run dev`, {
233
- async: true,
234
- });
235
- await timer(5500);
236
- const templateRunnerResult = fs.readFileSync(`../pwa-microservices-template/logs/start.js/all.log`, 'utf8');
237
- logger.info('Test template runner result');
238
- console.log(templateRunnerResult);
239
- if (!templateRunnerResult || templateRunnerResult.toLowerCase().match('error')) {
240
- logger.error('Test template runner result failed');
241
- break;
242
- }
243
- shellCd(`/home/dd/engine`);
244
- Underpost.repo.clean({ paths: ['/home/dd/engine', '/home/dd/engine/engine-private '] });
245
- const originPackageJson = JSON.parse(fs.readFileSync(`package.json`, 'utf8'));
246
- const newVersion = process.argv[3] ?? originPackageJson.version;
247
- const { version } = originPackageJson;
248
- originPackageJson.version = newVersion;
249
- fs.writeFileSync(`package.json`, JSON.stringify(originPackageJson, null, 4), 'utf8');
250
-
251
- const originPackageLockJson = JSON.parse(fs.readFileSync(`package-lock.json`, 'utf8'));
252
- originPackageLockJson.version = newVersion;
253
- originPackageLockJson.packages[''].version = newVersion;
254
- fs.writeFileSync(`package-lock.json`, JSON.stringify(originPackageLockJson, null, 4), 'utf8');
255
-
256
- if (fs.existsSync(`./engine-private/conf`)) {
257
- const files = await fs.readdir(`./engine-private/conf`, { recursive: true });
258
- for (const relativePath of files) {
259
- const filePah = `./engine-private/conf/${relativePath.replaceAll(`\\`, '/')}`;
260
- if (filePah.split('/').pop() === 'package.json') {
261
- const originPackage = JSON.parse(fs.readFileSync(filePah, 'utf8'));
262
- originPackage.version = newVersion;
263
- fs.writeFileSync(filePah, JSON.stringify(originPackage, null, 4), 'utf8');
264
- }
265
- if (filePah.split('/').pop() === 'deployment.yaml') {
266
- fs.writeFileSync(
267
- filePah,
268
- fs
269
- .readFileSync(filePah, 'utf8')
270
- .replaceAll(`v${version}`, `v${newVersion}`)
271
- .replaceAll(`engine.version: ${version}`, `engine.version: ${newVersion}`),
272
- 'utf8',
273
- );
274
- }
275
- }
276
- }
277
-
278
- fs.writeFileSync(
279
- `./manifests/deployment/dd-default-development/deployment.yaml`,
280
- fs
281
- .readFileSync(`./manifests/deployment/dd-default-development/deployment.yaml`, 'utf8')
282
- .replaceAll(`underpost:v${version}`, `underpost:v${newVersion}`),
283
- 'utf8',
284
- );
285
-
286
- if (fs.existsSync(`./.github/workflows/docker-image.ci.yml`))
287
- fs.writeFileSync(
288
- `./.github/workflows/docker-image.ci.yml`,
289
- fs
290
- .readFileSync(`./.github/workflows/docker-image.ci.yml`, 'utf8')
291
- .replaceAll(`underpost-engine:v${version}`, `underpost-engine:v${newVersion}`),
292
- 'utf8',
293
- );
294
-
295
- fs.writeFileSync(
296
- `./src/index.js`,
297
- fs.readFileSync(`./src/index.js`, 'utf8').replaceAll(`${version}`, `${newVersion}`),
298
- 'utf8',
299
- );
300
- shellExec(`node bin/deploy cli-docs ${version} ${newVersion}`);
301
- shellExec(`node bin/deploy update-dependencies`);
302
- shellExec(`node bin/build dd`);
303
- shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd production`);
304
- shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd development`);
305
- shellExec(`node bin/deploy build-default-confs`);
306
- shellExec(`sudo rm -rf ./engine-private/conf/dd-default`);
307
- shellExec(`node bin new --deploy-id dd-default`);
308
- console.log(fs.existsSync(`./engine-private/conf/dd-default`));
309
- shellExec(`sudo rm -rf ./engine-private/conf/dd-default`);
310
- shellExec(`node bin cron --dev --setup-start`);
311
- shellExec(`node bin cmt --changelog-build`);
312
- process.exit(0);
313
- break;
314
- }
315
-
316
- case 'version-deploy': {
317
- dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
318
- shellExec(
319
- `underpost secret underpost --create-from-file /home/dd/engine/engine-private/conf/dd-cron/.env.production`,
320
- );
321
- shellExec(`node bin/build dd conf`);
322
- shellExec(`git add . && cd ./engine-private && git add .`);
323
- shellExec(`node bin cmt . ci package-pwa-microservices-template 'New release v:${process.argv[3]}'`);
324
- shellExec(`node bin cmt ./engine-private ci package-pwa-microservices-template`);
325
- shellExec(`node bin push . ${process.env.GITHUB_USERNAME}/engine`);
326
- shellExec(`cd ./engine-private && node ../bin push . ${process.env.GITHUB_USERNAME}/engine-private`);
327
- break;
328
- }
329
-
330
221
  case 'build-default-confs': {
331
222
  for (const deployId of fs
332
223
  .readFileSync(`./engine-private/deploy/dd.router`, 'utf8')
@@ -475,7 +366,10 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
475
366
  `${path}/.env`,
476
367
  fs
477
368
  .readFileSync(`${path}/.env`, 'utf8')
478
- .replace(`FIRST_SUPERUSER=admin@example.com`, `FIRST_SUPERUSER=development@underpost.net`)
369
+ .replace(
370
+ `FIRST_SUPERUSER=admin@example.com`,
371
+ `FIRST_SUPERUSER=${process.env.GITHUB_EMAIL || 'development@underpost.net'}`,
372
+ )
479
373
  .replace(`FIRST_SUPERUSER_PASSWORD=changethis`, `FIRST_SUPERUSER_PASSWORD=${password}`)
480
374
  .replace(`SECRET_KEY=changethis`, `SECRET_KEY=${password}`)
481
375
  .replace(`POSTGRES_DB=app`, `POSTGRES_DB=postgresdb`)
@@ -561,7 +455,7 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
561
455
  shellExec(
562
456
  `sudo kubectl create secret generic ${secretSelector}` +
563
457
  ` --from-file=SECRET_KEY=/home/dd/engine/engine-private/postgresql-password` +
564
- ` --from-literal=FIRST_SUPERUSER=development@underpost.net` +
458
+ ` --from-literal=FIRST_SUPERUSER=${process.env.GITHUB_EMAIL || 'development@underpost.net'}` +
565
459
  ` --from-file=FIRST_SUPERUSER_PASSWORD=/home/dd/engine/engine-private/postgresql-password` +
566
460
  ` --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
567
461
  );
@@ -798,6 +692,7 @@ nvidia/gpu-operator \
798
692
  for (const file of fs.readdirSync(`./engine-private/conf/${deployId}/`)) {
799
693
  const deployPackage = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/package.json`, 'utf8'));
800
694
  deployPackage.overrides = originPackageJson.overrides;
695
+ deployPackage.dependencies = originPackageJson.dependencies;
801
696
  fs.writeFileSync(
802
697
  `./engine-private/conf/${deployId}/package.json`,
803
698
  JSON.stringify(deployPackage, null, 4),
@@ -810,7 +705,7 @@ nvidia/gpu-operator \
810
705
  for (const path of Object.keys(confObj[host])) {
811
706
  }
812
707
  }
813
- fs.writeFileSync(filePath, JSON.stringify(confObj, null, 4), 'utf8');
708
+ // fs.writeFileSync(filePath, JSON.stringify(confObj, null, 4), 'utf8');
814
709
  logger.info(`sync-conf`, { deployId, file });
815
710
  }
816
711
  }
@@ -839,7 +734,7 @@ nvidia/gpu-operator \
839
734
  if (fs.existsSync(toPath)) fs.removeSync(toPath);
840
735
  shellExec(`node bin/deploy pw-conf ${scriptPath}`);
841
736
  shellExec(`kubectl delete deployment playwright-server --ignore-not-found`);
842
- while (Underpost.deploy.get('playwright-server').length > 0) {
737
+ while (Underpost.kubectl.get('playwright-server').length > 0) {
843
738
  logger.info(`Waiting for playwright-server deployment to be deleted...`);
844
739
  await timer(1000);
845
740
  }
@@ -847,13 +742,13 @@ nvidia/gpu-operator \
847
742
  const id = 'playwright-server';
848
743
  await Underpost.test.statusMonitor(id);
849
744
  const nameSpace = 'default';
850
- const [pod] = Underpost.deploy.get(id);
745
+ const [pod] = Underpost.kubectl.get(id);
851
746
  const podName = pod.NAME;
852
747
  shellExec(`kubectl logs -f ${podName} -n ${nameSpace}`, {
853
748
  async: true,
854
749
  });
855
750
  (async () => {
856
- while (!Underpost.deploy.existsContainerFile({ podName, path: fromPath })) {
751
+ while (!Underpost.kubectl.existsFile({ podName, path: fromPath })) {
857
752
  await timer(1000);
858
753
  logger.info(`Waiting for file ${fromPath} in pod ${podName}...`);
859
754
  }
@@ -874,7 +769,8 @@ nvidia/gpu-operator \
874
769
  }
875
770
 
876
771
  case 'dependabot': {
877
- shellExec(`git fetch origin`);
772
+ dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
773
+ shellExec(`git fetch origin --prune`);
878
774
 
879
775
  const { stdout: branchOutput } = shellExec(`git branch -r`, { silent: true });
880
776
  const dependabotBranches = branchOutput
@@ -890,20 +786,177 @@ nvidia/gpu-operator \
890
786
 
891
787
  logger.info('Found dependabot branches:', dependabotBranches);
892
788
 
893
- for (const branch of dependabotBranches) {
894
- logger.info(`Checking out branch: ${branch}`);
895
- shellExec(`git checkout -B ${branch} origin/${branch}`);
789
+ // Stash local changes to prevent checkout/merge conflicts
790
+ const stashResult = shellExec(`git stash --include-untracked`, { silent: true });
791
+ const hasStash = !stashResult.stdout.includes('No local changes to save');
792
+
793
+ // Checkout master
794
+ const checkoutResult = shellExec(`git checkout master`);
795
+ if (checkoutResult.code !== 0) {
796
+ logger.error('Failed to checkout master');
797
+ if (hasStash) shellExec(`git stash pop`);
798
+ break;
896
799
  }
897
800
 
898
- logger.info('Checking out master');
899
- shellExec(`git checkout master`);
801
+ // Pull latest master
802
+ shellExec(`git pull origin master`);
803
+
804
+ // Get repo URI from remote
805
+ const remoteUrl = shellExec(`git config --get remote.origin.url`, { stdout: true, silent: true }).trim();
806
+ const gitUri = remoteUrl.replace(/.*github\.com[:/]/, '').replace(/\.git$/, '');
807
+
808
+ const mergedBranches = [];
809
+ const failedBranches = [];
900
810
 
901
811
  for (const branch of dependabotBranches) {
902
812
  logger.info(`Merging branch: ${branch}`);
903
- shellExec(`git merge ${branch}`);
813
+ const mergeResult = shellExec(`git merge origin/${branch}`);
814
+ if (mergeResult.code === 0) {
815
+ const isAlreadyMerged = mergeResult.stdout && mergeResult.stdout.includes('Already up to date');
816
+ mergedBranches.push({ branch, isAlreadyMerged });
817
+ } else {
818
+ logger.error(`Failed to merge branch: ${branch}`);
819
+ shellExec(`git merge --abort`, { silent: true });
820
+ failedBranches.push(branch);
821
+ }
904
822
  }
905
823
 
906
- logger.info('All dependabot branches merged into master');
824
+ // Delete merged local and remote branches
825
+ for (const { branch, isAlreadyMerged } of mergedBranches) {
826
+ shellExec(`git branch -D ${branch}`, { silent: true });
827
+ // logger.info(`Deleting remote branch: ${branch}${isAlreadyMerged ? ' (already merged)' : ''}`);
828
+ // shellExec(`git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}.git --delete ${branch}`, {
829
+ // disableLog: true,
830
+ // });
831
+ }
832
+
833
+ // Restore stashed changes
834
+ if (hasStash) shellExec(`git stash pop`);
835
+
836
+ logger.info(
837
+ 'Merged branches:',
838
+ mergedBranches.map((m) => m.branch),
839
+ );
840
+ if (failedBranches.length > 0) logger.warn('Failed branches:', failedBranches);
841
+ logger.info('Dependabot merge completed');
842
+ break;
843
+ }
844
+
845
+ case 'add-api': {
846
+ // node bin/deploy add-api <apiId> <deployId> [clientId] [host]
847
+ // Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal
848
+ // Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal underpost.net
849
+ //
850
+ // Adds an API to server conf files (main + dev variants) and client conf.
851
+ // - conf.server.json: adds apiId to every host/path that has an `apis` array
852
+ // (or only to the specified host if [host] is provided)
853
+ // - conf.server.dev.*.json: same treatment for all dev variants
854
+ // - conf.client.json: adds apiId to the specified clientId's `services` array
855
+ // Idempotent: skips if the API is already present.
856
+
857
+ const apiId = process.argv[3];
858
+ const deployId = process.argv[4];
859
+ const clientId = process.argv[5];
860
+ const targetHost = process.argv[6];
861
+
862
+ if (!apiId || !deployId) {
863
+ logger.error('Usage: node bin/deploy add-api <apiId> <deployId> [clientId] [host]');
864
+ logger.error('Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal');
865
+ logger.error('Example: node bin/deploy add-api cyberia-dialogue dd-cyberia cyberia-portal underpost.net');
866
+ process.exit(1);
867
+ }
868
+
869
+ const confFolder = `./engine-private/conf/${deployId}`;
870
+ if (!fs.existsSync(confFolder)) {
871
+ logger.error(`Config folder not found: ${confFolder}`);
872
+ process.exit(1);
873
+ }
874
+
875
+ // Helper: add apiId to apis[] arrays in a server conf file (idempotent)
876
+ // When targetHost is set, only entries under that host are modified.
877
+ const addApiToServerConf = (filePath) => {
878
+ if (!fs.existsSync(filePath)) return 0;
879
+ const conf = JSON.parse(fs.readFileSync(filePath, 'utf8'));
880
+ let count = 0;
881
+ const hosts = targetHost ? (conf[targetHost] ? [targetHost] : []) : Object.keys(conf);
882
+ for (const host of hosts) {
883
+ for (const path of Object.keys(conf[host])) {
884
+ const entry = conf[host][path];
885
+ if (Array.isArray(entry.apis) && entry.apis.length > 0 && !entry.apis.includes(apiId)) {
886
+ entry.apis.push(apiId);
887
+ count++;
888
+ }
889
+ }
890
+ }
891
+ if (count > 0) {
892
+ fs.writeFileSync(filePath, JSON.stringify(conf, null, 4), 'utf8');
893
+ }
894
+ return count;
895
+ };
896
+
897
+ // 1. Main conf.server.json
898
+ const mainPath = `${confFolder}/conf.server.json`;
899
+ const mainCount = addApiToServerConf(mainPath);
900
+ logger.info(`conf.server.json: added "${apiId}" to ${mainCount} path(s)`);
901
+
902
+ // 2. All dev variants: conf.server.dev.*.json
903
+ const devFiles = fs
904
+ .readdirSync(confFolder)
905
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
906
+ for (const devFile of devFiles) {
907
+ const devPath = `${confFolder}/${devFile}`;
908
+ const devCount = addApiToServerConf(devPath);
909
+ logger.info(`${devFile}: added "${apiId}" to ${devCount} path(s)`);
910
+ }
911
+
912
+ // Helper: add apiId to a client conf file's clientId services (idempotent)
913
+ const addApiToClientConf = (filePath, label) => {
914
+ if (!clientId || !fs.existsSync(filePath)) return;
915
+ const confClient = JSON.parse(fs.readFileSync(filePath, 'utf8'));
916
+ if (confClient[clientId] && Array.isArray(confClient[clientId].services)) {
917
+ if (!confClient[clientId].services.includes(apiId)) {
918
+ confClient[clientId].services.push(apiId);
919
+ fs.writeFileSync(filePath, JSON.stringify(confClient, null, 4), 'utf8');
920
+ logger.info(`${label}: added "${apiId}" to "${clientId}" services`);
921
+ } else {
922
+ logger.info(`${label}: "${apiId}" already in "${clientId}" services`);
923
+ }
924
+ } else {
925
+ logger.warn(`${label}: clientId "${clientId}" not found or has no services array`);
926
+ }
927
+ };
928
+
929
+ // 3. Client conf.client.json
930
+ addApiToClientConf(`${confFolder}/conf.client.json`, 'conf.client.json');
931
+
932
+ // 4. Replicas: engine-private/replica/<deployId>-*
933
+ const replicaBase = './engine-private/replica';
934
+ if (fs.existsSync(replicaBase)) {
935
+ const replicaDirs = fs
936
+ .readdirSync(replicaBase)
937
+ .filter((d) => d.startsWith(`${deployId}-`) && fs.statSync(`${replicaBase}/${d}`).isDirectory());
938
+ for (const replicaDir of replicaDirs) {
939
+ const replicaFolder = `${replicaBase}/${replicaDir}`;
940
+ // Server conf
941
+ const rMainCount = addApiToServerConf(`${replicaFolder}/conf.server.json`);
942
+ logger.info(`replica/${replicaDir}/conf.server.json: added "${apiId}" to ${rMainCount} path(s)`);
943
+ // Dev variants
944
+ const rDevFiles = fs
945
+ .readdirSync(replicaFolder)
946
+ .filter((f) => f.startsWith('conf.server.dev.') && f.endsWith('.json'));
947
+ for (const rDevFile of rDevFiles) {
948
+ const rDevCount = addApiToServerConf(`${replicaFolder}/${rDevFile}`);
949
+ logger.info(`replica/${replicaDir}/${rDevFile}: added "${apiId}" to ${rDevCount} path(s)`);
950
+ }
951
+ // Client conf
952
+ addApiToClientConf(`${replicaFolder}/conf.client.json`, `replica/${replicaDir}/conf.client.json`);
953
+ }
954
+ }
955
+
956
+ // 5. Rebuild default conf
957
+ shellExec(`node bin new --default-conf --deploy-id ${deployId}`);
958
+ logger.info(`Rebuilt default conf for ${deployId}`);
959
+
907
960
  break;
908
961
  }
909
962
  }
package/bin/file.js CHANGED
@@ -99,7 +99,10 @@ try {
99
99
  './src/server/atlas-sprite-sheet-generator.js',
100
100
  './src/server/shape-generator.js',
101
101
  './src/server/semantic-layer-generator.js',
102
+ './src/server/semantic-layer-generator-floor.js',
103
+ './src/server/semantic-layer-generator-skin.js',
102
104
  './src/server/besu-genesis-generator.js',
105
+ './src/grpc/cyberia',
103
106
  './test/shape-generator.test.js',
104
107
  'bin/cyberia.js',
105
108
  ]) {
package/conf.js CHANGED
@@ -63,12 +63,13 @@ const DefaultConf = /**/ {
63
63
  'Pagination',
64
64
  'windowGetDimensions',
65
65
  'SearchBox',
66
+ 'SocketIoHandler',
67
+ 'AppStore',
66
68
  ],
67
69
  default: [
68
70
  'MenuDefault',
69
71
  'RoutesDefault',
70
- 'ElementsDefault',
71
- 'CommonDefault',
72
+ 'AppStoreDefault',
72
73
  'CssDefault',
73
74
  'LogInDefault',
74
75
  'LogOutDefault',
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-backup
26
- image: underpost/underpost-engine:v3.1.3
26
+ image: underpost/underpost-engine:v3.2.0
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-dns
26
- image: underpost/underpost-engine:v3.1.3
26
+ image: underpost/underpost-engine:v3.2.0
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v3.1.3
20
+ image: localhost/rockylinux9-underpost:v3.2.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:v3.1.3
103
+ image: localhost/rockylinux9-underpost:v3.2.0
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"