@underpostnet/underpost 2.8.5 → 2.8.6

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 (60) hide show
  1. package/.github/workflows/ghpkg.yml +1 -1
  2. package/.github/workflows/npmpkg.yml +1 -1
  3. package/.github/workflows/pwa-microservices-template.page.yml +1 -1
  4. package/.vscode/settings.json +4 -0
  5. package/CHANGELOG.md +24 -0
  6. package/bin/build.js +29 -4
  7. package/bin/deploy.js +70 -74
  8. package/bin/hwt.js +0 -10
  9. package/bin/index.js +54 -23
  10. package/bin/util.js +0 -7
  11. package/bin/vs.js +1 -0
  12. package/conf.js +0 -2
  13. package/docker-compose.yml +1 -1
  14. package/manifests/kind-config-dev.yaml +12 -0
  15. package/manifests/mongodb/kustomization.yaml +2 -2
  16. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  17. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  18. package/package.json +9 -7
  19. package/src/cli/cluster.js +99 -51
  20. package/src/cli/cron.js +1 -1
  21. package/src/cli/db.js +102 -38
  22. package/src/cli/deploy.js +76 -35
  23. package/src/cli/fs.js +149 -0
  24. package/src/cli/image.js +50 -27
  25. package/src/cli/repository.js +21 -0
  26. package/src/cli/script.js +25 -1
  27. package/src/cli/test.js +39 -4
  28. package/src/client/components/core/CalendarCore.js +12 -1
  29. package/src/client/components/core/CommonJs.js +52 -1
  30. package/src/client/components/core/CssCore.js +2 -4
  31. package/src/client/components/core/Docs.js +1 -2
  32. package/src/client/components/core/Input.js +4 -2
  33. package/src/client/components/core/LoadingAnimation.js +8 -1
  34. package/src/client/components/core/Modal.js +30 -6
  35. package/src/client/components/core/Panel.js +8 -6
  36. package/src/client/components/core/PanelForm.js +23 -7
  37. package/src/client/services/core/core.service.js +15 -10
  38. package/src/client/ssr/Render.js +4 -1
  39. package/src/client/ssr/body/CacheControl.js +2 -3
  40. package/src/client/sw/default.sw.js +3 -3
  41. package/src/db/mongo/MongooseDB.js +17 -1
  42. package/src/index.js +9 -1
  43. package/src/server/backup.js +3 -3
  44. package/src/server/client-build.js +32 -23
  45. package/src/server/client-formatted.js +2 -1
  46. package/src/server/conf.js +17 -15
  47. package/src/server/dns.js +39 -46
  48. package/src/server/downloader.js +0 -8
  49. package/src/server/runtime.js +16 -1
  50. package/test/api.test.js +0 -8
  51. package/manifests/core/kustomization.yaml +0 -11
  52. package/manifests/core/underpost-engine-backup-access.yaml +0 -16
  53. package/manifests/core/underpost-engine-backup-pv-pvc.yaml +0 -22
  54. package/manifests/core/underpost-engine-headless-service.yaml +0 -10
  55. package/manifests/core/underpost-engine-mongodb-backup-cronjob.yaml +0 -40
  56. package/manifests/core/underpost-engine-mongodb-configmap.yaml +0 -26
  57. package/manifests/core/underpost-engine-statefulset.yaml +0 -91
  58. package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
  59. package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
  60. /package/manifests/{core/underpost-engine-pv-pvc.yaml → mongodb-4.4/pv-pvc.yaml} +0 -0
@@ -396,8 +396,7 @@ const CssCoreDark = {
396
396
  text-align: center;
397
397
  background: #1a1a1a;
398
398
  font-size: 17px;
399
- padding-top: 7px;
400
- padding-bottom: 6px;
399
+ height: 35px;
401
400
  }
402
401
  ::placeholder {
403
402
  color: #c6c4c4;
@@ -701,8 +700,7 @@ const CssCoreLight = {
701
700
  text-align: center;
702
701
  background: #eaeaea;
703
702
  font-size: 17px;
704
- padding-top: 7px;
705
- padding-bottom: 6px;
703
+ height: 35px;
706
704
  }
707
705
  ::placeholder {
708
706
  color: #333;
@@ -1,4 +1,3 @@
1
- import { _VERSION, CoreService } from '../../services/core/core.service.js';
2
1
  import { Badge } from './Badge.js';
3
2
  import { BtnIcon } from './BtnIcon.js';
4
3
  import { rgbToHex } from './CommonJs.js';
@@ -80,7 +79,7 @@ const Docs = {
80
79
  icon: html`<i class="fa-brands fa-osi"></i>`,
81
80
  text: 'Source Docs',
82
81
  url: function () {
83
- return `${getProxyPath()}docs/engine/${_VERSION}`;
82
+ return `${getProxyPath()}docs/engine/${window.renderPayload.version}`;
84
83
  },
85
84
  },
86
85
  {
@@ -88,8 +88,10 @@ const Input = {
88
88
  <div class="fl input-row-${id}">
89
89
  <div class="in fll" style="width: 80%;">${inputElement}</div>
90
90
  <div class="in fll btn-eye-password btn-eye-${id}" style="width: 20%;">
91
- <i class="fas fa-eye fa-eye-${id} eye-password"></i>
92
- <i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
91
+ <div class="abs center">
92
+ <i class="fas fa-eye fa-eye-${id} eye-password"></i>
93
+ <i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
94
+ </div>
93
95
  </div>
94
96
  </div>
95
97
  `
@@ -75,12 +75,17 @@ const LoadingAnimation = {
75
75
  const style = {
76
76
  'text-align': 'center',
77
77
  };
78
-
79
78
  if (s(container).classList) {
80
79
  const classes = Array.from(s(container).classList);
81
80
  if (classes.find((e) => e.match('management-table-btn-mini'))) {
82
81
  style.top = '-2px';
83
82
  style.left = '-2px';
83
+ } else if (classes.find((e) => e.match('-btn-tool'))) {
84
+ style.top = '-26px';
85
+ style.left = '-10px';
86
+ } else if (classes.find((e) => e.match('main-btn-')) && !classes.find((e) => e.match('main-btn-square-menu'))) {
87
+ style.top = '-8px';
88
+ style.left = '-10px';
84
89
  } else if (classes.find((e) => e.match('action-bar-box'))) {
85
90
  style.top = '-30px';
86
91
  style.left = '-12px';
@@ -145,6 +150,8 @@ const LoadingAnimation = {
145
150
  s(backgroundContainer).style.opacity = 0;
146
151
  setTimeout(async () => {
147
152
  s(backgroundContainer).style.display = 'none';
153
+ if (s(`.modal-menu`)) s(`.modal-menu`).classList.remove('hide');
154
+ if (s(`.main-body-btn-container`)) s(`.main-body-btn-container`).classList.remove('hide');
148
155
  if (callBack) callBack();
149
156
  }, 300);
150
157
  });
@@ -49,6 +49,7 @@ const Modal = {
49
49
  mode: '' /* slide-menu */,
50
50
  RouterInstance: {},
51
51
  disableTools: [],
52
+ observer: false,
52
53
  },
53
54
  ) {
54
55
  if (options.heightBottomBar === undefined) options.heightBottomBar = 50;
@@ -76,6 +77,8 @@ const Modal = {
76
77
  options,
77
78
  onCloseListener: {},
78
79
  onMenuListener: {},
80
+ onCollapseMenuListener: {},
81
+ onExtendMenuListener: {},
79
82
  onDragEndListener: {},
80
83
  onObserverListener: {},
81
84
  onClickListener: {},
@@ -156,7 +159,8 @@ const Modal = {
156
159
  };
157
160
  options.mode === 'slide-menu-right' ? (options.style.right = '0px') : (options.style.left = '0px');
158
161
  const contentIconClass = 'abs center';
159
-
162
+ if (options.class) options.class += ' hide';
163
+ else options.class = 'hide';
160
164
  options.dragDisabled = true;
161
165
  options.titleClass = 'hide';
162
166
  top = '0px';
@@ -238,7 +242,7 @@ const Modal = {
238
242
  'body',
239
243
  html`
240
244
  <div
241
- class="abs main-body-btn-container"
245
+ class="abs main-body-btn-container hide"
242
246
  style="top: ${options.heightTopBar + 50}px; z-index: 9; ${true ||
243
247
  (options.mode && options.mode.match('right'))
244
248
  ? 'right'
@@ -1383,6 +1387,9 @@ const Modal = {
1383
1387
  if (options.onCollapseMenu) options.onCollapseMenu();
1384
1388
  s(`.sub-menu-title-container-${'modal-menu'}`).classList.add('hide');
1385
1389
  s(`.nav-path-container-${'modal-menu'}`).classList.add('hide');
1390
+ Object.keys(this.Data[idModal].onCollapseMenuListener).map((keyListener) =>
1391
+ this.Data[idModal].onCollapseMenuListener[keyListener](),
1392
+ );
1386
1393
  } else {
1387
1394
  slideMenuWidth = originSlideMenuWidth;
1388
1395
  setTimeout(() => {
@@ -1403,6 +1410,9 @@ const Modal = {
1403
1410
  if (options.onExtendMenu) options.onExtendMenu();
1404
1411
  s(`.sub-menu-title-container-${'modal-menu'}`).classList.remove('hide');
1405
1412
  s(`.nav-path-container-${'modal-menu'}`).classList.remove('hide');
1413
+ Object.keys(this.Data[idModal].onExtendMenuListener).map((keyListener) =>
1414
+ this.Data[idModal].onExtendMenuListener[keyListener](),
1415
+ );
1406
1416
  }
1407
1417
  // btn-bar-center-icon-menu
1408
1418
  this.actionBtnCenter();
@@ -1781,20 +1791,34 @@ const renderMenuLabel = ({ img, text, icon }) => {
1781
1791
  <div class="abs center main-btn-menu-text">${text}</div>`;
1782
1792
  };
1783
1793
 
1784
- const renderViewTitle = (options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top }) => {
1785
- if (options.dim === undefined) options.dim = 60;
1794
+ const renderViewTitle = (
1795
+ options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top, topText: '' },
1796
+ ) => {
1797
+ if (options.dim === undefined) options.dim = 30;
1786
1798
  const { img, text, icon, dim, top } = options;
1787
1799
  if (!img && !options['ui-icon']) return html`<span class="view-title-icon">${icon}</span> ${text}`;
1788
1800
  return html`<img
1789
1801
  class="abs img-btn-square-view-title"
1790
1802
  style="${renderCssAttr({
1791
- style: { width: `${dim}px`, height: `${dim}px`, top: top !== undefined ? `${top}px` : `-${dim / 2}px` },
1803
+ style: {
1804
+ width: `${dim}px`,
1805
+ height: `${dim}px`,
1806
+ top: top !== undefined ? `${top}px !important` : undefined,
1807
+ },
1792
1808
  })}"
1793
1809
  src="${options['ui-icon']
1794
1810
  ? `${getProxyPath()}assets/${options.assetFolder ? options.assetFolder : 'ui-icons'}/${options['ui-icon']}`
1795
1811
  : img}"
1796
1812
  />
1797
- <div class="in text-btn-square-view-title" style="${renderCssAttr({ style: { 'padding-left': `${dim}px` } })}">
1813
+ <div
1814
+ class="in text-btn-square-view-title"
1815
+ style="${renderCssAttr({
1816
+ style: {
1817
+ // 'padding-left': `${20 + dim}px`,
1818
+ ...(options.topText !== undefined ? { top: options.topText + 'px !important' } : {}),
1819
+ },
1820
+ })}"
1821
+ >
1798
1822
  ${text}
1799
1823
  </div>`;
1800
1824
  };
@@ -26,6 +26,7 @@ const Panel = {
26
26
  idPanel: '',
27
27
  parentIdModal: '',
28
28
  scrollClassContainer: '',
29
+ htmlFormHeader: async () => '',
29
30
  formData: [],
30
31
  data: [],
31
32
  originData: () => [],
@@ -244,12 +245,13 @@ const Panel = {
244
245
 
245
246
  let render = '';
246
247
  let renderForm = html` <div class="in modal stq" style="top: 0px; z-index: 1; padding-bottom: 5px">
247
- ${await BtnIcon.Render({
248
- class: `section-mp btn-custom btn-${idPanel}-close`,
249
- label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
250
- type: 'button',
251
- })}
252
- </div>`;
248
+ ${await BtnIcon.Render({
249
+ class: `section-mp btn-custom btn-${idPanel}-close`,
250
+ label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
251
+ type: 'button',
252
+ })}
253
+ </div>
254
+ ${options?.htmlFormHeader ? await options.htmlFormHeader() : ''}`;
253
255
 
254
256
  for (const modelData of formData) {
255
257
  if (modelData.disableRender) continue;
@@ -29,6 +29,8 @@ const PanelForm = {
29
29
  Elements: {},
30
30
  parentIdModal: undefined,
31
31
  route: 'home',
32
+ htmlFormHeader: async () => '',
33
+ firsUpdateEvent: async () => {},
32
34
  },
33
35
  ) {
34
36
  const { idPanel, heightTopBar, heightBottomBar, defaultUrlImage, Elements } = options;
@@ -99,6 +101,7 @@ const PanelForm = {
99
101
  heightTopBar,
100
102
  heightBottomBar,
101
103
  data,
104
+ htmlFormHeader: options.htmlFormHeader,
102
105
  parentIdModal: options.parentIdModal,
103
106
  originData: () => PanelForm.Data[idPanel].originData,
104
107
  filesData: () => PanelForm.Data[idPanel].filesData,
@@ -421,8 +424,16 @@ const PanelForm = {
421
424
  ssr: true,
422
425
  })),
423
426
  });
424
-
427
+ let delayBlock = false;
428
+ let firsUpdateEvent = false;
425
429
  this.Data[idPanel].updatePanel = async () => {
430
+ if (delayBlock) return;
431
+ else {
432
+ delayBlock = true;
433
+ setTimeout(() => {
434
+ delayBlock = false;
435
+ }, 500);
436
+ }
426
437
  const cid = getQueryParams().cid ? getQueryParams().cid : '';
427
438
  if (options.route === 'home') Modal.homeCid = newInstance(cid);
428
439
  htmls(`.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`, await renderSrrPanelData());
@@ -431,23 +442,28 @@ const PanelForm = {
431
442
  `.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`,
432
443
  await panelRender({ data: this.Data[idPanel].data }),
433
444
  );
445
+ if (!firsUpdateEvent && options.firsUpdateEvent) {
446
+ firsUpdateEvent = true;
447
+ await options.firsUpdateEvent();
448
+ }
434
449
  };
435
450
  if (options.route)
436
451
  listenQueryPathInstance({
437
452
  id: options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body',
438
453
  routeId: options.route,
439
454
  event: async (path) => {
440
- if (!PanelForm.Data[idPanel].sessionIn) await this.Data[idPanel].updatePanel();
455
+ // if (!PanelForm.Data[idPanel].sessionIn)
456
+ await this.Data[idPanel].updatePanel();
441
457
  },
442
458
  });
443
459
 
444
460
  // if (options.route === 'home') setTimeout(this.Data[idPanel].updatePanel);
445
461
  setTimeout(() => {
446
- if (
447
- options.route !== 'home' &&
448
- (!PanelForm.Data[idPanel].originData || PanelForm.Data[idPanel].originData.length === 0)
449
- )
450
- this.Data[idPanel].updatePanel();
462
+ // if (
463
+ // options.route !== 'home' &&
464
+ // (!PanelForm.Data[idPanel].originData || PanelForm.Data[idPanel].originData.length === 0)
465
+ // )
466
+ this.Data[idPanel].updatePanel();
451
467
  });
452
468
 
453
469
  if (options.parentIdModal) {
@@ -4,13 +4,24 @@ import { getProxyPath } from '../../components/core/VanillaJs.js';
4
4
 
5
5
  const logger = loggerFactory(import.meta);
6
6
 
7
+ logger.info('Load service');
8
+
9
+ const endpoint = 'core';
10
+
7
11
  // https://developer.mozilla.org/en-US/docs/Web/API/AbortController
8
- const getBaseHost = () => location.host;
12
+ const getBaseHost = () => (window.renderPayload?.apiBaseHost ? window.renderPayload.apiBaseHost : location.host);
9
13
 
10
- const getApiBasePath = () => `${getProxyPath()}api/`;
14
+ const getApiBasePath = (options) =>
15
+ `${
16
+ options?.proxyPath
17
+ ? `/${options.proxyPath}/`
18
+ : window.renderPayload?.apiBaseProxyPath
19
+ ? window.renderPayload.apiBaseProxyPath
20
+ : getProxyPath()
21
+ }${window.renderPayload?.apiBasePath ? window.renderPayload.apiBasePath : 'api'}/`;
11
22
 
12
- const getApiBaseUrl = (options = { id: '', endpoint: '' }) =>
13
- `${location.protocol}//${getBaseHost()}${getApiBasePath()}${options?.endpoint ? options.endpoint : ''}${
23
+ const getApiBaseUrl = (options = { id: '', endpoint: '', proxyPath: '' }) =>
24
+ `${location.protocol}//${getBaseHost()}${getApiBasePath(options)}${options?.endpoint ? options.endpoint : ''}${
14
25
  options?.id ? `/${options.id}` : ''
15
26
  }`;
16
27
 
@@ -38,11 +49,6 @@ const payloadFactory = (body) => {
38
49
  return JSON.stringify(body);
39
50
  };
40
51
 
41
- logger.info('Load service');
42
-
43
- const endpoint = 'core';
44
- const _VERSION = window._VERSION;
45
-
46
52
  const CoreService = {
47
53
  getRaw: (options = { url: '' }) =>
48
54
  new Promise((resolve, reject) =>
@@ -159,7 +165,6 @@ const CoreService = {
159
165
  const ApiBase = getApiBaseUrl;
160
166
 
161
167
  export {
162
- _VERSION,
163
168
  CoreService,
164
169
  headersFactory,
165
170
  payloadFactory,
@@ -1,4 +1,4 @@
1
- SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents }) => html`
1
+ SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents, renderPayload, renderApi }) => html`
2
2
  <!DOCTYPE html>
3
3
  <html dir="ltr" lang="en">
4
4
  <head>
@@ -6,6 +6,9 @@ SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents
6
6
  <link rel="icon" type="image/x-icon" href="${ssrPath}favicon.ico" />
7
7
  <meta charset="UTF-8" />
8
8
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
9
+ <script>
10
+ window.renderPayload = ${renderApi.JSONweb(renderPayload)};
11
+ </script>
9
12
  ${ssrHeadComponents}
10
13
  </head>
11
14
  <body>
@@ -70,7 +70,7 @@ const CacheControl = function ({ ttiLoadTimeLimit }) {
70
70
  setTimeout(window.cacheControlCallBack, ttiLoadTimeLimit); // 70s limit);
71
71
  };
72
72
 
73
- SrrComponent = ({ ttiLoadTimeLimit }) => {
73
+ SrrComponent = ({ ttiLoadTimeLimit, version }) => {
74
74
  const borderChar = (px, color, selectors) => {
75
75
  if (selectors) {
76
76
  return selectors
@@ -106,10 +106,9 @@ SrrComponent = ({ ttiLoadTimeLimit }) => {
106
106
  </style>
107
107
  ${borderChar(1, 'black', ['.clean-cache-container'])}
108
108
  <script>
109
- window._VERSION = '${npm_package_version}';
110
109
  const CacheControl = ${CacheControl};
111
110
  CacheControl({ ttiLoadTimeLimit: ${ttiLoadTimeLimit ? ttiLoadTimeLimit : 1000 * 70 * 1} });
112
111
  </script>
113
- <div class="clean-cache-container">${npm_package_version}</div>
112
+ <div class="clean-cache-container">${version}</div>
114
113
  `;
115
114
  };
@@ -1,6 +1,6 @@
1
- const PRE_CACHED_RESOURCES = [];
2
- const CACHE_NAME = 'app-cache';
3
- const PROXY_PATH = '/';
1
+ const PRE_CACHED_RESOURCES = self.renderPayload?.PRE_CACHED_RESOURCES ? self.renderPayload.PRE_CACHED_RESOURCES : [];
2
+ const CACHE_NAME = self.renderPayload?.CACHE_NAME ? self.renderPayload.CACHE_NAME : 'app-cache';
3
+ const PROXY_PATH = self.renderPayload?.PROXY_PATH ? self.renderPayload.PROXY_PATH : '/';
4
4
  self.addEventListener('install', (event) => {
5
5
  // Activate right away
6
6
  self.skipWaiting();
@@ -79,7 +79,19 @@ const MongooseDB = {
79
79
  if (process.argv.includes('rocky')) {
80
80
  // https://github.com/mongodb/mongodb-selinux
81
81
  // https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-enterprise-on-red-hat/
82
- shellExec(`sudo chown -R mongod:mongod /var/lib/mongo`);
82
+ // https://www.mongodb.com/docs/v6.0/tutorial/install-mongodb-on-red-hat/
83
+ // https://www.mongodb.com/docs/v4.4/tutorial/install-mongodb-on-red-hat/
84
+ // dnf install selinux-policy-devel
85
+ // git clone https://github.com/mongodb/mongodb-selinux
86
+ // cd mongodb-selinux
87
+ // make
88
+ // sudo make install
89
+ // yum list installed | grep mongo
90
+ // sudo yum erase $(rpm -qa | grep mongodb)
91
+ // remove service
92
+ // sudo systemctl reset-failed
93
+ // MongoDB 5.0+ requires a CPU with AVX support
94
+ // check: grep avx /proc/cpuinfo
83
95
  }
84
96
  logger.info('install legacy 4.4');
85
97
  shellExec(`wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -`);
@@ -112,9 +124,13 @@ const MongooseDB = {
112
124
  shellExec(`sudo systemctl unmask mongod`);
113
125
  shellExec(`sudo pkill -f mongod`);
114
126
  shellExec(`sudo systemctl enable mongod.service`);
127
+
115
128
  shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb`);
116
129
  shellExec(`sudo chown mongodb:mongodb /tmp/mongodb-27017.sock`);
117
130
 
131
+ shellExec(`sudo chown -R mongod:mongod /var/lib/mongodb`);
132
+ shellExec(`sudo chown mongod:mongod /tmp/mongodb-27017.sock`);
133
+
118
134
  logger.info('run server');
119
135
  shellExec(`sudo service mongod restart`);
120
136
 
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ import UnderpostCron from './cli/cron.js';
9
9
  import UnderpostDB from './cli/db.js';
10
10
  import UnderpostDeploy from './cli/deploy.js';
11
11
  import UnderpostRootEnv from './cli/env.js';
12
+ import UnderpostFileStorage from './cli/fs.js';
12
13
  import UnderpostImage from './cli/image.js';
13
14
  import UnderpostRepository from './cli/repository.js';
14
15
  import UnderpostScript from './cli/script.js';
@@ -27,7 +28,7 @@ class Underpost {
27
28
  * @type {String}
28
29
  * @memberof Underpost
29
30
  */
30
- static version = 'v2.8.5';
31
+ static version = 'v2.8.6';
31
32
  /**
32
33
  * Repository cli API
33
34
  * @static
@@ -98,6 +99,13 @@ class Underpost {
98
99
  * @memberof Underpost
99
100
  */
100
101
  static cron = UnderpostCron.API;
102
+ /**
103
+ * File Storage cli API
104
+ * @static
105
+ * @type {UnderpostFileStorage.API}
106
+ * @memberof UnderpostFileStorage
107
+ */
108
+ static fs = UnderpostFileStorage.API;
101
109
  }
102
110
 
103
111
  const up = Underpost;
@@ -9,7 +9,7 @@ dotenv.config();
9
9
  const logger = loggerFactory(import.meta);
10
10
 
11
11
  class BackUp {
12
- static callback = async function (deployList, options = { disableKindCluster: false }) {
12
+ static callback = async function (deployList, options = { itc: false, git: false }) {
13
13
  if ((!deployList || deployList === 'dd') && fs.existsSync(`./engine-private/deploy/dd.router`))
14
14
  deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
15
15
 
@@ -25,8 +25,8 @@ class BackUp {
25
25
  const deployId = _deployId.trim();
26
26
  if (!deployId) continue;
27
27
 
28
- if (options.disableKindCluster !== true) {
29
- shellExec(`underpost db --export ${deployId}`);
28
+ if (!(options.itc === true)) {
29
+ shellExec(`node bin db ${options.git ? '--git ' : ''}--export ${deployId}`);
30
30
  continue;
31
31
  }
32
32
 
@@ -21,6 +21,7 @@ import swaggerAutoGen from 'swagger-autogen';
21
21
  import { SitemapStream, streamToPromise } from 'sitemap';
22
22
  import { Readable } from 'stream';
23
23
  import { buildIcons, buildTextImg, getBufferPngText } from './client-icons.js';
24
+ import Underpost from '../index.js';
24
25
 
25
26
  dotenv.config();
26
27
 
@@ -250,20 +251,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
250
251
  'services',
251
252
  baseHost,
252
253
  );
253
- if (module === 'core' && (process.env.NODE_ENV === 'production' || process.argv.includes('static'))) {
254
- if (apiBaseHost)
255
- jsSrc = jsSrc.replace(
256
- 'const getBaseHost = () => location.host;',
257
- `const getBaseHost = () => '${apiBaseHost}';`,
258
- );
259
- if (apiBaseProxyPath) {
260
- jsSrc = jsSrc.replace('${getProxyPath()}api/', `${apiBaseProxyPath}${process.env.BASE_API}/`);
261
- jsSrc = jsSrc.replace(
262
- "const getWsBasePath = () => (getProxyPath() !== '/' ? `${getProxyPath()}socket.io/` : undefined);",
263
- `const getWsBasePath = () => '${apiBaseProxyPath}socket.io/';`,
264
- );
265
- }
266
- }
267
254
  fs.writeFileSync(
268
255
  jsPublicPath,
269
256
  minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
@@ -487,7 +474,13 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
487
474
  }
488
475
 
489
476
  default:
490
- ssrBodyComponents += SrrComponent({ ssrPath, host, path, ttiLoadTimeLimit });
477
+ ssrBodyComponents += SrrComponent({
478
+ ssrPath,
479
+ host,
480
+ path,
481
+ ttiLoadTimeLimit,
482
+ version: Underpost.version,
483
+ });
491
484
  break;
492
485
  }
493
486
  }
@@ -507,6 +500,15 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
507
500
  ssrPath,
508
501
  ssrHeadComponents,
509
502
  ssrBodyComponents,
503
+ renderPayload: {
504
+ apiBaseProxyPath,
505
+ apiBaseHost,
506
+ apiBasePath: process.env.BASE_API,
507
+ version: Underpost.version,
508
+ },
509
+ renderApi: {
510
+ JSONweb,
511
+ },
510
512
  });
511
513
 
512
514
  fs.writeFileSync(
@@ -707,6 +709,15 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
707
709
  ssrPath,
708
710
  ssrHeadComponents: '',
709
711
  ssrBodyComponents: SsrComponent(),
712
+ renderPayload: {
713
+ apiBaseProxyPath,
714
+ apiBaseHost,
715
+ apiBasePath: process.env.BASE_API,
716
+ version: Underpost.version,
717
+ },
718
+ renderApi: {
719
+ JSONweb,
720
+ },
710
721
  });
711
722
 
712
723
  const buildPath = `${
@@ -739,16 +750,14 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
739
750
  }
740
751
 
741
752
  {
742
- const PRE_CACHED_JSON = `PRE_CACHED_RESOURCES = ${JSONweb(uniqueArray(PRE_CACHED_RESOURCES))}`;
743
- const PROXY_PATH = `PROXY_PATH = '${path}'`;
753
+ const renderPayload = {
754
+ PRE_CACHED_RESOURCES: uniqueArray(PRE_CACHED_RESOURCES),
755
+ PROXY_PATH: path,
756
+ };
744
757
  fs.writeFileSync(
745
758
  `${rootClientPath}/sw.js`,
746
- fs
747
- .readFileSync(`${rootClientPath}/sw.js`, 'utf8')
748
- .replaceAll(`PRE_CACHED_RESOURCES = []`, PRE_CACHED_JSON)
749
- .replaceAll(`PRE_CACHED_RESOURCES=[]`, PRE_CACHED_JSON)
750
- .replaceAll(`PROXY_PATH = '/'`, PROXY_PATH)
751
- .replaceAll(`PROXY_PATH='/'`, PROXY_PATH),
759
+ `self.renderPayload = ${JSONweb(renderPayload)};
760
+ ${fs.readFileSync(`${rootClientPath}/sw.js`, 'utf8')}`,
752
761
  'utf8',
753
762
  );
754
763
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import fs from 'fs-extra';
4
4
  import vm from 'node:vm';
5
+ import Underpost from '../index.js';
5
6
 
6
7
  const srcFormatted = (src) =>
7
8
  src
@@ -49,7 +50,7 @@ const viewFormatted = (src, dists, proxyPath, baseHost = '') => {
49
50
  };
50
51
 
51
52
  const ssrFactory = async (componentPath = `./src/client/ssr/Render.js`) => {
52
- const context = { SrrComponent: () => {}, npm_package_version: process.env.npm_package_version };
53
+ const context = { SrrComponent: () => {}, npm_package_version: Underpost.version };
53
54
  vm.createContext(context);
54
55
  vm.runInContext(await srcFormatted(fs.readFileSync(componentPath, 'utf8')), context);
55
56
  return context.SrrComponent;
@@ -19,17 +19,8 @@ import { DefaultConf } from '../../conf.js';
19
19
  import read from 'read';
20
20
  import splitFile from 'split-file';
21
21
  import axios from 'axios';
22
- import https from 'https';
23
22
  import { ssrFactory } from './client-formatted.js';
24
23
 
25
- // axios.defaults.baseURL = BASE_URL;
26
-
27
- // const httpsAgent = new https.Agent({
28
- // rejectUnauthorized: false,
29
- // });
30
-
31
- // axios.defaults.httpsAgent = httpsAgent;
32
-
33
24
  colors.enable();
34
25
 
35
26
  dotenv.config();
@@ -598,7 +589,13 @@ const cliSpinner = async (time = 5000, message0, message1, color, type = 'dots')
598
589
  const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1)}`;
599
590
 
600
591
  const getDataDeploy = (
601
- options = { buildSingleReplica: false, deployGroupId: '', deployId: '', disableSyncEnvPort: false },
592
+ options = {
593
+ buildSingleReplica: false,
594
+ deployGroupId: '',
595
+ deployId: '',
596
+ disableSyncEnvPort: false,
597
+ deployIdConcat: [],
598
+ },
602
599
  ) => {
603
600
  let dataDeploy =
604
601
  options.deployGroupId === 'dd'
@@ -610,6 +607,8 @@ const getDataDeploy = (
610
607
  .map((deployId) => deployId.trim())
611
608
  .filter((deployId) => deployId);
612
609
 
610
+ if (options.deployIdConcat) dataDeploy = dataDeploy.concat(options.deployIdConcat);
611
+
613
612
  if (options.deployId) dataDeploy = dataDeploy.filter((d) => d === options.deployId);
614
613
 
615
614
  dataDeploy = dataDeploy.map((deployId) => {
@@ -843,7 +842,7 @@ const deployRun = async (dataDeploy, currentAttempt = 1) => {
843
842
  if (failed.length > 0) {
844
843
  for (const deploy of failed) logger.error(deploy.deployId, Cmd.run(deploy.deployId));
845
844
  if (currentAttempt === maxAttempts) return logger.error(`max deploy attempts exceeded`);
846
- if (process.argv.includes('manual')) await read({ prompt: 'Press enter to retry failed processes\n' });
845
+ await read({ prompt: 'Press enter to retry failed processes\n' });
847
846
  currentAttempt++;
848
847
  await deployRun(failed, currentAttempt);
849
848
  } else logger.info(`Deploy process successfully`);
@@ -989,15 +988,15 @@ const getPathsSSR = (conf) => {
989
988
 
990
989
  const Cmd = {
991
990
  delete: (deployId) => `pm2 delete ${deployId}`,
992
- run: (deployId) => `node bin/deploy run ${deployId}`,
991
+ run: () => `npm start`,
993
992
  build: (deployId) => `node bin/deploy build-full-client ${deployId}${process.argv.includes('l') ? ' l' : ''}`,
994
993
  conf: (deployId, env) => `node bin/deploy conf ${deployId} ${env ? env : 'production'}`,
995
994
  replica: (deployId, host, path) => `node bin/deploy build-single-replica ${deployId} ${host} ${path}`,
996
995
  syncPorts: (deployGroupId) => `node bin/deploy sync-env-port ${deployGroupId}`,
997
996
  cron: (deployList, jobList, name, expression, options) =>
998
997
  `pm2 start ./bin/index.js --no-autorestart --instances 1 --cron "${expression}" --name ${name} -- cron ${
999
- options?.disableKindCluster ? `--disable-kind-cluster ` : ''
1000
- }${deployList} ${jobList}`,
998
+ options?.itc ? `--itc ` : ''
999
+ }${options?.git ? `--git ` : ''}${deployList} ${jobList}`,
1001
1000
  };
1002
1001
 
1003
1002
  const fixDependencies = async () => {
@@ -1064,7 +1063,7 @@ const setUpProxyMaintenanceServer = ({ deployGroupId }) => {
1064
1063
  shellExec(`node bin/deploy valkey-service`);
1065
1064
  const proxyDeployId = fs.readFileSync(`./engine-private/deploy/${deployGroupId}.proxy`, 'utf8').trim();
1066
1065
  shellExec(`node bin/deploy conf ${proxyDeployId} production`);
1067
- shellExec(`node bin/deploy run ${proxyDeployId} maintenance`);
1066
+ shellExec(`npm start ${proxyDeployId} maintenance`);
1068
1067
  };
1069
1068
 
1070
1069
  const getNpmRootPath = () =>
@@ -1074,6 +1073,8 @@ const getNpmRootPath = () =>
1074
1073
  silent: true,
1075
1074
  }).trim();
1076
1075
 
1076
+ const getUnderpostRootPath = () => `${getNpmRootPath()}/underpost`;
1077
+
1077
1078
  const writeEnv = (envPath, envObj) =>
1078
1079
  fs.writeFileSync(
1079
1080
  envPath,
@@ -1119,5 +1120,6 @@ export {
1119
1120
  buildPortProxyRouter,
1120
1121
  splitFileFactory,
1121
1122
  getNpmRootPath,
1123
+ getUnderpostRootPath,
1122
1124
  writeEnv,
1123
1125
  };