@underpostnet/underpost 2.7.83 → 2.7.92

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 (85) hide show
  1. package/.github/workflows/ghpkg.yml +41 -1
  2. package/.github/workflows/pwa-microservices-template.page.yml +54 -0
  3. package/.vscode/settings.json +7 -0
  4. package/CHANGELOG.md +64 -16
  5. package/bin/cron.js +47 -0
  6. package/bin/db.js +60 -7
  7. package/bin/deploy.js +358 -26
  8. package/bin/file.js +18 -1
  9. package/bin/hwt.js +59 -0
  10. package/bin/index.js +1 -1
  11. package/bin/util.js +31 -1
  12. package/conf.js +46 -8
  13. package/docker-compose.yml +1 -1
  14. package/package.json +4 -4
  15. package/src/api/core/core.router.js +9 -9
  16. package/src/api/core/core.service.js +12 -4
  17. package/src/api/default/default.service.js +4 -4
  18. package/src/api/file/file.service.js +3 -3
  19. package/src/api/user/user.service.js +10 -8
  20. package/src/client/components/core/404.js +20 -0
  21. package/src/client/components/core/500.js +20 -0
  22. package/src/client/{ssr/common → components/core}/Alert.js +13 -11
  23. package/src/client/components/core/CommonJs.js +3 -0
  24. package/src/client/components/core/CssCore.js +30 -3
  25. package/src/client/components/core/Docs.js +110 -10
  26. package/src/client/components/core/LoadingAnimation.js +4 -2
  27. package/src/client/components/core/Modal.js +223 -22
  28. package/src/client/components/core/Panel.js +1 -1
  29. package/src/client/components/core/PanelForm.js +2 -1
  30. package/src/client/components/core/Responsive.js +34 -5
  31. package/src/client/components/core/RichText.js +4 -2
  32. package/src/client/components/core/Translate.js +21 -5
  33. package/src/client/components/core/VanillaJs.js +2 -1
  34. package/src/client/components/core/WebComponent.js +44 -0
  35. package/src/client/components/core/Worker.js +15 -18
  36. package/src/client/components/default/MenuDefault.js +68 -0
  37. package/src/client/components/default/RoutesDefault.js +2 -0
  38. package/src/client/public/default/plantuml/client-conf.svg +1 -1
  39. package/src/client/public/default/plantuml/client-schema.svg +1 -1
  40. package/src/client/public/default/plantuml/cron-conf.svg +1 -1
  41. package/src/client/public/default/plantuml/cron-schema.svg +1 -1
  42. package/src/client/public/default/plantuml/server-conf.svg +1 -1
  43. package/src/client/public/default/plantuml/server-schema.svg +1 -1
  44. package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
  45. package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
  46. package/src/client/public/default/site.webmanifest +69 -0
  47. package/src/client/ssr/Render.js +1 -6
  48. package/src/client/ssr/{components/body → body}/CacheControl.js +1 -1
  49. package/src/client/ssr/head/Production.js +1 -0
  50. package/src/client/ssr/head/Pwa.js +146 -0
  51. package/src/client/ssr/head/Seo.js +14 -0
  52. package/src/client/ssr/mailer/DefaultRecoverEmail.js +21 -0
  53. package/src/client/ssr/mailer/DefaultVerifyEmail.js +17 -0
  54. package/src/client/ssr/offline/NoNetworkConnection.js +65 -0
  55. package/src/client/ssr/pages/Test.js +196 -0
  56. package/src/client/ssr/pages/maintenance.js +14 -0
  57. package/src/client/ssr/pages/offline.js +21 -0
  58. package/src/client/sw/default.sw.js +44 -165
  59. package/src/db/DataBaseProvider.js +12 -1
  60. package/src/db/mongo/MongooseDB.js +0 -1
  61. package/src/mailer/EmailRender.js +2 -4
  62. package/src/mailer/MailerProvider.js +4 -1
  63. package/src/runtime/lampp/Lampp.js +9 -9
  64. package/src/server/backup.js +82 -70
  65. package/src/server/client-build.js +133 -155
  66. package/src/server/client-formatted.js +2 -4
  67. package/src/server/conf.js +114 -23
  68. package/src/server/crypto.js +91 -0
  69. package/src/server/dns.js +48 -16
  70. package/src/server/network.js +94 -7
  71. package/src/server/proxy.js +26 -28
  72. package/src/server/runtime.js +42 -12
  73. package/src/server/ssl.js +2 -2
  74. package/src/client/ssr/common/SsrCore.js +0 -91
  75. package/src/client/ssr/common/Translate.js +0 -26
  76. package/src/client/ssr/common/Worker.js +0 -28
  77. package/src/client/ssr/components/head/PwaDefault.js +0 -60
  78. package/src/client/ssr/offline/default.index.js +0 -31
  79. package/src/cron.js +0 -30
  80. package/src/server/cron.js +0 -35
  81. /package/src/client/ssr/{components/body → body}/DefaultSplashScreen.js +0 -0
  82. /package/src/client/ssr/{components/email → email}/DefaultRecoverEmail.js +0 -0
  83. /package/src/client/ssr/{components/email → email}/DefaultVerifyEmail.js +0 -0
  84. /package/src/client/ssr/{components/head → head}/Css.js +0 -0
  85. /package/src/client/ssr/{components/head → head}/DefaultScripts.js +0 -0
@@ -1,6 +1,9 @@
1
1
  import { newInstance } from './CommonJs.js';
2
+ import { loggerFactory } from './Logger.js';
2
3
  import { getResponsiveData } from './VanillaJs.js';
3
4
 
5
+ const logger = loggerFactory(import.meta);
6
+
4
7
  const Responsive = {
5
8
  Data: {},
6
9
  Event: {},
@@ -18,9 +21,9 @@ const Responsive = {
18
21
  ResponsiveDataAmplitude.height = ResponsiveDataAmplitude.height * dimAmplitude;
19
22
  return ResponsiveDataAmplitude;
20
23
  },
21
- resizeCallback: function () {
24
+ resizeCallback: function (force) {
22
25
  const Data = getResponsiveData();
23
- if (Data.minValue !== Responsive.Data.minValue || Data.maxValue !== Responsive.Data.maxValue) {
26
+ if (force === true || Data.minValue !== Responsive.Data.minValue || Data.maxValue !== Responsive.Data.maxValue) {
24
27
  Responsive.Data = Data;
25
28
  Responsive.triggerEvents();
26
29
  }
@@ -28,13 +31,13 @@ const Responsive = {
28
31
  resize: 0,
29
32
  Init: async function () {
30
33
  Responsive.resizeCallback();
31
- window.onresize = () => {
34
+ window.onresize = (e, force) => {
32
35
  Responsive.resize++;
33
36
  const resize = Responsive.resize;
34
- Responsive.resizeCallback();
37
+ Responsive.resizeCallback(force);
35
38
  setTimeout(() => {
36
39
  if (resize === Responsive.resize) {
37
- Responsive.resizeCallback();
40
+ Responsive.resizeCallback(force);
38
41
  Responsive.resize = 0;
39
42
  for (const event of Object.keys(Responsive.DelayEvent)) Responsive.DelayEvent[event]();
40
43
  }
@@ -43,11 +46,37 @@ const Responsive = {
43
46
  // alternative option
44
47
  // this.Observer = new ResizeObserver(this.resizeCallback);
45
48
  // this.Observer.observe(document.documentElement);
49
+ screen.orientation.addEventListener('change', (event) => {
50
+ const type = event.target.type; // landscape-primary | portrait-primary
51
+ const angle = event.target.angle; // 90 degrees.
52
+ logger.info(`ScreenOrientation change: ${type}, ${angle} degrees.`);
53
+ setTimeout(() => window.onresize({}, true));
54
+ Responsive.triggerEventsOrientation();
55
+ });
56
+ Responsive.matchMediaOrientationInstance = matchMedia('screen and (orientation:portrait)');
57
+
58
+ Responsive.matchMediaOrientationInstance.onchange = (e) => {
59
+ console.log('orientation change', Responsive.matchMediaOrientationInstance.matches ? 'portrait' : 'landscape');
60
+ // though beware square will be marked as landscape here,
61
+ // if you want to handle this special case
62
+ // create an other mediaquery (orientation:landscape)
63
+ setTimeout(() => window.onresize({}, true));
64
+ Responsive.triggerEventsOrientation();
65
+ };
66
+ },
67
+ triggerEventsOrientation: function () {
68
+ for (const event of Object.keys(this.orientationEvent)) this.orientationEvent[event]();
69
+ setTimeout(() => {
70
+ window.onresize();
71
+ for (const event of Object.keys(this.orientationDelayEvent)) this.orientationDelayEvent[event]();
72
+ }, 1500);
46
73
  },
47
74
  triggerEvents: function (keyEvent) {
48
75
  if (keyEvent) return this.Event[keyEvent]();
49
76
  return Object.keys(this.Event).map((key) => this.Event[key]());
50
77
  },
78
+ orientationEvent: {},
79
+ orientationDelayEvent: {},
51
80
  };
52
81
 
53
82
  export { Responsive };
@@ -20,14 +20,16 @@ const RichText = {
20
20
  s(`.${options.parentIdModal}`).style.top = '0px';
21
21
  s(`.${options.parentIdModal}`).style.height = `${window.innerHeight}px`;
22
22
  }
23
- Modal.cleanUI();
23
+ // Modal.cleanUI();
24
+ if (s(`.slide-menu-top-bar`)) s(`.slide-menu-top-bar`).classList.add('hide');
24
25
  } else {
25
26
  if (options.parentIdModal) {
26
27
  s(`.btn-bar-modal-container-${options.parentIdModal}`).classList.remove('hide');
27
28
  s(`.${options.parentIdModal}`).style.top = top;
28
29
  s(`.${options.parentIdModal}`).style.height = height;
29
30
  }
30
- Modal.restoreUI();
31
+ if (s(`.slide-menu-top-bar`)) s(`.slide-menu-top-bar`).classList.add('remove');
32
+ // Modal.restoreUI();
31
33
  }
32
34
  },
33
35
  });
@@ -66,11 +66,7 @@ const Translate = {
66
66
 
67
67
  const TranslateCore = {
68
68
  Init: async function () {
69
- s('html').lang = localStorage.getItem('lang')
70
- ? localStorage.getItem('lang')
71
- : getLang() && getLang().match('es')
72
- ? 'es'
73
- : 'en';
69
+ s('html').lang = getLang();
74
70
  Translate.Data = {
75
71
  ...Translate.Data,
76
72
  isEmpty: {
@@ -252,6 +248,26 @@ const TranslateCore = {
252
248
  en: 'Comments',
253
249
  es: 'Comentarios',
254
250
  },
251
+ ['server-maintenance']: {
252
+ en: "The server is under maintenance <br> we'll be back soon.",
253
+ es: 'El servidor está en mantenimiento <br> volveremos pronto.',
254
+ },
255
+ ['no-internet-connection']: {
256
+ en: 'No internet connection <br> verify your network',
257
+ es: 'Sin conexión a internet <br> verifica tu red',
258
+ },
259
+ ['page-not-found']: {
260
+ en: 'Page not found',
261
+ es: 'Página no encontrada',
262
+ },
263
+ ['page-broken']: {
264
+ es: 'Algo salio mal',
265
+ en: 'Something went wrong',
266
+ },
267
+ ['back']: {
268
+ en: 'Back to <br> homepage',
269
+ es: 'Volver a <br> la pagina principal',
270
+ },
255
271
  },
256
272
  };
257
273
  Translate.Data['warning-upload-no-selects-file'] = {
@@ -428,7 +428,8 @@ const isDevInstance = () => location.origin.match('localhost') && location.port;
428
428
 
429
429
  const getDataFromInputFile = async (file) => Array.from(new Uint8Array(await file.arrayBuffer()));
430
430
 
431
- const getLang = () => navigator.language || navigator.userLanguage;
431
+ const getLang = () =>
432
+ (localStorage.getItem('lang') || navigator.language || navigator.userLanguage || s('html').lang).slice(0, 2);
432
433
 
433
434
  export {
434
435
  s,
@@ -0,0 +1,44 @@
1
+ // https://javascript.info/
2
+ // https://javascript.info/web-components
3
+
4
+ class MyElement extends HTMLElement {
5
+ constructor() {
6
+ super();
7
+ // element created
8
+ }
9
+
10
+ connectedCallback() {
11
+ // browser calls this method when the element is added to the document
12
+ // (can be called many times if an element is repeatedly added/removed)
13
+ }
14
+
15
+ disconnectedCallback() {
16
+ // browser calls this method when the element is removed from the document
17
+ // (can be called many times if an element is repeatedly added/removed)
18
+ }
19
+
20
+ static get observedAttributes() {
21
+ return [
22
+ /* array of attribute names to monitor for changes */
23
+ ];
24
+ }
25
+
26
+ attributeChangedCallback(name, oldValue, newValue) {
27
+ // called when one of attributes listed above is modified
28
+ }
29
+
30
+ adoptedCallback() {
31
+ // called when the element is moved to a new document
32
+ // (happens in document.adoptNode, very rarely used)
33
+ }
34
+
35
+ // there can be other element methods and properties
36
+ }
37
+
38
+ customElements.define('my-element', MyElement);
39
+
40
+ // Now for any HTML elements with tag <my-element>,
41
+ // an instance of MyElement is created, and the aforementioned
42
+ // methods are called.
43
+
44
+ export { MyElement };
@@ -13,6 +13,15 @@ const Worker = {
13
13
  devMode: () => location.origin.match('localhost') || location.origin.match('127.0.0.1'),
14
14
  instance: async function ({ router, render }) {
15
15
  logger.warn('Init');
16
+ window.ononline = async () => {
17
+ logger.warn('ononline');
18
+ };
19
+ window.onoffline = async () => {
20
+ logger.warn('onoffline');
21
+ };
22
+ setTimeout(() => {
23
+ if ('onLine' in navigator && navigator.onLine) window.ononline();
24
+ });
16
25
  navigator.serviceWorker.addEventListener('controllerchange', () => {
17
26
  logger.info('The controller of current browsing context has changed.');
18
27
  });
@@ -48,11 +57,9 @@ const Worker = {
48
57
  // channel.postMessage({ title: 'Hello from Client broadcast message' });
49
58
  // channel.close();
50
59
  });
60
+ this.RouterInstance = router();
51
61
  const isInstall = await this.status();
52
62
  if (!isInstall) await this.install();
53
- else await this.update();
54
- // else if (location.hostname === 'localhost') await this.update();
55
- this.RouterInstance = router();
56
63
  await render();
57
64
  LoadRouter(this.RouterInstance);
58
65
  LoadingAnimation.removeSplashScreen();
@@ -61,9 +68,9 @@ const Worker = {
61
68
  // Dev mode
62
69
 
63
70
  window.addEventListener('visibilitychange', (event) => {
64
- if (document.visibilityState === 'visible') {
65
- Worker.reload(delayLiveReload);
66
- }
71
+ // if (document.visibilityState === 'visible') {
72
+ // Worker.reload(delayLiveReload);
73
+ // }
67
74
  });
68
75
  window.addEventListener('focus', function () {
69
76
  // Worker.reload(delayLiveReload);
@@ -90,21 +97,11 @@ const Worker = {
90
97
  if (isInstall) {
91
98
  const cacheNames = await caches.keys();
92
99
  for (const cacheName of cacheNames) {
93
- if (
94
- cacheName.match('components/') ||
95
- cacheName.match('services/') ||
96
- cacheName.match('.index.js') ||
97
- cacheName.match('offline.')
98
- ) {
100
+ if (cacheName.match('components/') || cacheName.match('services/') || cacheName.match('.index.js')) {
99
101
  await caches.delete(cacheName);
100
102
  }
101
103
  }
102
104
  await this.updateServiceWorker();
103
- try {
104
- await fetch('/offline.html');
105
- } catch (error) {
106
- logger.error('error');
107
- }
108
105
  }
109
106
  },
110
107
  updateServiceWorker: async function () {},
@@ -143,7 +140,7 @@ const Worker = {
143
140
  return new Promise((resolve, reject) => {
144
141
  if ('serviceWorker' in navigator) {
145
142
  navigator.serviceWorker
146
- .register(`/sw.js`, {
143
+ .register(`${getProxyPath()}sw.js`, {
147
144
  // scope: getProxyPath(),
148
145
  // scope: '/',
149
146
  type: 'module',
@@ -17,6 +17,8 @@ import { Badge } from '../core/Badge.js';
17
17
  import { Docs } from '../core/Docs.js';
18
18
  import { Recover } from '../core/Recover.js';
19
19
  import { DefaultManagement } from '../../services/default/default.management.js';
20
+ import { Page500 } from '../core/500.js';
21
+ import { Page404 } from '../core/404.js';
20
22
 
21
23
  const MenuDefault = {
22
24
  Data: {},
@@ -136,6 +138,28 @@ const MenuDefault = {
136
138
  handleContainerClass: 'handle-btn-container',
137
139
  tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('default-management')),
138
140
  })}
141
+ ${await BtnIcon.Render({
142
+ class: 'in wfa main-btn-menu main-btn-404 hide',
143
+ label: renderMenuLabel({
144
+ icon: html`<i class="fa-solid fa-triangle-exclamation"></i>`,
145
+ text: html`<span class="menu-label-text">${Translate.Render('404')}</span>`,
146
+ }),
147
+ attrs: `data-id="404"`,
148
+ tabHref: `${getProxyPath()}404`,
149
+ handleContainerClass: 'handle-btn-container',
150
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('404')),
151
+ })}
152
+ ${await BtnIcon.Render({
153
+ class: 'in wfa main-btn-menu main-btn-500 hide',
154
+ label: renderMenuLabel({
155
+ icon: html`<i class="fa-solid fa-circle-exclamation"></i>`,
156
+ text: html`<span class="menu-label-text">${Translate.Render('500')}</span>`,
157
+ }),
158
+ attrs: `data-id="500"`,
159
+ tabHref: `${getProxyPath()}500`,
160
+ handleContainerClass: 'handle-btn-container',
161
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('500')),
162
+ })}
139
163
  </div>
140
164
  `,
141
165
  barConfig: newInstance(barConfig),
@@ -383,6 +407,50 @@ const MenuDefault = {
383
407
  heightBottomBar,
384
408
  });
385
409
  });
410
+
411
+ EventsUI.onClick(`.main-btn-404`, async () => {
412
+ const { barConfig } = await Themes[Css.currentTheme]();
413
+ await Modal.Render({
414
+ id: 'modal-404',
415
+ route: '404',
416
+ barConfig,
417
+ title: renderViewTitle({
418
+ icon: html`<i class="fa-solid fa-triangle-exclamation"></i>`,
419
+ text: Translate.Render('404'),
420
+ }),
421
+ html: async () => await Page404.Render({ idModal: 'modal-404' }),
422
+ handleType: 'bar',
423
+ maximize: true,
424
+ mode: 'view',
425
+ slideMenu: 'modal-menu',
426
+ RouterInstance,
427
+ heightTopBar,
428
+ heightBottomBar,
429
+ observer: true,
430
+ });
431
+ });
432
+
433
+ EventsUI.onClick(`.main-btn-500`, async () => {
434
+ const { barConfig } = await Themes[Css.currentTheme]();
435
+ await Modal.Render({
436
+ id: 'modal-500',
437
+ route: '500',
438
+ barConfig,
439
+ title: renderViewTitle({
440
+ icon: html`<i class="fa-solid fa-circle-exclamation"></i>`,
441
+ text: Translate.Render('500'),
442
+ }),
443
+ html: async () => await Page500.Render({ idModal: 'modal-500' }),
444
+ handleType: 'bar',
445
+ maximize: true,
446
+ mode: 'view',
447
+ slideMenu: 'modal-menu',
448
+ RouterInstance,
449
+ heightTopBar,
450
+ heightBottomBar,
451
+ observer: true,
452
+ });
453
+ });
386
454
  },
387
455
  };
388
456
 
@@ -36,6 +36,8 @@ const RoutesDefault = () => {
36
36
  render: () => s(`.main-btn-default-management`).click(),
37
37
  translateTitle: true,
38
38
  },
39
+ '/404': { title: '404 Not Found', render: () => s(`.main-btn-404`).click() },
40
+ '/500': { title: '500 Server Error', render: () => s(`.main-btn-500`).click() },
39
41
  };
40
42
  };
41
43