underpost 2.8.84 → 2.8.85

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 (104) hide show
  1. package/.env.development +1 -0
  2. package/.env.production +1 -0
  3. package/.env.test +1 -0
  4. package/.github/workflows/{ghpkg.yml → ghpkg.ci.yml} +1 -1
  5. package/.github/workflows/{npmpkg.yml → npmpkg.ci.yml} +1 -1
  6. package/.github/workflows/{publish.yml → publish.ci.yml} +1 -1
  7. package/.github/workflows/{pwa-microservices-template.page.yml → pwa-microservices-template-page.cd.yml} +1 -1
  8. package/.github/workflows/{pwa-microservices-template.test.yml → pwa-microservices-template-test.ci.yml} +1 -1
  9. package/.vscode/settings.json +0 -1
  10. package/README.md +45 -2
  11. package/bin/build.js +15 -5
  12. package/bin/deploy.js +17 -82
  13. package/bin/file.js +15 -8
  14. package/cli.md +65 -44
  15. package/conf.js +1 -1
  16. package/docker-compose.yml +1 -1
  17. package/manifests/deployment/dd-template-development/deployment.yaml +2 -2
  18. package/manifests/maas/gpu-diag.sh +1 -1
  19. package/package.json +4 -6
  20. package/src/api/user/user.router.js +24 -1
  21. package/src/api/user/user.service.js +1 -4
  22. package/src/cli/cluster.js +42 -27
  23. package/src/cli/deploy.js +20 -0
  24. package/src/cli/index.js +9 -0
  25. package/src/cli/monitor.js +8 -12
  26. package/src/cli/run.js +111 -6
  27. package/src/cli/ssh.js +32 -0
  28. package/src/client/Default.index.js +7 -3
  29. package/src/client/components/core/Account.js +1 -1
  30. package/src/client/components/core/Chat.js +1 -1
  31. package/src/client/components/core/CommonJs.js +24 -22
  32. package/src/client/components/core/Content.js +1 -5
  33. package/src/client/components/core/Css.js +258 -18
  34. package/src/client/components/core/CssCore.js +8 -8
  35. package/src/client/components/core/Docs.js +14 -61
  36. package/src/client/components/core/DropDown.js +137 -82
  37. package/src/client/components/core/EventsUI.js +92 -5
  38. package/src/client/components/core/LoadingAnimation.js +8 -15
  39. package/src/client/components/core/Modal.js +597 -136
  40. package/src/client/components/core/NotificationManager.js +2 -2
  41. package/src/client/components/core/ObjectLayerEngine.js +638 -0
  42. package/src/client/components/core/Panel.js +158 -34
  43. package/src/client/components/core/PanelForm.js +12 -3
  44. package/src/client/components/core/Recover.js +1 -1
  45. package/src/client/components/core/Router.js +77 -17
  46. package/src/client/components/core/SocketIo.js +3 -3
  47. package/src/client/components/core/Translate.js +6 -2
  48. package/src/client/components/core/VanillaJs.js +0 -3
  49. package/src/client/components/core/Worker.js +3 -1
  50. package/src/client/components/default/CssDefault.js +17 -3
  51. package/src/client/components/default/MenuDefault.js +264 -45
  52. package/src/client/components/default/RoutesDefault.js +6 -12
  53. package/src/client/public/default/android-chrome-144x144.png +0 -0
  54. package/src/client/public/default/android-chrome-192x192.png +0 -0
  55. package/src/client/public/default/android-chrome-256x256.png +0 -0
  56. package/src/client/public/default/android-chrome-36x36.png +0 -0
  57. package/src/client/public/default/android-chrome-48x48.png +0 -0
  58. package/src/client/public/default/android-chrome-72x72.png +0 -0
  59. package/src/client/public/default/android-chrome-96x96.png +0 -0
  60. package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
  61. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  62. package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
  63. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  64. package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
  65. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  66. package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
  67. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  68. package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
  69. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  70. package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
  71. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  72. package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
  73. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  74. package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
  75. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  76. package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
  77. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  78. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  79. package/src/client/public/default/apple-touch-icon.png +0 -0
  80. package/src/client/public/default/assets/background/dark.jpg +0 -0
  81. package/src/client/public/default/assets/background/dark.svg +557 -0
  82. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  83. package/src/client/public/default/assets/logo/underpost.gif +0 -0
  84. package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
  85. package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
  86. package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
  87. package/src/client/public/default/favicon-16x16.png +0 -0
  88. package/src/client/public/default/favicon-32x32.png +0 -0
  89. package/src/client/public/default/favicon.ico +0 -0
  90. package/src/client/public/default/mstile-144x144.png +0 -0
  91. package/src/client/public/default/mstile-150x150.png +0 -0
  92. package/src/client/public/default/mstile-310x150.png +0 -0
  93. package/src/client/public/default/mstile-310x310.png +0 -0
  94. package/src/client/public/default/mstile-70x70.png +0 -0
  95. package/src/client/public/default/safari-pinned-tab.svg +24 -0
  96. package/src/client/ssr/body/DefaultSplashScreen.js +2 -2
  97. package/src/index.js +9 -1
  98. package/src/monitor.js +24 -0
  99. package/src/runtime/lampp/Dockerfile +30 -39
  100. package/src/runtime/lampp/Lampp.js +11 -2
  101. package/src/server/client-build-docs.js +205 -0
  102. package/src/server/client-build.js +16 -166
  103. package/src/server/conf.js +12 -5
  104. package/src/server/valkey.js +102 -41
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="269.000000pt" height="269.000000pt" viewBox="0 0 269.000000 269.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+ <metadata>
8
+ Created by potrace 1.11, written by Peter Selinger 2001-2013
9
+ </metadata>
10
+ <g transform="translate(0.000000,269.000000) scale(0.100000,-0.100000)"
11
+ fill="#000000" stroke="none">
12
+ <path d="M980 2475 l0 -65 65 0 65 0 0 65 0 65 -65 0 -65 0 0 -65z"/>
13
+ <path d="M1700 2475 l0 -65 65 0 65 0 0 65 0 65 -65 0 -65 0 0 -65z"/>
14
+ <path d="M1110 2325 l0 -65 -85 0 -85 0 0 -140 0 -140 -60 0 -60 0 0 -160 0
15
+ -160 75 0 75 0 0 -100 0 -100 95 0 95 0 0 -40 0 -40 -240 0 -240 0 0 -445 0
16
+ -445 -65 0 -65 0 0 -135 0 -135 65 0 65 0 0 -55 0 -55 65 0 65 0 0 475 0 475
17
+ 85 0 85 0 0 -425 0 -425 425 0 425 0 0 425 0 425 85 0 85 0 0 -475 0 -475 65
18
+ 0 65 0 0 55 0 55 60 0 60 0 0 135 0 135 -60 0 -60 0 0 445 0 445 -240 0 -240
19
+ 0 0 35 0 35 95 0 95 0 0 105 0 105 75 0 75 0 0 160 0 160 -60 0 -60 0 0 140 0
20
+ 140 -85 0 -85 0 0 65 0 65 -75 0 -75 0 0 -65 0 -65 -145 0 -145 0 0 65 0 65
21
+ -75 0 -75 0 0 -65z m210 -505 l0 -110 -110 0 -110 0 0 110 0 110 110 0 110 0
22
+ 0 -110z m390 0 l0 -70 -70 0 -70 0 0 70 0 70 70 0 70 0 0 -70z"/>
23
+ </g>
24
+ </svg>
@@ -1,12 +1,12 @@
1
1
  SrrComponent = ({ backgroundImage, metadata }) => html`
2
2
  ${backgroundImage
3
- ? html`<style>
3
+ ? html`<style class="style-ssr-background-image">
4
4
  .ssr-background-image {
5
5
  background-image: url('${backgroundImage}');
6
6
  }
7
7
  </style>`
8
8
  : metadata?.themeColor
9
- ? html`<style>
9
+ ? html`<style class="style-ssr-background-image">
10
10
  .ssr-background-image {
11
11
  background: ${metadata.themeColor};
12
12
  }
package/src/index.js CHANGED
@@ -19,6 +19,7 @@ import UnderpostRepository from './cli/repository.js';
19
19
  import UnderpostRun from './cli/run.js';
20
20
  import UnderpostScript from './cli/script.js';
21
21
  import UnderpostSecret from './cli/secrets.js';
22
+ import UnderpostSSH from './cli/ssh.js';
22
23
  import UnderpostTest from './cli/test.js';
23
24
  import UnderpostStartUp from './server/start.js';
24
25
 
@@ -34,7 +35,7 @@ class Underpost {
34
35
  * @type {String}
35
36
  * @memberof Underpost
36
37
  */
37
- static version = 'v2.8.84';
38
+ static version = 'v2.8.85';
38
39
  /**
39
40
  * Repository cli API
40
41
  * @static
@@ -126,6 +127,13 @@ class Underpost {
126
127
  * @memberof Underpost
127
128
  */
128
129
  static monitor = UnderpostMonitor.API;
130
+ /**
131
+ * SSH cli API
132
+ * @static
133
+ * @type {UnderpostSSH.API}
134
+ * @memberof Underpost
135
+ */
136
+ static ssh = UnderpostSSH.API;
129
137
  /**
130
138
  * LXD cli API
131
139
  * @static
package/src/monitor.js ADDED
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ // https://nodejs.org/api
4
+ // https://expressjs.com/en/4x/api.html
5
+
6
+ import dotenv from 'dotenv';
7
+ import { loggerFactory } from './server/logger.js';
8
+ import { ProcessController } from './server/process.js';
9
+ import { getUnderpostRootPath } from './server/conf.js';
10
+ import fs from 'fs-extra';
11
+ import UnderpostMonitor from './cli/monitor.js';
12
+
13
+ const underpostRootPath = getUnderpostRootPath();
14
+ fs.existsSync(`${underpostRootPath}/.env`)
15
+ ? dotenv.config({ path: `${underpostRootPath}/.env`, override: true })
16
+ : dotenv.config();
17
+
18
+ const logger = loggerFactory(import.meta);
19
+
20
+ await logger.setUpInfo();
21
+
22
+ UnderpostMonitor.API.callback(process.argv[2], process.argv[3], { type: 'blue-green', sync: true });
23
+
24
+ ProcessController.init(logger);
@@ -1,43 +1,35 @@
1
1
  FROM rockylinux:9
2
2
 
3
- RUN dnf install -y --allowerasing bzip2
4
-
5
- RUN dnf update -y
6
- RUN dnf install -y epel-release
7
- RUN dnf install -y --allowerasing sudo
8
- RUN dnf install -y --allowerasing curl
9
- RUN dnf install -y --allowerasing net-tools
10
- RUN dnf install -y --allowerasing openssh-server
11
- RUN dnf install -y --allowerasing nano
12
- RUN dnf install -y --allowerasing vim-enhanced
13
- RUN dnf install -y --allowerasing less
14
- RUN dnf install -y --allowerasing openssl-devel
15
- RUN dnf install -y --allowerasing wget
16
- RUN dnf install -y --allowerasing git
17
- RUN dnf install -y --allowerasing gnupg2
18
- RUN dnf clean all
19
-
20
- # Install LAMPP (XAMPP)
21
- # Download the XAMPP installer for Linux
22
- RUN curl -Lo xampp-linux-installer.run https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run?from_af=true
23
- RUN chmod +x xampp-linux-installer.run
24
- # Run the XAMPP installer in silent mode
25
- RUN bash -c './xampp-linux-installer.run --mode unattended'
26
- # Create a symbolic link for easy access to lampp command
27
- RUN ln -sf /opt/lampp/lampp /usr/bin/lampp
28
-
29
- # Configure XAMPP
30
- # Enable XAMPP web interface (remove security checks)
31
- RUN sed -i.bak 's/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf
32
- # Enable error display in php
33
- RUN sed -i.bak 's/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
34
- # Enable includes of several configuration files for Apache
35
- RUN mkdir -p /opt/lampp/apache2/conf.d
36
- RUN echo "IncludeOptional /opt/lampp/apache2/conf.d/*.conf" >>/opt/lampp/etc/httpd.conf
37
- # Create a /www folder and a symbolic link to it in /opt/lampp/htdocs
38
- # This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools
39
- RUN mkdir /www
40
- RUN ln -s /www /opt/lampp/htdocs
3
+ # --- Update and install required packages
4
+ RUN dnf -y update && \
5
+ dnf -y install epel-release && \
6
+ dnf -y install --allowerasing \
7
+ bzip2 \
8
+ sudo \
9
+ curl \
10
+ net-tools \
11
+ openssh-server \
12
+ nano \
13
+ vim-enhanced \
14
+ less \
15
+ openssl-devel \
16
+ wget \
17
+ git \
18
+ gnupg2 \
19
+ libnsl \
20
+ perl && \
21
+ dnf clean all
22
+
23
+ # --- Download and install XAMPP
24
+ RUN curl -L -o /tmp/xampp-linux-installer.run "https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run" && \
25
+ chmod +x /tmp/xampp-linux-installer.run && \
26
+ bash -c "/tmp/xampp-linux-installer.run --mode unattended" && \
27
+ ln -sf /opt/lampp/lampp /usr/bin/lampp
28
+
29
+ # --- Create /xampp/htdocs (static root) and set permissions
30
+ RUN mkdir -p /opt/lampp/htdocs && \
31
+ chown -R root:root /opt/lampp/htdocs && \
32
+ chmod -R a+rX /opt/lampp/htdocs
41
33
 
42
34
  # Install Node.js
43
35
  RUN curl -fsSL https://rpm.nodesource.com/setup_23.x | bash -
@@ -51,7 +43,6 @@ RUN npm --version
51
43
  # Set working directory
52
44
  WORKDIR /home/dd
53
45
 
54
- # Expose necessary ports
55
46
  EXPOSE 22
56
47
  EXPOSE 80
57
48
  EXPOSE 443
@@ -10,7 +10,16 @@ const Lampp = {
10
10
  initService: async function (options = { daemon: false }) {
11
11
  let cmd;
12
12
  // linux
13
- fs.writeFileSync(`/opt/lampp/apache2/conf/httpd.conf`, this.router || '', 'utf8');
13
+ // /opt/lampp/apache2/conf/httpd.conf
14
+ fs.writeFileSync(`/opt/lampp/etc/extra/httpd-vhosts.conf`, this.router || '', 'utf8');
15
+ fs.writeFileSync(
16
+ `/opt/lampp/etc/httpd.conf`,
17
+ fs
18
+ .readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8')
19
+ .replace(`#Include etc/extra/httpd-vhosts.conf`, `Include etc/extra/httpd-vhosts.conf`),
20
+ 'utf8',
21
+ );
22
+
14
23
  cmd = `sudo /opt/lampp/lampp stop`;
15
24
  if (!fs.readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8').match(`# Listen 80`))
16
25
  fs.writeFileSync(
@@ -42,7 +51,7 @@ const Lampp = {
42
51
  if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
43
52
  shellExec(cmd);
44
53
  },
45
- enabled: () => fs.existsSync(`/opt/lampp/apache2/conf/httpd.conf`),
54
+ enabled: () => fs.existsSync(`/opt/lampp/etc/httpd.conf`),
46
55
  appendRouter: function (render) {
47
56
  if (!this.router) {
48
57
  if (fs.existsSync(`./tmp/lampp-router.conf`))
@@ -0,0 +1,205 @@
1
+ 'use strict';
2
+
3
+ import fs from 'fs-extra';
4
+ import swaggerAutoGen from 'swagger-autogen';
5
+ import { shellExec } from './process.js';
6
+ import { loggerFactory } from './logger.js';
7
+ import { JSONweb } from './client-formatted.js';
8
+
9
+ /**
10
+ * Builds API documentation using Swagger
11
+ * @param {Object} options - Documentation build options
12
+ * @param {string} options.host - The hostname for the API
13
+ * @param {string} options.path - The base path for the API
14
+ * @param {number} options.port - The port number for the API
15
+ * @param {Object} options.metadata - Metadata for the API documentation
16
+ * @param {Array<string>} options.apis - List of API modules to document
17
+ * @param {string} options.publicClientId - Client ID for the public documentation
18
+ * @param {string} options.rootClientPath - Root path for client files
19
+ * @param {Object} options.packageData - Package.json data
20
+ */
21
+ const buildApiDocs = async ({
22
+ host,
23
+ path,
24
+ port,
25
+ metadata = {},
26
+ apis = [],
27
+ publicClientId,
28
+ rootClientPath,
29
+ packageData,
30
+ }) => {
31
+ const logger = loggerFactory(import.meta);
32
+ const basePath = path === '/' ? `${process.env.BASE_API}` : `/${process.env.BASE_API}`;
33
+
34
+ const doc = {
35
+ info: {
36
+ version: packageData.version,
37
+ title: metadata?.title ? `${metadata.title}` : 'REST API',
38
+ description: metadata?.description ? metadata.description : '',
39
+ },
40
+ servers: [
41
+ {
42
+ url:
43
+ process.env.NODE_ENV === 'development'
44
+ ? `http://localhost:${port}${path}${basePath}`
45
+ : `https://${host}${path}${basePath}`,
46
+ description: `${process.env.NODE_ENV} server`,
47
+ },
48
+ ],
49
+ tags: [
50
+ {
51
+ name: 'user',
52
+ description: 'User API operations',
53
+ },
54
+ ],
55
+ components: {
56
+ schemas: {
57
+ userRequest: {
58
+ username: 'user123',
59
+ password: 'Password123',
60
+ email: 'user@example.com',
61
+ },
62
+ userResponse: {
63
+ status: 'success',
64
+ data: {
65
+ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjY2YzM3N2Y1N2Y5OWU1OTY5YjgxZG...',
66
+ user: {
67
+ _id: '66c377f57f99e5969b81de89',
68
+ email: 'user@example.com',
69
+ emailConfirmed: false,
70
+ username: 'user123',
71
+ role: 'user',
72
+ profileImageId: '66c377f57f99e5969b81de87',
73
+ },
74
+ },
75
+ },
76
+ userUpdateResponse: {
77
+ status: 'success',
78
+ data: {
79
+ _id: '66c377f57f99e5969b81de89',
80
+ email: 'user@example.com',
81
+ emailConfirmed: false,
82
+ username: 'user123222',
83
+ role: 'user',
84
+ profileImageId: '66c377f57f99e5969b81de87',
85
+ },
86
+ },
87
+ userGetResponse: {
88
+ status: 'success',
89
+ data: {
90
+ _id: '66c377f57f99e5969b81de89',
91
+ email: 'user@example.com',
92
+ emailConfirmed: false,
93
+ username: 'user123222',
94
+ role: 'user',
95
+ profileImageId: '66c377f57f99e5969b81de87',
96
+ },
97
+ },
98
+ userLogInRequest: {
99
+ email: 'user@example.com',
100
+ password: 'Password123',
101
+ },
102
+ userBadRequestResponse: {
103
+ status: 'error',
104
+ message: 'Bad request. Please check your inputs, and try again',
105
+ },
106
+ },
107
+ securitySchemes: {
108
+ bearerAuth: {
109
+ type: 'http',
110
+ scheme: 'bearer',
111
+ },
112
+ },
113
+ },
114
+ };
115
+
116
+ logger.warn('build swagger api docs', doc.info);
117
+
118
+ const outputFile = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
119
+ const routes = [];
120
+ for (const api of apis) {
121
+ if (['user'].includes(api)) routes.push(`./src/api/${api}/${api}.router.js`);
122
+ }
123
+
124
+ await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
125
+ };
126
+
127
+ /**
128
+ * Builds JSDoc documentation
129
+ * @param {Object} options - JSDoc build options
130
+ * @param {string} options.host - The hostname for the documentation
131
+ * @param {string} options.path - The base path for the documentation
132
+ * @param {Object} options.metadata - Metadata for the documentation
133
+ */
134
+ const buildJsDocs = async ({ host, path, metadata = {} }) => {
135
+ const logger = loggerFactory(import.meta);
136
+ const jsDocsConfig = JSON.parse(fs.readFileSync(`./jsdoc.json`, 'utf8'));
137
+
138
+ jsDocsConfig.opts.destination = `./public/${host}${path === '/' ? path : `${path}/`}docs/`;
139
+ jsDocsConfig.opts.theme_opts.title = metadata?.title ? metadata.title : undefined;
140
+ jsDocsConfig.opts.theme_opts.favicon = `./public/${host}${path === '/' ? path : `${path}/favicon.ico`}`;
141
+
142
+ fs.writeFileSync(`./jsdoc.json`, JSON.stringify(jsDocsConfig, null, 4), 'utf8');
143
+ logger.warn('build jsdoc view', jsDocsConfig.opts.destination);
144
+
145
+ shellExec(`npm run docs`, { silent: true });
146
+ };
147
+
148
+ /**
149
+ * Builds test coverage documentation
150
+ * @param {Object} options - Coverage build options
151
+ * @param {string} options.host - The hostname for the coverage
152
+ * @param {string} options.path - The base path for the coverage
153
+ */
154
+ const buildCoverage = async ({ host, path }) => {
155
+ const logger = loggerFactory(import.meta);
156
+ const jsDocsConfig = JSON.parse(fs.readFileSync(`./jsdoc.json`, 'utf8'));
157
+
158
+ if (!fs.existsSync(`./coverage`)) {
159
+ shellExec(`npm test`);
160
+ }
161
+
162
+ const coverageBuildPath = `${jsDocsConfig.opts.destination}/coverage`;
163
+ fs.mkdirSync(coverageBuildPath, { recursive: true });
164
+ fs.copySync(`./coverage`, coverageBuildPath);
165
+
166
+ logger.warn('build coverage', coverageBuildPath);
167
+ };
168
+
169
+ /**
170
+ * Main function to build all documentation
171
+ * @param {Object} options - Documentation build options
172
+ * @param {string} options.host - The hostname
173
+ * @param {string} options.path - The base path
174
+ * @param {number} options.port - The port number
175
+ * @param {Object} options.metadata - Metadata for the documentation
176
+ * @param {Array<string>} options.apis - List of API modules to document
177
+ * @param {string} options.publicClientId - Client ID for the public documentation
178
+ * @param {string} options.rootClientPath - Root path for client files
179
+ * @param {Object} options.packageData - Package.json data
180
+ */
181
+ const buildDocs = async ({
182
+ host,
183
+ path,
184
+ port,
185
+ metadata = {},
186
+ apis = [],
187
+ publicClientId,
188
+ rootClientPath,
189
+ packageData,
190
+ }) => {
191
+ await buildJsDocs({ host, path, metadata });
192
+ await buildCoverage({ host, path });
193
+ await buildApiDocs({
194
+ host,
195
+ path,
196
+ port,
197
+ metadata,
198
+ apis,
199
+ publicClientId,
200
+ rootClientPath,
201
+ packageData,
202
+ });
203
+ };
204
+
205
+ export { buildDocs };
@@ -17,11 +17,11 @@ import dotenv from 'dotenv';
17
17
  import AdmZip from 'adm-zip';
18
18
  import * as dir from 'path';
19
19
  import { shellExec } from './process.js';
20
- import swaggerAutoGen from 'swagger-autogen';
21
20
  import { SitemapStream, streamToPromise } from 'sitemap';
22
21
  import { Readable } from 'stream';
23
22
  import { buildIcons, buildTextImg, getBufferPngText } from './client-icons.js';
24
23
  import Underpost from '../index.js';
24
+ import { buildDocs } from './client-build-docs.js';
25
25
 
26
26
  dotenv.config();
27
27
 
@@ -333,14 +333,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
333
333
  minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
334
334
  'utf8',
335
335
  );
336
-
337
- // const title = `${metadata && metadata.title ? metadata.title : cap(client)}${
338
- // view.title ? ` | ${view.title}` : view.path !== '/' ? ` | ${titleFormatted(view.path)}` : ''
339
- // }`;
340
-
341
- const title = `${
342
- view.title ? `${view.title} | ` : view.path !== '/' ? `${titleFormatted(view.path)} | ` : ''
343
- }${metadata && metadata.title ? metadata.title : cap(client)}`;
336
+ const title = metadata.title ? metadata.title : title;
344
337
 
345
338
  const canonicalURL = `https://${host}${path}${
346
339
  view.path === '/' ? (path === '/' ? '' : '/') : path === '/' ? `${view.path.slice(1)}/` : `${view.path}/`
@@ -441,27 +434,13 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
441
434
  case 'CyberiaDefaultSplashScreen':
442
435
  case 'NexodevSplashScreen':
443
436
  case 'DefaultSplashScreen':
444
- if (backgroundImage) {
437
+ if (backgroundImage)
445
438
  ssrHeadComponents += SrrComponent({
439
+ ...metadata,
446
440
  backgroundImage: (path === '/' ? path : `${path}/`) + backgroundImage,
447
441
  });
448
- // `data:image/${backgroundImage.split('.').pop()};base64,${fs
449
- // .readFileSync()
450
- // .toString('base64')}`,
451
- break;
452
- } else {
453
- ssrHeadComponents += SrrComponent({ metadata });
454
- break;
455
- const bufferBackgroundImage = await getBufferPngText({
456
- text: ' ',
457
- textColor: metadata?.themeColor ? metadata.themeColor : '#ececec',
458
- size: '100x100',
459
- bgColor: metadata?.themeColor ? metadata.themeColor : '#ececec',
460
- });
461
- ssrHeadComponents += SrrComponent({
462
- backgroundImage: `data:image/png;base64,${bufferBackgroundImage.toString('base64')}`,
463
- });
464
- }
442
+ else ssrHeadComponents += SrrComponent({ metadata });
443
+ break;
465
444
 
466
445
  case 'CyberiaSplashScreenLore': {
467
446
  ssrBodyComponents += SrrComponent({
@@ -557,145 +536,16 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
557
536
  }
558
537
 
559
538
  if (!enableLiveRebuild && !process.argv.includes('l') && !process.argv.includes('deploy') && docsBuild) {
560
- // https://www.pullrequest.com/blog/leveraging-jsdoc-for-better-code-documentation-in-javascript/
561
- // https://jsdoc.app/about-configuring-jsdoc
562
- // https://jsdoc.app/ Block tags
563
-
564
- const jsDocsConfig = JSON.parse(fs.readFileSync(`./jsdoc.json`, 'utf8'));
565
- jsDocsConfig.opts.destination = `./public/${host}${path === '/' ? path : `${path}/`}docs/`;
566
- jsDocsConfig.opts.theme_opts.title = metadata && metadata.title ? metadata.title : undefined;
567
- jsDocsConfig.opts.theme_opts.favicon = `./public/${host}${path === '/' ? path : `${path}/favicon.ico`}`;
568
- fs.writeFileSync(`./jsdoc.json`, JSON.stringify(jsDocsConfig, null, 4), 'utf8');
569
- logger.warn('build jsdoc view', jsDocsConfig.opts.destination);
570
- shellExec(`npm run docs`, { silent: true });
571
-
572
- // coverage
573
- if (!fs.existsSync(`./coverage`)) {
574
- shellExec(`npm test`);
575
- }
576
- const coverageBuildPath = `${jsDocsConfig.opts.destination}/coverage`;
577
- fs.mkdirSync(coverageBuildPath, { recursive: true });
578
- fs.copySync(`./coverage`, coverageBuildPath);
579
-
580
- // uml
581
- // shellExec(`node bin/deploy uml ${host} ${path}`);
582
-
583
- // https://swagger-autogen.github.io/docs/
584
-
585
- const basePath = path === '/' ? `${process.env.BASE_API}` : `/${process.env.BASE_API}`;
586
-
587
- const doc = {
588
- info: {
589
- version: packageData.version, // by default: '1.0.0'
590
- title: metadata?.title ? `${metadata.title}` : 'REST API', // by default: 'REST API'
591
- description: metadata?.description ? metadata.description : '', // by default: ''
592
- },
593
- servers: [
594
- {
595
- url:
596
- process.env.NODE_ENV === 'development'
597
- ? `http://localhost:${port}${path}${basePath}`
598
- : `https://${host}${path}${basePath}`, // by default: 'http://localhost:3000'
599
- description: `${process.env.NODE_ENV} server`, // by default: ''
600
- },
601
- ],
602
- tags: [
603
- // by default: empty Array
604
- {
605
- name: 'user', // Tag name
606
- description: 'User API operations', // Tag description
607
- },
608
- ],
609
- components: {
610
- schemas: {
611
- userRequest: {
612
- username: 'user123',
613
- password: 'Password123',
614
- email: 'user@example.com',
615
- },
616
- userResponse: {
617
- status: 'success',
618
- data: {
619
- token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjY2YzM3N2Y1N2Y5OWU1OTY5YjgxZG...',
620
- user: {
621
- _id: '66c377f57f99e5969b81de89',
622
- email: 'user@example.com',
623
- emailConfirmed: false,
624
- username: 'user123',
625
- role: 'user',
626
- profileImageId: '66c377f57f99e5969b81de87',
627
- },
628
- },
629
- },
630
- userUpdateResponse: {
631
- status: 'success',
632
- data: {
633
- _id: '66c377f57f99e5969b81de89',
634
- email: 'user@example.com',
635
- emailConfirmed: false,
636
- username: 'user123222',
637
- role: 'user',
638
- profileImageId: '66c377f57f99e5969b81de87',
639
- },
640
- },
641
- userGetResponse: {
642
- status: 'success',
643
- data: {
644
- _id: '66c377f57f99e5969b81de89',
645
- email: 'user@example.com',
646
- emailConfirmed: false,
647
- username: 'user123222',
648
- role: 'user',
649
- profileImageId: '66c377f57f99e5969b81de87',
650
- },
651
- },
652
- userLogInRequest: {
653
- email: 'user@example.com',
654
- password: 'Password123',
655
- },
656
- userBadRequestResponse: {
657
- status: 'error',
658
- message: 'Bad request. Please check your inputs, and try again',
659
- },
660
- },
661
- securitySchemes: {
662
- bearerAuth: {
663
- type: 'http',
664
- scheme: 'bearer',
665
- },
666
- },
667
- },
668
- };
669
-
670
- // plantuml
671
- logger.info('copy plantuml', `${rootClientPath}/docs/plantuml`);
672
- fs.copySync(`./src/client/public/default/plantuml`, `${rootClientPath}/docs/plantuml`);
673
-
674
- logger.warn('build swagger api docs', doc.info);
675
-
676
- const outputFile = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
677
- const routes = [];
678
- for (const api of apis) {
679
- if (['user'].includes(api)) routes.push(`./src/api/${api}/${api}.router.js`);
680
- }
681
-
682
- /* NOTE: If you are using the express Router, you must pass in the 'routes' only the
683
- root file where the route starts, such as index.js, app.js, routes.js, etc ... */
684
-
685
- await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
686
-
687
- const htmlFiles = await fs.readdir(`./public/${host}/docs/engine/${Underpost.version.replace('v', '')}`);
688
- for (const htmlFile of htmlFiles) {
689
- if (htmlFile.match('.html')) {
690
- fs.writeFileSync(
691
- `./public/${host}/docs/engine/${Underpost.version.replace('v', '')}/${htmlFile}`,
692
- fs
693
- .readFileSync(`./public/${host}/docs/engine/${Underpost.version.replace('v', '')}/${htmlFile}`, 'utf8')
694
- .replaceAll('Tutorials', 'References'),
695
- 'utf8',
696
- );
697
- }
698
- }
539
+ await buildDocs({
540
+ host,
541
+ path,
542
+ port,
543
+ metadata,
544
+ apis,
545
+ publicClientId,
546
+ rootClientPath,
547
+ packageData,
548
+ });
699
549
  }
700
550
 
701
551
  if (client) {
@@ -89,12 +89,19 @@ const Config = {
89
89
  };
90
90
 
91
91
  const loadConf = (deployId, envInput, subConf) => {
92
+ if (deployId === 'current') {
93
+ console.log(process.env.DEPLOY_ID);
94
+ return;
95
+ }
92
96
  if (deployId === 'clean') {
93
- shellExec(`git checkout package.json`);
94
- shellExec(`git checkout .env.production`);
95
- shellExec(`git checkout .env.development`);
96
- shellExec(`git checkout .env.test`);
97
- shellExec(`git checkout jsdoc.json`);
97
+ const path = envInput ?? '.';
98
+ fs.removeSync(`${path}/.env`);
99
+ shellExec(`git checkout ${path}/.env.production`);
100
+ shellExec(`git checkout ${path}/.env.development`);
101
+ shellExec(`git checkout ${path}/.env.test`);
102
+ if (fs.existsSync(`${path}/jsdoc.json`)) shellExec(`git checkout ${path}/jsdoc.json`);
103
+ shellExec(`git checkout ${path}/package.json`);
104
+ shellExec(`git checkout ${path}/package-lock.json`);
98
105
  return;
99
106
  }
100
107
  const folder = fs.existsSync(`./engine-private/replica/${deployId}`)