underpost 2.8.85 → 2.8.87

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 (70) hide show
  1. package/.env.development +7 -2
  2. package/.env.production +7 -2
  3. package/.env.test +7 -2
  4. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -1
  5. package/.github/workflows/release.cd.yml +37 -0
  6. package/README.md +7 -24
  7. package/bin/build.js +1 -0
  8. package/bin/db.js +1 -3
  9. package/bin/deploy.js +43 -368
  10. package/bin/file.js +16 -3
  11. package/bin/util.js +1 -56
  12. package/cli.md +46 -21
  13. package/conf.js +3 -3
  14. package/manifests/deployment/{dd-template-development → dd-default-development}/deployment.yaml +16 -16
  15. package/manifests/deployment/{dd-template-development → dd-default-development}/proxy.yaml +3 -3
  16. package/manifests/deployment/mongo-express/deployment.yaml +12 -12
  17. package/manifests/grafana/deployment.yaml +57 -0
  18. package/manifests/grafana/kustomization.yaml +7 -0
  19. package/manifests/grafana/pvc.yaml +12 -0
  20. package/manifests/grafana/service.yaml +14 -0
  21. package/manifests/maas/nvim.sh +91 -0
  22. package/manifests/maas/ssh-cluster-info.sh +14 -0
  23. package/manifests/prometheus/deployment.yaml +82 -0
  24. package/package.json +3 -12
  25. package/src/api/file/file.service.js +28 -8
  26. package/src/api/user/user.router.js +31 -5
  27. package/src/api/user/user.service.js +11 -38
  28. package/src/cli/cluster.js +45 -25
  29. package/src/cli/cron.js +12 -45
  30. package/src/cli/db.js +149 -19
  31. package/src/cli/deploy.js +41 -110
  32. package/src/cli/fs.js +1 -0
  33. package/src/cli/index.js +24 -7
  34. package/src/cli/monitor.js +1 -4
  35. package/src/cli/repository.js +15 -6
  36. package/src/cli/run.js +94 -16
  37. package/src/client/Default.index.js +0 -2
  38. package/src/client/components/core/Account.js +6 -2
  39. package/src/client/components/core/Content.js +11 -7
  40. package/src/client/components/core/Css.js +5 -1
  41. package/src/client/components/core/CssCore.js +12 -0
  42. package/src/client/components/core/FullScreen.js +19 -28
  43. package/src/client/components/core/Input.js +7 -1
  44. package/src/client/components/core/LogIn.js +3 -0
  45. package/src/client/components/core/LogOut.js +1 -1
  46. package/src/client/components/core/Modal.js +32 -43
  47. package/src/client/components/core/ObjectLayerEngine.js +229 -4
  48. package/src/client/components/core/ObjectLayerEngineModal.js +441 -0
  49. package/src/client/components/core/Recover.js +5 -2
  50. package/src/client/components/core/Scroll.js +65 -120
  51. package/src/client/components/core/SignUp.js +1 -0
  52. package/src/client/components/core/ToggleSwitch.js +15 -1
  53. package/src/client/components/core/VanillaJs.js +48 -2
  54. package/src/client/components/default/MenuDefault.js +2 -2
  55. package/src/client/components/default/RoutesDefault.js +3 -3
  56. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  57. package/src/index.js +1 -1
  58. package/src/mailer/MailerProvider.js +37 -0
  59. package/src/server/client-build-docs.js +1 -1
  60. package/src/server/client-build-live.js +1 -1
  61. package/src/server/client-build.js +4 -12
  62. package/src/server/client-dev-server.js +1 -1
  63. package/src/server/client-icons.js +6 -78
  64. package/src/server/conf.js +83 -408
  65. package/src/server/proxy.js +2 -3
  66. package/src/server/runtime.js +1 -2
  67. package/src/server/start.js +5 -5
  68. package/test/api.test.js +3 -2
  69. package/docker-compose.yml +0 -67
  70. package/prometheus.yml +0 -36
@@ -67,7 +67,7 @@ const ToggleSwitch = {
67
67
 
68
68
  if (options.type === 'checkbox') {
69
69
  }
70
- return html`
70
+ const htmlRender = html`
71
71
  ${options?.displayMode === 'checkbox'
72
72
  ? html`<div class="${options?.containerClass ? options.containerClass : 'inl box-content-border'} ${id}">
73
73
  <div class="in ${id}-content toggle-switch-content-checkbox">
@@ -81,6 +81,20 @@ const ToggleSwitch = {
81
81
  </div>`}
82
82
  <input type="checkbox" class="${id}-checkbox" style="display: none" />
83
83
  `;
84
+ if (options.wrapper) {
85
+ setTimeout(() => (s(`.toggle-form-container-${id}`).onclick = () => ToggleSwitch.Tokens[`${id}`].click()));
86
+ return html`
87
+ <div class="in toggle-form-container toggle-form-container-${id} hover">
88
+ <div class="fl ">
89
+ <div class="in fll" style="width: 70%">
90
+ <div class="in">${options.wrapperLabel}</div>
91
+ </div>
92
+ <div class="in fll" style="width: 30%">${htmlRender}</div>
93
+ </div>
94
+ </div>
95
+ `;
96
+ }
97
+ return htmlRender;
84
98
  },
85
99
  };
86
100
 
@@ -147,8 +147,40 @@ const pasteData = () => new Promise((resolve) => navigator.clipboard.readText().
147
147
  * @memberof VanillaJS
148
148
  */
149
149
  const setPath = (path = '/', stateStorage = {}, title = '') => {
150
- if (window.location.pathname === path || window.location.pathname === `${path}/`) return;
151
- return history.pushState(stateStorage, title, path);
150
+ if (!path) path = '/';
151
+
152
+ const [inputPath, inputSearch] = `${path}`.split('?');
153
+
154
+ let sanitizedPath = (inputPath[0] !== '/' ? `/${inputPath}` : inputPath)
155
+ .trim()
156
+ .replaceAll('//', '/')
157
+ .replaceAll(`\\`, '/');
158
+
159
+ if (sanitizedPath.length > 1 && sanitizedPath[sanitizedPath.length - 1] === '/')
160
+ sanitizedPath = sanitizedPath.slice(0, -1);
161
+
162
+ if (window.location.pathname === sanitizedPath && (!inputSearch || inputSearch === location.search)) {
163
+ console.warn('Prevent overwriting same path', {
164
+ inputPath: inputPath,
165
+ inputSearch: inputSearch,
166
+ sanitizedPath: sanitizedPath,
167
+ currentLocationSearch: location.search,
168
+ currentLocationHash: location.hash,
169
+ });
170
+ return;
171
+ }
172
+ console.warn('Set path', {
173
+ inputPath: inputPath,
174
+ inputSearch: inputSearch,
175
+ sanitizedPath: sanitizedPath,
176
+ currentLocationSearch: location.search,
177
+ currentLocationHash: location.hash,
178
+ });
179
+ return history.pushState(
180
+ stateStorage,
181
+ title,
182
+ `${sanitizedPath}${inputSearch ? `?${inputSearch}` : ''}${location.hash ?? ''}`,
183
+ );
152
184
  };
153
185
 
154
186
  /**
@@ -425,6 +457,19 @@ const getLang = () =>
425
457
  .slice(0, 2)
426
458
  .toLowerCase();
427
459
 
460
+ function hexToRgbA(hex) {
461
+ let c;
462
+ if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
463
+ c = hex.substring(1).split('');
464
+ if (c.length == 3) {
465
+ c = [c[0], c[0], c[1], c[1], c[2], c[2]];
466
+ }
467
+ c = '0x' + c.join('');
468
+ return [(c >> 16) & 255, (c >> 8) & 255, c & 255];
469
+ }
470
+ throw new Error('Invalid Hex');
471
+ }
472
+
428
473
  export {
429
474
  s,
430
475
  htmls,
@@ -454,4 +499,5 @@ export {
454
499
  isDevInstance,
455
500
  getDataFromInputFile,
456
501
  getLang,
502
+ hexToRgbA,
457
503
  };
@@ -35,7 +35,7 @@ const MenuDefault = {
35
35
  const id = getId(this.Data, 'menu-');
36
36
  this.Data[id] = {};
37
37
  const RouterInstance = RouterDefault();
38
- const { NameApp } = RouterInstance;
38
+ const { BannerAppTemplate } = RouterInstance;
39
39
  const { barConfig } = await Themes[Css.currentTheme]();
40
40
  const heightTopBar = 50;
41
41
  const heightBottomBar = 50;
@@ -162,7 +162,7 @@ const MenuDefault = {
162
162
  </div>
163
163
  `,
164
164
  barConfig: newInstance(barConfig),
165
- title: NameApp,
165
+ title: BannerAppTemplate,
166
166
  // titleClass: 'hide',
167
167
  titleRender: () => {
168
168
  ThemeEvents['titleRender'] = () => {
@@ -4,7 +4,7 @@ import { getProxyPath, s } from '../core/VanillaJs.js';
4
4
 
5
5
  const logger = loggerFactory(import.meta);
6
6
 
7
- const NameApp = html`<strong class="inl" style="font-family: system-ui">PWA</strong>`;
7
+ const BannerAppTemplate = html`<strong class="inl" style="font-family: system-ui">PWA</strong>`;
8
8
 
9
9
  // Router
10
10
  const RoutesDefault = () => {
@@ -39,7 +39,7 @@ const RoutesDefault = () => {
39
39
  window.Routes = RoutesDefault;
40
40
 
41
41
  const RouterDefault = () => {
42
- return { Routes: RoutesDefault, NameApp };
42
+ return { Routes: RoutesDefault, BannerAppTemplate };
43
43
  };
44
44
 
45
- export { RoutesDefault, RouterDefault, NameApp };
45
+ export { RoutesDefault, RouterDefault, BannerAppTemplate };
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ class Underpost {
35
35
  * @type {String}
36
36
  * @memberof Underpost
37
37
  */
38
- static version = 'v2.8.85';
38
+ static version = 'v2.8.87';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static
@@ -48,6 +48,43 @@ const MailerProvider = {
48
48
  ...options,
49
49
  transporter,
50
50
  templates: await EmailRender.getTemplates(options),
51
+ translateTemplates: {
52
+ confirmEmail: {
53
+ H1: {
54
+ en: 'Confirm Your Email',
55
+ es: 'Confirma tu correo electrónico',
56
+ },
57
+ P1: {
58
+ en: `Email confirmed! Thanks.
59
+ <br />
60
+ <span style="font-size: 12px; color: gray">
61
+ If it is not automatically verified,
62
+ please allow the image to be seen, thank you.
63
+ </span>
64
+ `,
65
+ es: `Correo electrónico confirmado! Gracias.
66
+ <br />
67
+ <span style="font-size: 12px; color: gray">
68
+ Si no se verifica automáticamente, por favor permita que se vea la imagen, gracias.
69
+ </span>
70
+ `,
71
+ },
72
+ },
73
+ recoverEmail: {
74
+ H1: {
75
+ en: 'Recover your account',
76
+ es: 'Recupera tu cuenta',
77
+ },
78
+ P1: {
79
+ en: 'To recover your account, please click the button below:',
80
+ es: 'Para recuperar tu cuenta, haz click en el botón de abajo:',
81
+ },
82
+ BTN_LABEL: {
83
+ en: 'Recover Password',
84
+ es: 'Recuperar Contraseña',
85
+ },
86
+ },
87
+ },
51
88
  };
52
89
 
53
90
  return this.instance[id];
@@ -159,7 +159,7 @@ const buildCoverage = async ({ host, path }) => {
159
159
  shellExec(`npm test`);
160
160
  }
161
161
 
162
- const coverageBuildPath = `${jsDocsConfig.opts.destination}/coverage`;
162
+ const coverageBuildPath = `${jsDocsConfig.opts.destination}coverage`;
163
163
  fs.mkdirSync(coverageBuildPath, { recursive: true });
164
164
  fs.copySync(`./coverage`, coverageBuildPath);
165
165
 
@@ -59,7 +59,7 @@ const clientLiveBuild = async () => {
59
59
  const updates = JSON.parse(fs.readFileSync(`./tmp/client.build.json`, 'utf8'));
60
60
  const liveClientBuildPaths = [];
61
61
  for (let srcPath of updates) {
62
- srcPath = srcPath.replaceAll('/', `\\`); // linux case
62
+ srcPath = srcPath.replaceAll('/', `\\`);
63
63
 
64
64
  const srcBuildPath = `./src${srcPath.split('src')[1].replace(/\\/g, '/')}`;
65
65
  if (
@@ -19,7 +19,7 @@ import * as dir from 'path';
19
19
  import { shellExec } from './process.js';
20
20
  import { SitemapStream, streamToPromise } from 'sitemap';
21
21
  import { Readable } from 'stream';
22
- import { buildIcons, buildTextImg, getBufferPngText } from './client-icons.js';
22
+ import { buildIcons } from './client-icons.js';
23
23
  import Underpost from '../index.js';
24
24
  import { buildDocs } from './client-build-docs.js';
25
25
 
@@ -65,16 +65,8 @@ const fullBuild = async ({
65
65
  fs.removeSync(rootClientPath);
66
66
 
67
67
  if (fs.existsSync(`./src/client/public/${publicClientId}`)) {
68
- if (iconsBuild) {
69
- const defaultBaseIconFolderPath = `src/client/public/${publicClientId}/assets/logo`;
70
- if (!fs.existsSync(defaultBaseIconFolderPath)) fs.mkdirSync(defaultBaseIconFolderPath, { recursive: true });
71
- const defaultBaseIconPath = `${defaultBaseIconFolderPath}/base-icon.png`;
72
- if (!fs.existsSync(defaultBaseIconPath))
73
- await buildTextImg(metadata.title, { debugFilename: defaultBaseIconPath });
74
-
75
- if (!fs.existsSync(`./src/client/public/${publicClientId}/site.webmanifest`))
76
- await buildIcons({ publicClientId, metadata });
77
- }
68
+ if (iconsBuild === true) await buildIcons({ publicClientId, metadata });
69
+
78
70
  fs.copySync(
79
71
  `./src/client/public/${publicClientId}`,
80
72
  rootClientPath /* {
@@ -535,7 +527,7 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
535
527
  );
536
528
  }
537
529
 
538
- if (!enableLiveRebuild && !process.argv.includes('l') && !process.argv.includes('deploy') && docsBuild) {
530
+ if (fullBuildEnabled && !enableLiveRebuild && !process.argv.includes('l') && docsBuild) {
539
531
  await buildDocs({
540
532
  host,
541
533
  path,
@@ -7,7 +7,7 @@ const logger = loggerFactory(import.meta);
7
7
 
8
8
  const createClientDevServer = () => {
9
9
  // process.argv.slice(2).join(' ')
10
- shellExec(`env-cmd -f .env.development node bin/deploy build-full-client ${process.argv.slice(2).join(' ')} l`);
10
+ shellExec(`env-cmd -f .env.development node bin/deploy build-full-client ${process.argv.slice(2).join(' ')}`);
11
11
  shellExec(
12
12
  `env-cmd -f .env.development node src/api ${process.argv[2]}${process.argv[5] ? ` ${process.argv[5]}` : ''}${
13
13
  process.argv.includes('static') ? ' static' : ''
@@ -1,80 +1,17 @@
1
1
  import { favicons } from 'favicons';
2
- // TODO: search alternatives
3
- // import textToImage from 'text-to-image';
4
2
  import { loggerFactory } from './logger.js';
5
3
  import fs from 'fs-extra';
6
- import { getCapVariableName, s4 } from '../client/components/core/CommonJs.js';
7
- import { FileFactory } from '../api/file/file.service.js';
8
- import { svg, png, png3x } from 'font-awesome-assets';
4
+ import { getCapVariableName } from '../client/components/core/CommonJs.js';
9
5
 
10
6
  const logger = loggerFactory(import.meta);
11
7
 
12
- const faBase64Png = (faId = 'check', width = 100, height = 100, color = '#209e00') => {
13
- const b64Src = png3x(faId, color, width, height);
14
- return b64Src.split('src="data:image/png;base64,')[1].split('"')[0];
15
- };
16
-
17
- const defaultBaseTextImgOptions = {
18
- debug: true,
19
- fontFamily: 'Arial',
20
- fontWeight: 'bold',
21
- bgColor: 'black',
22
- textColor: 'white',
23
- debugFilename: 'src/client/public/text-image.png',
24
- verticalAlign: 'center',
25
- textAlign: 'center',
26
- };
27
-
28
- const defaultBaseTextImgOptionsSizes = {
29
- '70x70': {
30
- maxWidth: 70,
31
- customHeight: 70,
32
- fontSize: 25,
33
- margin: 10,
34
- },
35
- '100x100': {
36
- maxWidth: 100,
37
- customHeight: 100,
38
- fontSize: 30,
39
- margin: 12,
40
- },
41
- '100x300': {
42
- maxWidth: 300,
43
- customHeight: 100,
44
- fontSize: 30,
45
- margin: 12,
46
- },
47
- '1200x1200': {
48
- maxWidth: 1200,
49
- customHeight: 1200,
50
- fontSize: 500,
51
- margin: 50,
52
- },
53
- };
54
-
55
- const buildTextImg = async (text = 'APP', options, size = '1200x1200') => {
56
- options = { ...defaultBaseTextImgOptions, ...defaultBaseTextImgOptionsSizes[size], ...options };
57
- // await textToImage.generate(text, options);
58
- };
59
-
60
- const getBufferPngText = async ({ text, textColor, bgColor, size, debugFilename }) => {
61
- if (!text) text = 'Hello World!';
62
- if (!textColor) textColor = '#000000';
63
- if (!bgColor) bgColor = '#ffffff';
64
- if (!size) size = '100x300';
65
- if (!debugFilename) debugFilename = `./${s4()}${s4()}${s4()}.png`;
66
- await buildTextImg(text, { textColor, bgColor, size, debugFilename }, size);
67
- if (!fs.existsSync(debugFilename)) return Buffer.alloc(0); // Return empty buffer if file not found
68
- const bufferImage = fs.readFileSync(debugFilename);
69
- fs.removeSync(debugFilename);
70
- return bufferImage;
71
- };
72
-
73
8
  const buildIcons = async ({
74
9
  publicClientId,
75
- metadata: { title, description, keywords, author, thumbnail, themeColor },
10
+ metadata: { title, description, keywords, author, thumbnail, themeColor, baseBuildIconReference },
76
11
  }) => {
77
- const source = `src/client/public/${publicClientId}/assets/logo/base-icon.png`; // Source image(s). `string`, `buffer` or array of `string`
12
+ const source = baseBuildIconReference
13
+ ? baseBuildIconReference
14
+ : `src/client/public/${publicClientId}/assets/logo/base-icon.png`; // Source image(s). `string`, `buffer` or array of `string`
78
15
 
79
16
  const configuration = {
80
17
  path: '/', // Path for overriding default icons path. `string`
@@ -149,13 +86,4 @@ const buildIcons = async ({
149
86
  }
150
87
  };
151
88
 
152
- const getDefaultProfileImageId = async (File) => {
153
- const faId = 'user';
154
- const tmpFilePath = `./tmp/${faId}-${s4() + s4()}.svg`;
155
- fs.writeFileSync(tmpFilePath, svg(faId, '#f5f5f5d1'), 'utf8');
156
- const file = await new File(FileFactory.svg(fs.readFileSync(tmpFilePath), `${faId}.svg`)).save();
157
- fs.removeSync(tmpFilePath);
158
- return file._id;
159
- };
160
-
161
- export { buildIcons, buildTextImg, defaultBaseTextImgOptions, faBase64Png, getBufferPngText, getDefaultProfileImageId };
89
+ export { buildIcons };