underpost 2.8.1 → 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 (108) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/ghpkg.yml +19 -49
  3. package/.github/workflows/npmpkg.yml +67 -0
  4. package/.github/workflows/publish.yml +5 -5
  5. package/.github/workflows/pwa-microservices-template.page.yml +12 -4
  6. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  7. package/.vscode/extensions.json +17 -71
  8. package/.vscode/settings.json +18 -3
  9. package/AUTHORS.md +16 -5
  10. package/CHANGELOG.md +103 -3
  11. package/Dockerfile +24 -66
  12. package/README.md +1 -28
  13. package/bin/build.js +186 -0
  14. package/bin/db.js +2 -24
  15. package/bin/deploy.js +169 -144
  16. package/bin/file.js +59 -16
  17. package/bin/hwt.js +0 -10
  18. package/bin/index.js +201 -60
  19. package/bin/ssl.js +19 -11
  20. package/bin/util.js +9 -104
  21. package/bin/vs.js +26 -2
  22. package/conf.js +29 -138
  23. package/docker-compose.yml +1 -1
  24. package/manifests/deployment/mongo-express/deployment.yaml +60 -0
  25. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  26. package/manifests/kind-config-dev.yaml +12 -0
  27. package/manifests/kind-config.yaml +12 -0
  28. package/manifests/letsencrypt-prod.yaml +15 -0
  29. package/manifests/mariadb/config.yaml +10 -0
  30. package/manifests/mariadb/kustomization.yaml +9 -0
  31. package/manifests/mariadb/pv.yaml +12 -0
  32. package/manifests/mariadb/pvc.yaml +10 -0
  33. package/manifests/mariadb/secret.yaml +8 -0
  34. package/manifests/mariadb/service.yaml +10 -0
  35. package/manifests/mariadb/statefulset.yaml +55 -0
  36. package/manifests/mongodb/backup-access.yaml +16 -0
  37. package/manifests/mongodb/backup-cronjob.yaml +42 -0
  38. package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
  39. package/manifests/mongodb/configmap.yaml +26 -0
  40. package/manifests/mongodb/headless-service.yaml +10 -0
  41. package/manifests/mongodb/kustomization.yaml +11 -0
  42. package/manifests/mongodb/pv-pvc.yaml +23 -0
  43. package/manifests/mongodb/statefulset.yaml +125 -0
  44. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  45. package/manifests/mongodb-4.4/pv-pvc.yaml +23 -0
  46. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  47. package/manifests/valkey/kustomization.yaml +7 -0
  48. package/manifests/valkey/service.yaml +17 -0
  49. package/manifests/valkey/statefulset.yaml +39 -0
  50. package/package.json +133 -136
  51. package/src/api/core/core.service.js +1 -1
  52. package/src/api/user/user.model.js +16 -3
  53. package/src/api/user/user.service.js +1 -1
  54. package/src/cli/cluster.js +202 -0
  55. package/src/cli/cron.js +90 -0
  56. package/src/cli/db.js +212 -0
  57. package/src/cli/deploy.js +318 -0
  58. package/src/cli/env.js +52 -0
  59. package/src/cli/fs.js +149 -0
  60. package/src/cli/image.js +148 -0
  61. package/src/cli/repository.js +125 -0
  62. package/src/cli/script.js +53 -0
  63. package/src/cli/secrets.js +37 -0
  64. package/src/cli/test.js +118 -0
  65. package/src/client/components/core/Auth.js +22 -4
  66. package/src/client/components/core/CalendarCore.js +127 -50
  67. package/src/client/components/core/CommonJs.js +282 -19
  68. package/src/client/components/core/Css.js +1 -0
  69. package/src/client/components/core/CssCore.js +8 -4
  70. package/src/client/components/core/Docs.js +1 -2
  71. package/src/client/components/core/DropDown.js +5 -1
  72. package/src/client/components/core/Input.js +22 -6
  73. package/src/client/components/core/LoadingAnimation.js +8 -1
  74. package/src/client/components/core/Modal.js +40 -12
  75. package/src/client/components/core/Panel.js +92 -31
  76. package/src/client/components/core/PanelForm.js +25 -23
  77. package/src/client/components/core/Scroll.js +1 -0
  78. package/src/client/components/core/Translate.js +47 -9
  79. package/src/client/components/core/Validator.js +9 -1
  80. package/src/client/components/core/VanillaJs.js +0 -9
  81. package/src/client/components/core/Worker.js +34 -31
  82. package/src/client/services/core/core.service.js +15 -10
  83. package/src/client/services/default/default.management.js +4 -2
  84. package/src/client/ssr/Render.js +4 -1
  85. package/src/client/ssr/body/CacheControl.js +2 -3
  86. package/src/client/sw/default.sw.js +3 -3
  87. package/src/db/mongo/MongooseDB.js +29 -1
  88. package/src/index.js +85 -19
  89. package/src/runtime/lampp/Lampp.js +1 -13
  90. package/src/runtime/xampp/Xampp.js +0 -13
  91. package/src/server/auth.js +3 -3
  92. package/src/server/backup.js +49 -93
  93. package/src/server/client-build.js +36 -46
  94. package/src/server/client-formatted.js +6 -3
  95. package/src/server/conf.js +204 -54
  96. package/src/server/dns.js +30 -55
  97. package/src/server/downloader.js +0 -8
  98. package/src/server/logger.js +15 -10
  99. package/src/server/network.js +17 -43
  100. package/src/server/process.js +25 -2
  101. package/src/server/proxy.js +4 -26
  102. package/src/server/runtime.js +30 -30
  103. package/src/server/ssl.js +1 -1
  104. package/src/server/valkey.js +2 -0
  105. package/test/api.test.js +0 -8
  106. package/src/dns.js +0 -22
  107. package/src/server/prompt-optimizer.js +0 -28
  108. package/startup.js +0 -11
@@ -11,35 +11,49 @@ const Translate = {
11
11
  Data: {},
12
12
  Token: {},
13
13
  Event: {},
14
+ Options: {},
14
15
  Parse: function (lang) {
15
16
  s('html').lang = lang;
16
17
  Object.keys(this.Token).map((translateHash) => {
17
18
  if (translateHash in this.Token && lang in this.Token[translateHash]) {
18
- if (!('placeholder' in this.Token[translateHash]) && s(`.${translateHash}`))
19
- htmls(`.${translateHash}`, textFormatted(this.Token[translateHash][lang]));
19
+ if (!('placeholder' in this.Options[translateHash]) && s(`.${translateHash}`))
20
+ htmls(
21
+ `.${translateHash}`,
22
+ this.Options[translateHash]?.disableTextFormat
23
+ ? this.Token[translateHash][lang]
24
+ : textFormatted(this.Token[translateHash][lang]),
25
+ );
20
26
  else if ('placeholder' in this.Token[translateHash] && s(this.Token[translateHash].placeholder))
21
- s(this.Token[translateHash].placeholder).placeholder = textFormatted(this.Token[translateHash][lang]);
27
+ s(this.Token[translateHash].placeholder).placeholder = this.Options[translateHash]?.disableTextFormat
28
+ ? this.Token[translateHash][lang]
29
+ : textFormatted(this.Token[translateHash][lang]);
22
30
  }
23
31
  });
24
32
  for (const keyEvent of Object.keys(this.Event)) this.Event[keyEvent]();
25
33
  },
26
- Render: function (keyLang, placeholder) {
34
+ Render: function (keyLang, placeholder, options = { disableTextFormat: false }) {
27
35
  if (!(keyLang in this.Data)) {
28
36
  // TODO: add translate package or library for this case
29
37
  logger.warn('translate key lang does not exist: ', keyLang);
30
- return textFormatted(keyLang);
38
+ return options.disableTextFormat ? keyLang : textFormatted(keyLang);
31
39
  }
32
40
  if (placeholder) this.Data[keyLang].placeholder = placeholder;
33
41
  keyLang = this.Data[keyLang];
34
42
  const translateHash = getId(this.Token, 'trans');
43
+ this.Options[translateHash] = options;
35
44
  this.Token[translateHash] = newInstance(keyLang);
36
45
  if ('placeholder' in keyLang) {
37
- if (s('html').lang in keyLang) return textFormatted(keyLang[s('html').lang]);
38
- return textFormatted(keyLang['en']);
46
+ if (s('html').lang in keyLang)
47
+ return options.disableTextFormat ? keyLang[s('html').lang] : textFormatted(keyLang[s('html').lang]);
48
+ return options.disableTextFormat ? keyLang['en'] : textFormatted(keyLang['en']);
39
49
  }
40
50
  if (s('html').lang in keyLang)
41
- return html`<span class="${translateHash}">${textFormatted(keyLang[s('html').lang])}</span>`;
42
- return html`<span class="${translateHash}">${textFormatted(keyLang['en'])}</span>`;
51
+ return html`<span class="${translateHash}"
52
+ >${options.disableTextFormat ? keyLang[s('html').lang] : textFormatted(keyLang[s('html').lang])}</span
53
+ >`;
54
+ return html`<span class="${translateHash}"
55
+ >${options.disableTextFormat ? keyLang['en'] : textFormatted(keyLang['en'])}</span
56
+ >`;
43
57
  },
44
58
  renderLang: function (language) {
45
59
  localStorage.setItem('lang', language);
@@ -474,6 +488,30 @@ const TranslateCore = {
474
488
  Translate.Data['friday'] = { es: 'Viernes', en: 'Friday' };
475
489
  Translate.Data['saturday'] = { es: 'Sábado', en: 'Saturday' };
476
490
  Translate.Data['sunday'] = { es: 'Domingo', en: 'Sunday' };
491
+
492
+ Translate.Data['description'] = { es: 'Descripción', en: 'Description' };
493
+ Translate.Data['daysOfWeek'] = { es: 'Días de la semana', en: 'Days of the week' };
494
+ Translate.Data['startTime'] = { es: 'Hora de inicio', en: 'Start time' };
495
+ Translate.Data['endTime'] = { es: 'Hora de finalizacion', en: 'End time' };
496
+ Translate.Data['appointment-scheduled'] = {
497
+ en: 'Your appointment has been scheduled',
498
+ es: 'Tu cita ha sido programada',
499
+ };
500
+ Translate.Data['info'] = { es: 'Información', en: 'Info' };
501
+ Translate.Data['complete-name'] = { es: 'Nombre completo', en: 'Complete name' };
502
+ Translate.Data['identityDocument'] = { es: 'Rut', en: 'Identity document' };
503
+ Translate.Data['day'] = { es: 'Día', en: 'Day' };
504
+ Translate.Data['month'] = { es: 'Mes', en: 'Month' };
505
+ Translate.Data['year'] = { es: 'Año', en: 'Year' };
506
+ Translate.Data['phone'] = { es: 'Teléfono', en: 'Phone' };
507
+ Translate.Data['invalid-identity-document'] = {
508
+ en: 'Invalid identity document',
509
+ es: 'Documento de identidad inválido',
510
+ };
511
+ Translate.Data['expired-session'] = {
512
+ en: 'Your session has expired. Please log in again.',
513
+ es: 'Su sesión ha expirado. Por favor, inicie sesión de nuevo.',
514
+ };
477
515
  },
478
516
  };
479
517
 
@@ -1,4 +1,4 @@
1
- import { validatePassword } from './CommonJs.js';
1
+ import { isChileanIdentityDocument, validatePassword } from './CommonJs.js';
2
2
  import { renderStatus } from './Css.js';
3
3
  import { loggerFactory } from './Logger.js';
4
4
  import { textFormatted, Translate } from './Translate.js';
@@ -58,6 +58,14 @@ const Validator = {
58
58
  if (!validator.isLength(s(`.${validatorData.id}`).value, rule.options))
59
59
  errorMessage += this.renderErrorMessage(rule);
60
60
  break;
61
+
62
+ case 'isChileanIdentityDocument': {
63
+ if (!isChileanIdentityDocument(s(`.${validatorData.id}`).value)) {
64
+ errorMessage += this.renderErrorMessage(undefined, Translate.Render('invalid-identity-document'));
65
+ }
66
+
67
+ break;
68
+ }
61
69
  default:
62
70
  if (
63
71
  validator[rule.type] &&
@@ -419,14 +419,6 @@ const isActiveTab = () => document.hasFocus();
419
419
  const isActiveElement = (classSearch = '') =>
420
420
  document.activeElement?.classList?.value?.match(classSearch) ? true : false;
421
421
 
422
- const getCurrentTrace = () => {
423
- try {
424
- _stack;
425
- } catch (error) {
426
- return error.stack.split('is not defined')[1];
427
- }
428
- };
429
-
430
422
  const isDevInstance = () => location.origin.match('localhost') && location.port;
431
423
 
432
424
  const getDataFromInputFile = async (file) => Array.from(new Uint8Array(await file.arrayBuffer()));
@@ -460,7 +452,6 @@ export {
460
452
  isNavigator,
461
453
  getTimeZone,
462
454
  getAllChildNodes,
463
- getCurrentTrace,
464
455
  isActiveTab,
465
456
  isActiveElement,
466
457
  isDevInstance,
@@ -22,41 +22,44 @@ const Worker = {
22
22
  setTimeout(() => {
23
23
  if ('onLine' in navigator && navigator.onLine) window.ononline();
24
24
  });
25
- navigator.serviceWorker.addEventListener('controllerchange', () => {
26
- logger.info('The controller of current browsing context has changed.');
27
- });
28
- navigator.serviceWorker.ready.then((worker) => {
29
- logger.info('Ready', worker);
30
- // event message
31
- navigator.serviceWorker.addEventListener('message', (event) => {
32
- logger.info('Received event message', event.data);
33
- const { status } = event.data;
25
+ if ('serviceWorker' in navigator) {
26
+ navigator.serviceWorker.addEventListener('controllerchange', () => {
27
+ logger.info('The controller of current browsing context has changed.');
28
+ });
29
+ navigator.serviceWorker.ready.then((worker) => {
30
+ logger.info('Ready', worker);
31
+ // event message
32
+ navigator.serviceWorker.addEventListener('message', (event) => {
33
+ logger.info('Received event message', event.data);
34
+ const { status } = event.data;
34
35
 
35
- switch (status) {
36
- case 'loader':
37
- {
38
- LoadingAnimation.RenderCurrentSrcLoad(event);
39
- }
40
- break;
36
+ switch (status) {
37
+ case 'loader':
38
+ {
39
+ LoadingAnimation.RenderCurrentSrcLoad(event);
40
+ }
41
+ break;
41
42
 
42
- default:
43
- break;
44
- }
45
- });
43
+ default:
44
+ break;
45
+ }
46
+ });
46
47
 
47
- // if (navigator.serviceWorker.controller)
48
- // navigator.serviceWorker.controller.postMessage({
49
- // title: 'Hello from Client event message',
50
- // });
48
+ // if (navigator.serviceWorker.controller)
49
+ // navigator.serviceWorker.controller.postMessage({
50
+ // title: 'Hello from Client event message',
51
+ // });
52
+
53
+ // broadcast message
54
+ // const channel = new BroadcastChannel('sw-messages');
55
+ // channel.addEventListener('message', (event) => {
56
+ // logger.info('Received broadcast message', event.data);
57
+ // });
58
+ // channel.postMessage({ title: 'Hello from Client broadcast message' });
59
+ // channel.close();
60
+ });
61
+ }
51
62
 
52
- // broadcast message
53
- // const channel = new BroadcastChannel('sw-messages');
54
- // channel.addEventListener('message', (event) => {
55
- // logger.info('Received broadcast message', event.data);
56
- // });
57
- // channel.postMessage({ title: 'Hello from Client broadcast message' });
58
- // channel.close();
59
- });
60
63
  this.RouterInstance = router();
61
64
  const isInstall = await this.status();
62
65
  if (!isInstall) await this.install();
@@ -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,6 +1,6 @@
1
1
  import { AgGrid } from '../../components/core/AgGrid.js';
2
2
  import { BtnIcon } from '../../components/core/BtnIcon.js';
3
- import { getId, timer } from '../../components/core/CommonJs.js';
3
+ import { getId, getValueFromJoinString, timer } from '../../components/core/CommonJs.js';
4
4
  import { darkTheme } from '../../components/core/Css.js';
5
5
  import { EventsUI } from '../../components/core/EventsUI.js';
6
6
  import { loggerFactory } from '../../components/core/Logger.js';
@@ -88,7 +88,9 @@ const DefaultManagement = {
88
88
  ${Translate.Render('confirm-delete-item')}
89
89
  ${Object.keys(params.data).length > 0
90
90
  ? html`<br />
91
- "${params.data[Object.keys(params.data)[0]]}"`
91
+ "${options.defaultColKeyFocus
92
+ ? getValueFromJoinString(params.data, options.defaultColKeyFocus)
93
+ : params.data[Object.keys(params.data)[0]]}"`
92
94
  : ''}
93
95
  </div>
94
96
  `;
@@ -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 = '${process.env.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">${process.env.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();
@@ -9,7 +9,12 @@ const MongooseDB = {
9
9
  connect: async (host, name) => {
10
10
  const uri = `${host}/${name}`;
11
11
  // logger.info('MongooseDB connect', { host, name, uri });
12
- return await mongoose.createConnection(uri).asPromise();
12
+ return await mongoose
13
+ .createConnection(uri, {
14
+ // useNewUrlParser: true,
15
+ // useUnifiedTopology: true,
16
+ })
17
+ .asPromise();
13
18
  return new Promise((resolve, reject) =>
14
19
  mongoose
15
20
  .connect(
@@ -67,8 +72,27 @@ const MongooseDB = {
67
72
  shellExec(`sudo rm -r /var/lib/mongodb`);
68
73
  // restore lib
69
74
  // shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb/*`);
75
+ // mongod --repair
70
76
 
71
77
  if (process.argv.includes('legacy')) {
78
+ // TODO:
79
+ if (process.argv.includes('rocky')) {
80
+ // https://github.com/mongodb/mongodb-selinux
81
+ // https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-enterprise-on-red-hat/
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
95
+ }
72
96
  logger.info('install legacy 4.4');
73
97
  shellExec(`wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -`);
74
98
 
@@ -100,9 +124,13 @@ const MongooseDB = {
100
124
  shellExec(`sudo systemctl unmask mongod`);
101
125
  shellExec(`sudo pkill -f mongod`);
102
126
  shellExec(`sudo systemctl enable mongod.service`);
127
+
103
128
  shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb`);
104
129
  shellExec(`sudo chown mongodb:mongodb /tmp/mongodb-27017.sock`);
105
130
 
131
+ shellExec(`sudo chown -R mongod:mongod /var/lib/mongodb`);
132
+ shellExec(`sudo chown mongod:mongod /tmp/mongodb-27017.sock`);
133
+
106
134
  logger.info('run server');
107
135
  shellExec(`sudo service mongod restart`);
108
136
 
package/src/index.js CHANGED
@@ -4,9 +4,17 @@
4
4
  * @namespace Underpost
5
5
  */
6
6
 
7
- import { loggerFactory, setUpInfo } from './server/logger.js';
8
-
9
- const logger = loggerFactory(import.meta);
7
+ import UnderpostCluster from './cli/cluster.js';
8
+ import UnderpostCron from './cli/cron.js';
9
+ import UnderpostDB from './cli/db.js';
10
+ import UnderpostDeploy from './cli/deploy.js';
11
+ import UnderpostRootEnv from './cli/env.js';
12
+ import UnderpostFileStorage from './cli/fs.js';
13
+ import UnderpostImage from './cli/image.js';
14
+ import UnderpostRepository from './cli/repository.js';
15
+ import UnderpostScript from './cli/script.js';
16
+ import UnderpostSecret from './cli/secrets.js';
17
+ import UnderpostTest from './cli/test.js';
10
18
 
11
19
  /**
12
20
  * Underpost main module methods
@@ -20,26 +28,84 @@ class Underpost {
20
28
  * @type {String}
21
29
  * @memberof Underpost
22
30
  */
23
- static version = 'v2.8.1';
24
-
25
- constructor() {}
26
-
31
+ static version = 'v2.8.6';
32
+ /**
33
+ * Repository cli API
34
+ * @static
35
+ * @type {UnderpostRepository.API}
36
+ * @memberof Underpost
37
+ */
38
+ static repo = UnderpostRepository.API;
39
+ /**
40
+ * Root Env cli API
41
+ * @static
42
+ * @type {UnderpostRootEnv.API}
43
+ * @memberof Underpost
44
+ */
45
+ static env = UnderpostRootEnv.API;
46
+ /**
47
+ * Test cli API
48
+ * @static
49
+ * @type {UnderpostTest.API}
50
+ * @memberof Underpost
51
+ */
52
+ static test = UnderpostTest.API;
53
+ /**
54
+ * Cluster cli API
55
+ * @static
56
+ * @type {UnderpostCluster.API}
57
+ * @memberof Underpost
58
+ */
59
+ static cluster = UnderpostCluster.API;
60
+ /**
61
+ * Image cli API
62
+ * @static
63
+ * @type {UnderpostImage.API}
64
+ * @memberof Underpost
65
+ */
66
+ static image = UnderpostImage.API;
67
+ /**
68
+ * Secrets cli API
69
+ * @static
70
+ * @type {UnderpostSecret.API}
71
+ * @memberof Underpost
72
+ */
73
+ static secret = UnderpostSecret.API;
27
74
  /**
28
- * Logs information about the current process environment to the console.
29
- *
30
- * This function is used to log details about
31
- * the execution context, such as command-line arguments,
32
- * environment variables, the process's administrative privileges,
33
- * and the maximum available heap space size.
34
- *
75
+ * Scripts cli API
35
76
  * @static
36
- * @method setUpInfo
37
- * @returns {Promise<void>}
77
+ * @type {UnderpostScript.API}
38
78
  * @memberof Underpost
39
79
  */
40
- static async setUpInfo() {
41
- return await setUpInfo(logger);
42
- }
80
+ static script = UnderpostScript.API;
81
+ /**
82
+ * Database cli API
83
+ * @static
84
+ * @type {UnderpostDB.API}
85
+ * @memberof Underpost
86
+ */
87
+ static db = UnderpostDB.API;
88
+ /**
89
+ * Deployment cli API
90
+ * @static
91
+ * @type {UnderpostDeploy.API}
92
+ * @memberof Underpost
93
+ */
94
+ static deploy = UnderpostDeploy.API;
95
+ /**
96
+ * Cron cli API
97
+ * @static
98
+ * @type {UnderpostCron.API}
99
+ * @memberof Underpost
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;
43
109
  }
44
110
 
45
111
  const up = Underpost;
@@ -1,5 +1,4 @@
1
1
  import fs from 'fs-extra';
2
- import { network } from '../../server/network.js';
3
2
  import { shellCd, shellExec } from '../../server/process.js';
4
3
  import { timer } from '../../client/components/core/CommonJs.js';
5
4
  import { loggerFactory } from '../../server/logger.js';
@@ -39,20 +38,9 @@ const Lampp = {
39
38
  );
40
39
 
41
40
  shellExec(cmd);
42
- await network.port.portClean(3306);
43
- for (const port of this.ports) await network.port.portClean(port);
44
41
  cmd = `sudo /opt/lampp/lampp start`;
45
42
  if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
46
- shellExec(cmd, { async: true });
47
- if (options && options.daemon) this.daemon();
48
- },
49
- daemon: async function () {
50
- await timer(1000 * 60 * 2); // 2 minutes
51
- for (const port of this.ports) {
52
- const [portStatus] = await network.port.status([port]);
53
- if (!portStatus.open) return await this.initService();
54
- }
55
- this.daemon();
43
+ shellExec(cmd);
56
44
  },
57
45
  enabled: () => fs.existsSync(`/opt/lampp/apache2/conf/httpd.conf`),
58
46
  appendRouter: function (render) {
@@ -1,7 +1,5 @@
1
1
  import fs from 'fs-extra';
2
- import { network } from '../../server/network.js';
3
2
  import { shellExec } from '../../server/process.js';
4
- import { timer } from '../../client/components/core/CommonJs.js';
5
3
 
6
4
  const Xampp = {
7
5
  ports: [],
@@ -16,20 +14,9 @@ const Xampp = {
16
14
  fs.writeFileSync(`C:/xampp/apache/conf/extra/httpd-ssl.conf`, this.router || '', 'utf8');
17
15
  cmd = `C:/xampp/xampp_stop.exe`;
18
16
  shellExec(cmd);
19
- await network.port.portClean(3306);
20
- for (const port of this.ports) await network.port.portClean(port);
21
17
  cmd = `C:/xampp/xampp_start.exe`;
22
18
  if (this.router) fs.writeFileSync(`./tmp/xampp-router.conf`, this.router, 'utf-8');
23
19
  shellExec(cmd);
24
- if (options && options.daemon) this.daemon();
25
- },
26
- daemon: async function () {
27
- await timer(1000 * 60 * 2); // 2 minutes
28
- for (const port of this.ports) {
29
- const [portStatus] = await network.port.status([port]);
30
- if (!portStatus.open) return await this.initService();
31
- }
32
- this.daemon();
33
20
  },
34
21
  enabled: () => fs.existsSync(`C:/xampp/apache/conf/httpd.conf`),
35
22
  appendRouter: function (render) {
@@ -9,7 +9,7 @@ import jwt from 'jsonwebtoken';
9
9
  import { loggerFactory } from './logger.js';
10
10
  import crypto from 'crypto';
11
11
  import { userRoleEnum } from '../api/user/user.model.js';
12
- import { validatePassword } from '../client/components/core/CommonJs.js';
12
+ import { commonAdminGuard, commonModeratorGuard, validatePassword } from '../client/components/core/CommonJs.js';
13
13
 
14
14
  dotenv.config();
15
15
 
@@ -162,7 +162,7 @@ const authMiddleware = (req, res, next) => {
162
162
  */
163
163
  const adminGuard = (req, res, next) => {
164
164
  try {
165
- if (!(userRoleEnum.indexOf(req.auth.user.role) === userRoleEnum.indexOf('admin')))
165
+ if (!commonAdminGuard(req.auth.user.role))
166
166
  return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
167
167
  return next();
168
168
  } catch (error) {
@@ -194,7 +194,7 @@ const adminGuard = (req, res, next) => {
194
194
  */
195
195
  const moderatorGuard = (req, res, next) => {
196
196
  try {
197
- if (!(userRoleEnum.indexOf(req.auth.user.role) <= userRoleEnum.indexOf('moderator')))
197
+ if (!commonModeratorGuard(req.auth.user.role))
198
198
  return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
199
199
  return next();
200
200
  } catch (error) {