cyberia 2.89.2 → 2.89.45

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 (64) hide show
  1. package/.env.development +2 -0
  2. package/.env.production +2 -0
  3. package/.env.test +2 -0
  4. package/.github/workflows/engine-cyberia.cd.yml +4 -0
  5. package/.github/workflows/release.cd.yml +2 -0
  6. package/bin/cyberia.js +10 -7
  7. package/bin/deploy.js +22 -15
  8. package/bin/index.js +10 -7
  9. package/cli.md +105 -54
  10. package/deployment.yaml +34 -6
  11. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  12. package/manifests/deployment/dd-test-development/deployment.yaml +18 -6
  13. package/manifests/deployment/dd-test-development/proxy.yaml +2 -0
  14. package/manifests/deployment/kafka/deployment.yaml +0 -2
  15. package/manifests/deployment/spark/spark-pi-py.yaml +0 -1
  16. package/manifests/deployment/tensorflow/tf-gpu-test.yaml +0 -2
  17. package/manifests/envoy-service-nodeport.yaml +0 -1
  18. package/manifests/kubeadm-calico-config.yaml +10 -115
  19. package/manifests/letsencrypt-prod.yaml +0 -1
  20. package/manifests/mariadb/statefulset.yaml +1 -1
  21. package/manifests/mongodb/statefulset.yaml +11 -11
  22. package/manifests/mongodb-4.4/service-deployment.yaml +1 -3
  23. package/manifests/mysql/pv-pvc.yaml +1 -1
  24. package/manifests/mysql/statefulset.yaml +1 -1
  25. package/manifests/pv-pvc-dd.yaml +34 -0
  26. package/manifests/valkey/service.yaml +0 -1
  27. package/manifests/valkey/statefulset.yaml +2 -3
  28. package/package.json +1 -1
  29. package/proxy.yaml +6 -0
  30. package/scripts/device-scan.sh +43 -21
  31. package/scripts/gen-fqdns.sh +14 -0
  32. package/scripts/ip-info.sh +118 -0
  33. package/scripts/rpmfusion-ffmpeg-setup.sh +1 -0
  34. package/src/api/object-layer/object-layer.controller.js +19 -0
  35. package/src/api/object-layer/object-layer.router.js +4 -0
  36. package/src/api/object-layer/object-layer.service.js +111 -0
  37. package/src/api/user/user.model.js +10 -1
  38. package/src/cli/cluster.js +88 -75
  39. package/src/cli/deploy.js +165 -85
  40. package/src/cli/index.js +44 -3
  41. package/src/cli/monitor.js +12 -6
  42. package/src/cli/repository.js +13 -1
  43. package/src/cli/run.js +127 -60
  44. package/src/client/components/core/Logger.js +1 -1
  45. package/src/client/components/core/Modal.js +5 -0
  46. package/src/client/components/core/ObjectLayerEngineModal.js +336 -72
  47. package/src/client/components/core/ObjectLayerEngineViewer.js +239 -420
  48. package/src/client/components/core/Router.js +10 -1
  49. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +1 -1
  50. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +1 -1
  51. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +1 -1
  52. package/src/client/components/cyberia-portal/ObjectLayerCyberiaPortal.js +44 -4
  53. package/src/client/services/default/default.management.js +25 -5
  54. package/src/client/services/object-layer/object-layer.management.js +8 -8
  55. package/src/client/services/object-layer/object-layer.service.js +34 -0
  56. package/src/index.js +1 -1
  57. package/src/server/client-build.js +5 -4
  58. package/src/server/conf.js +1 -1
  59. package/src/server/start.js +3 -1
  60. package/manifests/kubelet-config.yaml +0 -65
  61. package/manifests/mongodb/backup-access.yaml +0 -16
  62. package/manifests/mongodb/backup-cronjob.yaml +0 -42
  63. package/manifests/mongodb/backup-pv-pvc.yaml +0 -22
  64. package/manifests/mongodb/configmap.yaml +0 -26
package/src/cli/run.js CHANGED
@@ -60,9 +60,16 @@ class UnderpostRun {
60
60
  * @property {string} tty - The TTY option for the container.
61
61
  * @property {string} stdin - The stdin option for the container.
62
62
  * @property {string} restartPolicy - The restart policy for the container.
63
+ * @property {string} runtimeClassName - The runtime class name for the container.
64
+ * @property {string} imagePullPolicy - The image pull policy for the container.
65
+ * @property {string} apiVersion - The API version for the container.
66
+ * @property {string} claimName - The claim name for the volume.
67
+ * @property {string} kind - The kind of resource to create.
63
68
  * @property {boolean} terminal - Whether to open a terminal.
64
69
  * @property {number} devProxyPortOffset - The port offset for the development proxy.
70
+ * @property {boolean} hostNetwork - Whether to use host networking.
65
71
  * @property {string} confServerPath - The configuration server path.
72
+ * @property {string} underpostRoot - The root path of the Underpost installation.
66
73
  * @memberof UnderpostRun
67
74
  */
68
75
  static DEFAULT_OPTION = {
@@ -74,7 +81,7 @@ class UnderpostRun {
74
81
  volumeMountPath: '',
75
82
  imageName: '',
76
83
  containerName: '',
77
- namespace: '',
84
+ namespace: 'default',
78
85
  build: false,
79
86
  replicas: 1,
80
87
  k3s: false,
@@ -85,9 +92,16 @@ class UnderpostRun {
85
92
  tty: '',
86
93
  stdin: '',
87
94
  restartPolicy: '',
95
+ runtimeClassName: '',
96
+ imagePullPolicy: '',
97
+ apiVersion: '',
98
+ claimName: '',
99
+ kind: '',
88
100
  terminal: false,
89
101
  devProxyPortOffset: 0,
102
+ hostNetwork: false,
90
103
  confServerPath: '',
104
+ underpostRoot: '',
91
105
  };
92
106
  /**
93
107
  * @static
@@ -195,10 +209,10 @@ class UnderpostRun {
195
209
  * @memberof UnderpostRun
196
210
  */
197
211
  'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
198
- const { underpostRoot } = options;
199
- shellExec(`kubectl delete configmap tf-gpu-test-script`);
200
- shellExec(`kubectl delete pod tf-gpu-test-pod`);
201
- shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
212
+ const { underpostRoot, namespace } = options;
213
+ shellExec(`kubectl delete configmap tf-gpu-test-script -n ${namespace} --ignore-not-found`);
214
+ shellExec(`kubectl delete pod tf-gpu-test-pod -n ${namespace} --ignore-not-found`);
215
+ shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml -n ${namespace}`);
202
216
  },
203
217
  /**
204
218
  * @method dev-cluster
@@ -326,9 +340,10 @@ class UnderpostRun {
326
340
  * @memberof UnderpostRun
327
341
  */
328
342
  'cluster-build': (path, options = UnderpostRun.DEFAULT_OPTION) => {
343
+ const nodeOptions = options.nodeName ? ` --node-name ${options.nodeName}` : '';
329
344
  shellExec(`node bin run clean`);
330
- shellExec(`node bin run --dev sync-replica template-deploy`);
331
- shellExec(`node bin run sync-replica template-deploy`);
345
+ shellExec(`node bin run --dev sync-replica template-deploy${nodeOptions}`);
346
+ shellExec(`node bin run sync-replica template-deploy${nodeOptions}`);
332
347
  shellExec(`node bin env clean`);
333
348
  for (const deployId of fs.readFileSync('./engine-private/deploy/dd.router', 'utf8').split(','))
334
349
  shellExec(`node bin/deploy update-default-conf ${deployId.trim()}`);
@@ -478,7 +493,7 @@ class UnderpostRun {
478
493
  versions = versions ? versions.replaceAll('+', ',') : defaultPath[2];
479
494
  image = image ? image : defaultPath[3];
480
495
  node = node ? node : defaultPath[4];
481
-
496
+ shellExec(`${baseCommand} cluster --ns-use ${options.namespace}`);
482
497
  if (isDeployRunnerContext(path, options)) {
483
498
  const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
484
499
  if (!validVersion) throw new Error('Version mismatch');
@@ -495,11 +510,13 @@ class UnderpostRun {
495
510
  shellExec(
496
511
  `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
497
512
  replicas ? replicas : 1
498
- } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
513
+ } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''}${options.namespace ? ` --namespace ${options.namespace}` : ''} dd ${env}`,
499
514
  );
500
515
 
501
516
  if (isDeployRunnerContext(path, options)) {
502
- shellExec(`${baseCommand} deploy --kubeadm --disable-update-proxy ${deployId} ${env} --versions ${versions}`);
517
+ shellExec(
518
+ `${baseCommand} deploy --kubeadm --disable-update-proxy ${deployId} ${env} --versions ${versions}${options.namespace ? ` --namespace ${options.namespace}` : ''}`,
519
+ );
503
520
  if (!targetTraffic) targetTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
504
521
  await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic);
505
522
  UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
@@ -578,40 +595,75 @@ class UnderpostRun {
578
595
  },
579
596
 
580
597
  /**
581
- * @method dev-container
582
- * @description Runs a development container pod named `underpost-dev-container` with specified volume mounts and opens a terminal to follow its logs.
583
- * @param {string} path - The input value, identifier, or path for the operation (used as an optional command to run inside the container).
598
+ * @method dd-container
599
+ * @description Deploys a development or debug container tasks jobs, setting up necessary volumes and images, and running specified commands within the container.
600
+ * @param {string} path - The input value, identifier, or path for the operation (used as the command to run inside the container).
584
601
  * @param {Object} options - The default underpost runner options for customizing workflow
585
602
  * @memberof UnderpostRun
586
603
  */
587
- 'dev-container': async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
588
- options.dev = true;
604
+ 'dd-container': async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
589
605
  const baseCommand = options.dev ? 'node bin' : 'underpost';
590
606
  const baseClusterCommand = options.dev ? ' --dev' : '';
591
- const currentImage = UnderpostDeploy.API.getCurrentLoadedImages('kind-worker', false).find((o) =>
592
- o.IMAGE.match('underpost'),
593
- );
594
- const podName = `underpost-dev-container`;
595
- if (!UnderpostDeploy.API.existsContainerFile({ podName: 'kind-worker', path: '/home/dd/engine' })) {
596
- shellExec(`docker exec -i kind-worker bash -c "mkdir -p /home/dd"`);
597
- shellExec(`docker cp /home/dd/engine kind-worker:/home/dd/engine`);
598
- shellExec(`docker exec -i kind-worker bash -c "chown -R 1000:1000 /home/dd || true; chmod -R 755 /home/dd"`);
607
+ const currentImage = options.imageName
608
+ ? options.imageName
609
+ : UnderpostDeploy.API.getCurrentLoadedImages(options.nodeName ? options.nodeName : 'kind-worker', false).find(
610
+ (o) => o.IMAGE.match('underpost'),
611
+ );
612
+ const podName = options.podName || `underpost-dev-container`;
613
+ const volumeHostPath = options.claimName || '/home/dd';
614
+ const claimName = options.claimName || `pvc-dd`;
615
+
616
+ if (!options.nodeName) {
617
+ shellExec(`docker exec -i kind-worker bash -c "rm -rf ${volumeHostPath}"`);
618
+ shellExec(`docker exec -i kind-worker bash -c "mkdir -p ${volumeHostPath}"`);
619
+ shellExec(`docker cp ${volumeHostPath}/engine kind-worker:${volumeHostPath}/engine`);
620
+ shellExec(
621
+ `docker exec -i kind-worker bash -c "chown -R 1000:1000 ${volumeHostPath} || true; chmod -R 755 ${volumeHostPath}"`,
622
+ );
623
+ } else {
624
+ shellExec(`kubectl apply -f ${options.underpostRoot}/manifests/pv-pvc-dd.yaml -n ${options.namespace}`);
599
625
  }
600
- if (!currentImage) shellExec(`${baseCommand} dockerfile-pull-base-images${baseClusterCommand} --kind-load`);
626
+
627
+ if (!currentImage)
628
+ shellExec(
629
+ `${baseCommand} dockerfile-pull-base-images${baseClusterCommand} ${options.dev ? '--kind-load' : '--kubeadm-load'}`,
630
+ );
601
631
  // shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
602
- await UnderpostRun.RUNNERS['deploy-job']('', {
603
- dev: true,
632
+
633
+ const payload = {
634
+ ...options,
604
635
  podName,
605
- imageName: currentImage ? currentImage.image : `localhost/rockylinux9-underpost:${Underpost.version}`,
606
- volumeHostPath: '/home/dd',
607
- volumeMountPath: '/home/dd',
636
+ imageName: currentImage
637
+ ? currentImage.image
638
+ ? currentImage.image
639
+ : currentImage.IMAGE
640
+ ? `${currentImage.IMAGE}:${currentImage.TAG}`
641
+ : `localhost/rockylinux9-underpost:${Underpost.version}`
642
+ : `localhost/rockylinux9-underpost:${Underpost.version}`,
643
+ volumeMountPath: volumeHostPath,
644
+ ...(options.dev ? { volumeHostPath } : { claimName }),
608
645
  on: {
609
646
  init: async () => {
610
647
  // openTerminal(`kubectl logs -f ${podName}`);
611
648
  },
612
649
  },
613
- args: [daemonProcess(path ? path : `cd /home/dd/engine && npm run test`)],
614
- });
650
+ args: [daemonProcess(path ? path : `cd /home/dd/engine && npm install && npm run test`)],
651
+ };
652
+
653
+ await UnderpostRun.RUNNERS['deploy-job'](path, payload);
654
+ },
655
+
656
+ /**
657
+ * @method ip-info
658
+ * @description Executes the `ip-info.sh` script to display IP-related information for the specified path.
659
+ * @param {string} path - The input value, identifier, or path for the operation (used as an argument to the script).
660
+ * @param {Object} options - The default underpost runner options for customizing workflow
661
+ * @memberof UnderpostRun
662
+ */
663
+ 'ip-info': (path, options = UnderpostRun.DEFAULT_OPTION) => {
664
+ const { underpostRoot } = options;
665
+ shellExec(`chmod +x ${underpostRoot}/scripts/ip-info.sh`);
666
+ shellExec(`${underpostRoot}/scripts/ip-info.sh ${path}`);
615
667
  },
616
668
 
617
669
  /**
@@ -632,7 +684,7 @@ class UnderpostRun {
632
684
  switch (path) {
633
685
  case 'tf-vae-test':
634
686
  {
635
- const nameSpace = 'default';
687
+ const nameSpace = options.namespace || 'default';
636
688
  const podName = path;
637
689
  const basePath = '/home/dd';
638
690
  const scriptPath = '/site/en/tutorials/generative/cvae.py';
@@ -714,8 +766,8 @@ class UnderpostRun {
714
766
  // For kubeadm/k3s, ensure it's available for containerd
715
767
  shellExec(`sudo crictl pull ${image}`);
716
768
 
717
- shellExec(`kubectl delete deployment adminer`);
718
- shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/.`);
769
+ shellExec(`kubectl delete deployment adminer -n ${options.namespace} --ignore-not-found`);
770
+ shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/. -n ${options.namespace}`);
719
771
  const successInstance = await UnderpostTest.API.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
720
772
 
721
773
  if (successInstance) {
@@ -872,7 +924,7 @@ class UnderpostRun {
872
924
  const env = 'production';
873
925
  const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
874
926
 
875
- shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
927
+ shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic} -n ${options.namespace}`);
876
928
 
877
929
  await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic, ignorePods);
878
930
 
@@ -993,9 +1045,9 @@ class UnderpostRun {
993
1045
  );
994
1046
  switch (serviceId) {
995
1047
  case 'mongo-express-service': {
996
- shellExec(`kubectl delete svc mongo-express-service --ignore-not-found`);
997
- shellExec(`kubectl delete deployment mongo-express --ignore-not-found`);
998
- shellExec(`kubectl apply -f manifests/deployment/mongo-express/deployment.yaml`);
1048
+ shellExec(`kubectl delete svc mongo-express-service -n ${options.namespace} --ignore-not-found`);
1049
+ shellExec(`kubectl delete deployment mongo-express -n ${options.namespace} --ignore-not-found`);
1050
+ shellExec(`kubectl apply -f manifests/deployment/mongo-express/deployment.yaml -n ${options.namespace}`);
999
1051
  podToMonitor = 'mongo-express';
1000
1052
  break;
1001
1053
  }
@@ -1094,7 +1146,11 @@ class UnderpostRun {
1094
1146
  shellExec(`${baseCommand} env ${deployId} ${env}`);
1095
1147
  for (const host of Object.keys(confServer))
1096
1148
  if (_path in confServer[host]) shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
1097
- const node = options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname();
1149
+ const node = options.nodeName
1150
+ ? options.nodeName
1151
+ : options.dev || !isDeployRunnerContext(path, options)
1152
+ ? 'kind-control-plane'
1153
+ : os.hostname();
1098
1154
  // deployId, replicas, versions, image, node
1099
1155
  let defaultPath = [deployId, 1, ``, ``, node];
1100
1156
  shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
@@ -1153,40 +1209,58 @@ class UnderpostRun {
1153
1209
  'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1154
1210
  const podName = options.podName || 'deploy-job';
1155
1211
  const volumeName = `${podName}-volume`;
1156
- const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
1212
+ if (typeof options.args === 'string') options.args = options.args.split(',');
1213
+ const args = (options.args ? options.args : path ? [path] : [`python ${path}`]).filter((c) => c.trim());
1157
1214
  const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
1158
1215
  const containerName = options.containerName || `${podName}-container`;
1159
1216
  const gpuEnable = imageName.match('nvidia');
1160
- const runtimeClassName = gpuEnable ? 'nvidia' : '';
1217
+ const runtimeClassName = options.runtimeClassName ? options.runtimeClassName : gpuEnable ? 'nvidia' : '';
1161
1218
  const namespace = options.namespace || 'default';
1162
1219
  const volumeMountPath = options.volumeMountPath || path;
1163
1220
  const volumeHostPath = options.volumeHostPath || path;
1164
- const enableVolumeMount = volumeHostPath && volumeMountPath;
1221
+ const claimName = options.claimName || '';
1222
+ const enableVolumeMount = volumeMountPath && (volumeHostPath || claimName);
1165
1223
  const tty = options.tty ? 'true' : 'false';
1166
1224
  const stdin = options.stdin ? 'true' : 'false';
1167
1225
  const restartPolicy = options.restartPolicy || 'Never';
1168
-
1226
+ const kind = options.kind || 'Pod';
1227
+ const imagePullPolicy = options.imagePullPolicy || 'IfNotPresent';
1228
+ const hostNetwork = options.hostNetwork ? options.hostNetwork : '';
1229
+ const apiVersion = options.apiVersion || 'v1';
1230
+ const labels = options.labels
1231
+ ? options.labels
1232
+ .split(',')
1233
+ .map((keyValue) => {
1234
+ const [key, value] = keyValue.split('=');
1235
+ return ` ${key}: ${value}
1236
+ `;
1237
+ })
1238
+ .join('')
1239
+ : ` app: ${podName}`;
1169
1240
  if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
1170
1241
  const volumeType =
1171
- options.volumeType || (enableVolumeMount && fs.statSync(volumeHostPath).isDirectory()) ? 'Directory' : 'File';
1242
+ options.volumeType || (enableVolumeMount && volumeHostPath && fs.statSync(volumeHostPath).isDirectory())
1243
+ ? 'Directory'
1244
+ : 'File';
1172
1245
 
1173
1246
  const envs = UnderpostRootEnv.API.list();
1174
1247
 
1175
1248
  const cmd = `kubectl apply -f - <<EOF
1176
- apiVersion: v1
1177
- kind: Pod
1249
+ apiVersion: ${apiVersion}
1250
+ kind: ${kind}
1178
1251
  metadata:
1179
1252
  name: ${podName}
1180
1253
  namespace: ${namespace}
1181
1254
  labels:
1182
- app: ${podName}
1255
+ ${labels}
1183
1256
  spec:
1184
1257
  restartPolicy: ${restartPolicy}
1185
1258
  ${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
1259
+ ${hostNetwork ? ` hostNetwork: ${hostNetwork}` : ''}
1186
1260
  containers:
1187
1261
  - name: ${containerName}
1188
1262
  image: ${imageName}
1189
- imagePullPolicy: IfNotPresent
1263
+ imagePullPolicy: ${imagePullPolicy}
1190
1264
  tty: ${tty}
1191
1265
  stdin: ${stdin}
1192
1266
  command: ${JSON.stringify(options.command ? options.command : ['/bin/bash', '-c'])}
@@ -1212,25 +1286,17 @@ ${Object.keys(envs)
1212
1286
  .join('\n')}`}
1213
1287
  ${
1214
1288
  enableVolumeMount
1215
- ? `
1216
- volumeMounts:
1217
- - name: ${volumeName}
1218
- mountPath: ${volumeMountPath}
1219
- volumes:
1220
- - name: ${volumeName}
1221
- hostPath:
1222
- path: ${volumeHostPath}
1223
- type: ${volumeType}`
1289
+ ? UnderpostDeploy.API.volumeFactory([{ volumeMountPath, volumeName, volumeHostPath, volumeType, claimName }]).render
1224
1290
  : ''
1225
1291
  }
1226
1292
  EOF`;
1227
- shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
1293
+ shellExec(`kubectl delete pod ${podName} -n ${namespace} --ignore-not-found`);
1228
1294
  console.log(cmd);
1229
1295
  shellExec(cmd, { disableLog: true });
1230
1296
  const successInstance = await UnderpostTest.API.statusMonitor(podName);
1231
1297
  if (successInstance) {
1232
1298
  options.on?.init ? await options.on.init() : null;
1233
- shellExec(`kubectl logs -f ${podName}`);
1299
+ shellExec(`kubectl logs -f ${podName} -n ${namespace}`);
1234
1300
  }
1235
1301
  },
1236
1302
  };
@@ -1251,7 +1317,8 @@ EOF`;
1251
1317
  const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
1252
1318
  if (options.command) options.command = options.command.split(',');
1253
1319
  if (options.args) options.args = options.args.split(',');
1254
- options.underpostRoot = underpostRoot;
1320
+ if (!options.underpostRoot) options.underpostRoot = underpostRoot;
1321
+ if (!options.namespace) options.namespace = 'default';
1255
1322
  options.npmRoot = npmRoot;
1256
1323
  logger.info('callback', { path, options });
1257
1324
  if (!(runner in UnderpostRun.RUNNERS)) throw new Error(`Runner not found: ${runner}`);
@@ -6,7 +6,7 @@ const loggerFactory = (meta, options = { trace: false }) => {
6
6
  const logger = {
7
7
  log: function (type, args) {
8
8
  if (!window.renderPayload.dev) return;
9
- if (options.trace === true) args.push(getCurrentTrace().split('Logger.js:23')[1]);
9
+ if (options.trace === true) args.push(getCurrentTrace().split('Logger.js')[1]);
10
10
  return console[type](`[${meta}] ${new Date().toISOString()} ${type}:`, ...args);
11
11
  },
12
12
  };
@@ -87,6 +87,7 @@ const Modal = {
87
87
  onExpandUiListener: {},
88
88
  onBarUiOpen: {},
89
89
  onBarUiClose: {},
90
+ onReloadModalListener: {},
90
91
  onHome: {},
91
92
  homeModals: options.homeModals ? options.homeModals : [],
92
93
  query: options.query ? `${window.location.search}` : undefined,
@@ -121,6 +122,7 @@ const Modal = {
121
122
  top = `${windowGetH() / 2 - height / 2}px`;
122
123
  left = `${windowGetW() / 2 - width / 2}px`;
123
124
  },
125
+ ...this.Data[idModal],
124
126
  };
125
127
 
126
128
  if (options && 'mode' in options) {
@@ -1387,6 +1389,9 @@ const Modal = {
1387
1389
  if (options.zIndexSync) this.zIndexSync({ idModal });
1388
1390
 
1389
1391
  if (s(`.${idModal}`)) {
1392
+ for (const event of Object.keys(Modal.Data[idModal].onReloadModalListener))
1393
+ await Modal.Data[idModal].onReloadModalListener[event]();
1394
+
1390
1395
  s(`.btn-maximize-${idModal}`).click();
1391
1396
  return;
1392
1397
  }