underpost 2.8.86 → 2.8.88

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 (116) hide show
  1. package/.env.development +39 -2
  2. package/.env.production +42 -2
  3. package/.env.test +39 -2
  4. package/.github/workflows/ghpkg.ci.yml +1 -1
  5. package/.github/workflows/npmpkg.ci.yml +1 -1
  6. package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -5
  7. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  8. package/.github/workflows/release.cd.yml +3 -3
  9. package/README.md +76 -2
  10. package/bin/build.js +5 -0
  11. package/bin/deploy.js +93 -27
  12. package/bin/file.js +8 -4
  13. package/bin/util.js +1 -56
  14. package/cli.md +16 -5
  15. package/conf.js +33 -7
  16. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  17. package/manifests/deployment/dd-test-development/deployment.yaml +174 -0
  18. package/manifests/deployment/dd-test-development/proxy.yaml +51 -0
  19. package/manifests/deployment/mongo-express/deployment.yaml +12 -12
  20. package/manifests/maas/nvim.sh +91 -0
  21. package/package.json +8 -15
  22. package/src/api/core/core.router.js +2 -1
  23. package/src/api/default/default.controller.js +6 -1
  24. package/src/api/default/default.router.js +6 -2
  25. package/src/api/default/default.service.js +10 -1
  26. package/src/api/document/document.controller.js +66 -0
  27. package/src/api/document/document.model.js +51 -0
  28. package/src/api/document/document.router.js +24 -0
  29. package/src/api/document/document.service.js +125 -0
  30. package/src/api/file/file.controller.js +15 -1
  31. package/src/api/file/file.router.js +2 -1
  32. package/src/api/file/file.service.js +28 -8
  33. package/src/api/test/test.router.js +1 -1
  34. package/src/api/user/postman_collection.json +216 -0
  35. package/src/api/user/user.controller.js +25 -60
  36. package/src/api/user/user.model.js +29 -7
  37. package/src/api/user/user.router.js +40 -8
  38. package/src/api/user/user.service.js +86 -35
  39. package/src/cli/baremetal.js +33 -3
  40. package/src/cli/cloud-init.js +11 -0
  41. package/src/cli/cluster.js +4 -23
  42. package/src/cli/cron.js +0 -1
  43. package/src/cli/db.js +0 -19
  44. package/src/cli/deploy.js +67 -52
  45. package/src/cli/fs.js +1 -0
  46. package/src/cli/index.js +9 -1
  47. package/src/cli/lxd.js +7 -0
  48. package/src/cli/repository.js +44 -6
  49. package/src/cli/run.js +56 -9
  50. package/src/cli/ssh.js +20 -6
  51. package/src/client/Default.index.js +42 -1
  52. package/src/client/components/core/Account.js +10 -2
  53. package/src/client/components/core/AgGrid.js +30 -8
  54. package/src/client/components/core/Auth.js +99 -56
  55. package/src/client/components/core/BtnIcon.js +3 -2
  56. package/src/client/components/core/CalendarCore.js +2 -3
  57. package/src/client/components/core/CommonJs.js +1 -2
  58. package/src/client/components/core/Content.js +15 -12
  59. package/src/client/components/core/Css.js +2 -1
  60. package/src/client/components/core/CssCore.js +18 -1
  61. package/src/client/components/core/Docs.js +5 -5
  62. package/src/client/components/core/FileExplorer.js +3 -3
  63. package/src/client/components/core/FullScreen.js +19 -28
  64. package/src/client/components/core/Input.js +22 -16
  65. package/src/client/components/core/JoyStick.js +2 -2
  66. package/src/client/components/core/LoadingAnimation.js +2 -2
  67. package/src/client/components/core/LogIn.js +16 -23
  68. package/src/client/components/core/LogOut.js +5 -1
  69. package/src/client/components/core/Logger.js +4 -1
  70. package/src/client/components/core/Modal.js +102 -87
  71. package/src/client/components/core/ObjectLayerEngine.js +229 -4
  72. package/src/client/components/core/ObjectLayerEngineModal.js +442 -0
  73. package/src/client/components/core/Pagination.js +207 -0
  74. package/src/client/components/core/Panel.js +10 -10
  75. package/src/client/components/core/PanelForm.js +130 -33
  76. package/src/client/components/core/Recover.js +2 -2
  77. package/src/client/components/core/Router.js +210 -34
  78. package/src/client/components/core/SignUp.js +1 -2
  79. package/src/client/components/core/Stream.js +1 -1
  80. package/src/client/components/core/ToggleSwitch.js +15 -1
  81. package/src/client/components/core/VanillaJs.js +3 -84
  82. package/src/client/components/core/Worker.js +2 -2
  83. package/src/client/components/default/LogInDefault.js +0 -6
  84. package/src/client/components/default/LogOutDefault.js +0 -16
  85. package/src/client/components/default/MenuDefault.js +97 -44
  86. package/src/client/components/default/RoutesDefault.js +5 -2
  87. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  88. package/src/client/services/core/core.service.js +8 -20
  89. package/src/client/services/default/default.management.js +115 -18
  90. package/src/client/services/default/default.service.js +13 -4
  91. package/src/client/services/document/document.service.js +97 -0
  92. package/src/client/services/file/file.service.js +2 -0
  93. package/src/client/services/test/test.service.js +3 -0
  94. package/src/client/services/user/user.management.js +6 -0
  95. package/src/client/services/user/user.service.js +15 -4
  96. package/src/client/ssr/Render.js +1 -1
  97. package/src/client/ssr/head/DefaultScripts.js +3 -0
  98. package/src/client/ssr/head/Seo.js +1 -0
  99. package/src/index.js +24 -2
  100. package/src/runtime/lampp/Lampp.js +89 -2
  101. package/src/runtime/xampp/Xampp.js +48 -1
  102. package/src/server/auth.js +519 -155
  103. package/src/server/backup.js +2 -2
  104. package/src/server/client-build-docs.js +1 -1
  105. package/src/server/client-build.js +4 -12
  106. package/src/server/client-icons.js +6 -78
  107. package/src/server/conf.js +144 -141
  108. package/src/server/process.js +2 -1
  109. package/src/server/proxy.js +1 -1
  110. package/src/server/runtime.js +136 -288
  111. package/src/server/ssl.js +1 -2
  112. package/src/server/ssr.js +85 -0
  113. package/src/server/start.js +4 -4
  114. package/src/server/valkey.js +2 -1
  115. package/test/api.test.js +3 -2
  116. package/bin/cyberia0.js +0 -78
@@ -1,34 +1,31 @@
1
1
  import fs from 'fs-extra';
2
2
  import express from 'express';
3
- import cors from 'cors';
4
3
  import dotenv from 'dotenv';
5
4
  import fileUpload from 'express-fileupload';
6
5
  import swaggerUi from 'swagger-ui-express';
7
6
  import * as promClient from 'prom-client';
8
7
  import compression from 'compression';
9
8
 
10
- import { createServer } from 'http';
11
- import { getRootDirectory } from './process.js';
12
9
  import UnderpostStartUp from './start.js';
10
+ import { createServer } from 'http';
13
11
  import { loggerFactory, loggerMiddleware } from './logger.js';
14
12
  import { getCapVariableName, newInstance } from '../client/components/core/CommonJs.js';
15
- import { Xampp } from '../runtime/xampp/Xampp.js';
16
13
  import { MailerProvider } from '../mailer/MailerProvider.js';
17
14
  import { DataBaseProvider } from '../db/DataBaseProvider.js';
18
- // import { createProxyMiddleware } from 'http-proxy-middleware';
19
15
  import { createPeerServer } from './peer.js';
20
16
  import { Lampp } from '../runtime/lampp/Lampp.js';
21
- import { getDeployId } from './conf.js';
22
- import { JSONweb, ssrFactory } from './client-formatted.js';
23
- import Underpost from '../index.js';
17
+ import { Xampp } from '../runtime/xampp/Xampp.js';
24
18
  import { createValkeyConnection } from './valkey.js';
19
+ import { applySecurity, authMiddlewareFactory } from './auth.js';
20
+ import { getInstanceContext } from './conf.js';
21
+ import { ssrMiddlewareFactory } from './ssr.js';
25
22
 
26
23
  dotenv.config();
27
24
 
28
25
  const logger = loggerFactory(import.meta);
29
26
 
30
27
  const buildRuntime = async () => {
31
- const deployId = getDeployId();
28
+ const deployId = process.env.DEPLOY_ID;
32
29
 
33
30
  const collectDefaultMetrics = promClient.collectDefaultMetrics;
34
31
  collectDefaultMetrics();
@@ -39,8 +36,6 @@ const buildRuntime = async () => {
39
36
  labelNames: ['instance', 'method', 'status_code'],
40
37
  };
41
38
 
42
- // logger.info('promCounterOption', promCounterOption);
43
-
44
39
  const requestCounter = new promClient.Counter(promCounterOption);
45
40
  const initPort = parseInt(process.env.PORT) + 1;
46
41
  let currentPort = initPort;
@@ -48,9 +43,8 @@ const buildRuntime = async () => {
48
43
  const confSSR = JSON.parse(fs.readFileSync(`./conf/conf.ssr.json`, 'utf8'));
49
44
  const singleReplicaHosts = [];
50
45
  for (const host of Object.keys(confServer)) {
51
- if (singleReplicaHosts.length > 0 && !singleReplicaHosts.includes(host)) {
46
+ if (singleReplicaHosts.length > 0)
52
47
  currentPort += singleReplicaHosts.reduce((accumulator, currentValue) => accumulator + currentValue.replicas, 0);
53
- }
54
48
  const rootHostPath = `/public/${host}`;
55
49
  for (const path of Object.keys(confServer[host])) {
56
50
  confServer[host][path].port = newInstance(currentPort);
@@ -69,9 +63,17 @@ const buildRuntime = async () => {
69
63
  singleReplica,
70
64
  replicas,
71
65
  valkey,
66
+ apiBaseHost,
72
67
  } = confServer[host][path];
73
68
 
74
- if (singleReplica && replicas && replicas.length > 0 && !singleReplicaHosts.includes(host)) {
69
+ const { redirectTarget, singleReplicaHost } = await getInstanceContext({
70
+ redirect,
71
+ singleReplicaHosts,
72
+ singleReplica,
73
+ replicas,
74
+ });
75
+
76
+ if (singleReplicaHost) {
75
77
  singleReplicaHosts.push({
76
78
  host,
77
79
  replicas: replicas.length,
@@ -88,161 +90,7 @@ const buildRuntime = async () => {
88
90
  apis,
89
91
  };
90
92
 
91
- const redirectTarget = redirect
92
- ? redirect[redirect.length - 1] === '/'
93
- ? redirect.slice(0, -1)
94
- : redirect
95
- : undefined;
96
-
97
- // if (redirect) logger.info('redirect', new URL(redirect));
98
-
99
93
  switch (runtime) {
100
- case 'lampp':
101
- if (!Lampp.enabled()) continue;
102
- if (!Lampp.ports.includes(port)) Lampp.ports.push(port);
103
- if (currentPort === initPort) Lampp.removeRouter();
104
- Lampp.appendRouter(`
105
-
106
- Listen ${port}
107
-
108
- <VirtualHost *:${port}>
109
- DocumentRoot "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}"
110
- ServerName ${host}:${port}
111
-
112
- <Directory "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}">
113
- Options Indexes FollowSymLinks MultiViews
114
- AllowOverride All
115
- Require all granted
116
- </Directory>
117
-
118
- ${
119
- redirect
120
- ? `
121
- RewriteEngine on
122
-
123
- RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge
124
- RewriteRule ^(.*)$ ${redirectTarget}%{REQUEST_URI} [R=302,L]
125
- `
126
- : ''
127
- }
128
-
129
- ErrorDocument 400 ${path === '/' ? '' : path}/400.html
130
- ErrorDocument 404 ${path === '/' ? '' : path}/400.html
131
- ErrorDocument 500 ${path === '/' ? '' : path}/500.html
132
- ErrorDocument 502 ${path === '/' ? '' : path}/500.html
133
- ErrorDocument 503 ${path === '/' ? '' : path}/500.html
134
- ErrorDocument 504 ${path === '/' ? '' : path}/500.html
135
-
136
- </VirtualHost>
137
-
138
- `);
139
- // ERR too many redirects:
140
- // Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
141
- // Check: wp-config.php
142
- // if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
143
- // $_SERVER['HTTPS'] = 'on';
144
- // }
145
- // For plugins:
146
- // define( 'FS_METHOD', 'direct' );
147
-
148
- // ErrorDocument 404 /custom_404.html
149
- // ErrorDocument 500 /custom_50x.html
150
- // ErrorDocument 502 /custom_50x.html
151
- // ErrorDocument 503 /custom_50x.html
152
- // ErrorDocument 504 /custom_50x.html
153
-
154
- // Respond When Error Pages are Directly Requested
155
-
156
- // <Files "custom_404.html">
157
- // <If "-z %{ENV:REDIRECT_STATUS}">
158
- // RedirectMatch 404 ^/custom_404.html$
159
- // </If>
160
- // </Files>
161
-
162
- // <Files "custom_50x.html">
163
- // <If "-z %{ENV:REDIRECT_STATUS}">
164
- // RedirectMatch 404 ^/custom_50x.html$
165
- // </If>
166
- // </Files>
167
-
168
- // Add www or https with htaccess rewrite
169
-
170
- // Options +FollowSymLinks
171
- // RewriteEngine On
172
- // RewriteCond %{HTTP_HOST} ^ejemplo.com [NC]
173
- // RewriteRule ^(.*)$ http://ejemplo.com/$1 [R=301,L]
174
-
175
- // Redirect http to https with htaccess rewrite
176
-
177
- // RewriteEngine On
178
- // RewriteCond %{SERVER_PORT} 80
179
- // RewriteRule ^(.*)$ https://www.ejemplo.com/$1 [R,L]
180
-
181
- // Redirect to HTTPS with www subdomain
182
-
183
- // RewriteEngine On
184
- // RewriteCond %{HTTPS} off [OR]
185
- // RewriteCond %{HTTP_HOST} ^www\. [NC]
186
- // RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
187
- // RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
188
-
189
- await UnderpostStartUp.API.listenPortController(
190
- UnderpostStartUp.API.listenServerFactory(),
191
- port,
192
- runningData,
193
- );
194
- break;
195
- case 'xampp':
196
- if (!Xampp.enabled()) continue;
197
- if (!Xampp.ports.includes(port)) Xampp.ports.push(port);
198
- if (currentPort === initPort) Xampp.removeRouter();
199
- Xampp.appendRouter(`
200
-
201
- Listen ${port}
202
-
203
- <VirtualHost *:${port}>
204
- DocumentRoot "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}"
205
- ServerName ${host}:${port}
206
-
207
- <Directory "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}">
208
- Options Indexes FollowSymLinks MultiViews
209
- AllowOverride All
210
- Require all granted
211
- </Directory>
212
-
213
- ${
214
- redirect
215
- ? `
216
- RewriteEngine on
217
-
218
- RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge
219
- RewriteRule ^(.*)$ ${redirectTarget}%{REQUEST_URI} [R=302,L]
220
- `
221
- : ''
222
- }
223
-
224
- ErrorDocument 400 ${path === '/' ? '' : path}/400.html
225
- ErrorDocument 404 ${path === '/' ? '' : path}/400.html
226
- ErrorDocument 500 ${path === '/' ? '' : path}/500.html
227
- ErrorDocument 502 ${path === '/' ? '' : path}/500.html
228
- ErrorDocument 503 ${path === '/' ? '' : path}/500.html
229
- ErrorDocument 504 ${path === '/' ? '' : path}/500.html
230
-
231
- </VirtualHost>
232
-
233
- `);
234
- // ERR too many redirects:
235
- // Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
236
- // Check: wp-config.php
237
- // if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
238
- // $_SERVER['HTTPS'] = 'on';
239
- // }
240
- await UnderpostStartUp.API.listenPortController(
241
- UnderpostStartUp.API.listenServerFactory(),
242
- port,
243
- runningData,
244
- );
245
- break;
246
94
  case 'nodejs':
247
95
  const app = express();
248
96
 
@@ -269,9 +117,6 @@ const buildRuntime = async () => {
269
117
  // set logger
270
118
  app.use(loggerMiddleware(import.meta));
271
119
 
272
- // instance public static
273
- app.use('/', express.static(directory ? directory : `.${rootHostPath}`));
274
-
275
120
  // js src compression
276
121
  app.use(compression({ filter: shouldCompress }));
277
122
  function shouldCompress(req, res) {
@@ -316,14 +161,15 @@ const buildRuntime = async () => {
316
161
  return next();
317
162
  });
318
163
 
319
- // cors
320
- const originPayload = {
164
+ // instance public static
165
+ app.use('/', express.static(directory ? directory : `.${rootHostPath}`));
166
+
167
+ // security
168
+ applySecurity(app, {
321
169
  origin: origins.concat(
322
170
  apis && process.env.NODE_ENV === 'development' ? [`http://localhost:${currentPort + 2}`] : [],
323
171
  ),
324
- };
325
- // logger.info('originPayload', originPayload);
326
- app.use(cors(originPayload));
172
+ });
327
173
 
328
174
  if (redirect) {
329
175
  app.use(function (req = express.Request, res = express.Response, next = express.NextFunction) {
@@ -343,145 +189,147 @@ const buildRuntime = async () => {
343
189
  await UnderpostStartUp.API.listenPortController(app, port, runningData);
344
190
  break;
345
191
  }
192
+ // instance server
193
+ const server = createServer({}, app);
194
+ if (peer) currentPort++;
346
195
 
347
- const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
348
- if (fs.existsSync(swaggerJsonPath)) {
349
- // logger.info('Build swagger serve', swaggerJsonPath);
350
-
351
- const swaggerInstance =
352
- (swaggerDoc) =>
353
- (...args) =>
354
- swaggerUi.setup(swaggerDoc)(...args);
196
+ if (!apiBaseHost) {
197
+ const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
198
+ if (fs.existsSync(swaggerJsonPath)) {
199
+ // logger.info('Build swagger serve', swaggerJsonPath);
355
200
 
356
- const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
201
+ const swaggerInstance =
202
+ (swaggerDoc) =>
203
+ (...args) =>
204
+ swaggerUi.setup(swaggerDoc)(...args);
357
205
 
358
- app.use(`${path === '/' ? `/api-docs` : `${path}/api-docs`}`, swaggerUi.serve, swaggerInstance(swaggerDoc));
359
- }
206
+ const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
360
207
 
361
- if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
208
+ app.use(
209
+ `${path === '/' ? `/api-docs` : `${path}/api-docs`}`,
210
+ swaggerUi.serve,
211
+ swaggerInstance(swaggerDoc),
212
+ );
213
+ }
362
214
 
363
- // valkey server
364
- if (valkey) await createValkeyConnection({ host, path }, valkey);
215
+ if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
365
216
 
366
- if (mailer) {
367
- const mailerSsrConf = confSSR[getCapVariableName(client)];
368
- await MailerProvider.load({
369
- id: `${host}${path}`,
370
- meta: `mailer-${host}${path}`,
371
- host,
372
- path,
373
- ...mailer,
374
- templates: mailerSsrConf ? mailerSsrConf.mailer : {},
375
- });
376
- }
377
- if (apis) {
378
- const apiPath = `${path === '/' ? '' : path}/${process.env.BASE_API}`;
379
- for (const api of apis)
380
- await (async () => {
381
- const { ApiRouter } = await import(`../api/${api}/${api}.router.js`);
382
- const router = ApiRouter({ host, path, apiPath, mailer, db });
383
- // router.use(cors({ origin: origins }));
384
- // logger.info('Load api router', { host, path: apiPath, api });
385
- app.use(`${apiPath}/${api}`, router);
386
- })();
387
- }
217
+ // valkey server
218
+ if (valkey) await createValkeyConnection({ host, path }, valkey);
388
219
 
389
- const Render = await ssrFactory();
390
- const ssrPath = path === '/' ? path : `${path}/`;
391
-
392
- const defaultHtmlSrc404 = Render({
393
- title: '404 Not Found',
394
- ssrPath,
395
- ssrHeadComponents: '',
396
- ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/404.js`))(),
397
- renderPayload: {
398
- apiBasePath: process.env.BASE_API,
399
- version: Underpost.version,
400
- },
401
- renderApi: {
402
- JSONweb,
403
- },
404
- });
405
- const path404 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/404/index.html`;
406
- const page404 = fs.existsSync(path404) ? `${path === '/' ? '' : path}/404` : undefined;
407
- app.use(function (req, res, next) {
408
- if (page404) return res.status(404).redirect(page404);
409
- else {
410
- res.set('Content-Type', 'text/html');
411
- return res.status(404).send(defaultHtmlSrc404);
220
+ if (mailer) {
221
+ const mailerSsrConf = confSSR[getCapVariableName(client)];
222
+ await MailerProvider.load({
223
+ id: `${host}${path}`,
224
+ meta: `mailer-${host}${path}`,
225
+ host,
226
+ path,
227
+ ...mailer,
228
+ templates: mailerSsrConf ? mailerSsrConf.mailer : {},
229
+ });
412
230
  }
413
- });
414
-
415
- const defaultHtmlSrc500 = Render({
416
- title: '500 Server Error',
417
- ssrPath,
418
- ssrHeadComponents: '',
419
- ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/500.js`))(),
420
- renderPayload: {
421
- apiBasePath: process.env.BASE_API,
422
- version: Underpost.version,
423
- },
424
- renderApi: {
425
- JSONweb,
426
- },
427
- });
428
- const path500 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/500/index.html`;
429
- const page500 = fs.existsSync(path500) ? `${path === '/' ? '' : path}/500` : undefined;
430
- app.use(function (err, req, res, next) {
431
- logger.error(err, err.stack);
432
- if (page500) return res.status(500).redirect(page500);
433
- else {
434
- res.set('Content-Type', 'text/html');
435
- return res.status(500).send(defaultHtmlSrc500);
231
+ if (apis) {
232
+ const authMiddleware = authMiddlewareFactory({ host, path });
233
+
234
+ const apiPath = `${path === '/' ? '' : path}/${process.env.BASE_API}`;
235
+ for (const api of apis)
236
+ await (async () => {
237
+ const { ApiRouter } = await import(`../api/${api}/${api}.router.js`);
238
+ const router = ApiRouter({ host, path, apiPath, mailer, db, authMiddleware, origins });
239
+ // router.use(cors({ origin: origins }));
240
+ // logger.info('Load api router', { host, path: apiPath, api });
241
+ app.use(`${apiPath}/${api}`, router);
242
+ })();
436
243
  }
437
- });
438
244
 
439
- // instance server
440
- const server = createServer({}, app);
245
+ if (ws)
246
+ await (async () => {
247
+ const { createIoServer } = await import(`../ws/${ws}/${ws}.ws.server.js`);
248
+ // logger.info('Load socket.io ws router', { host, ws });
249
+ // start socket.io
250
+ const { options, meta } = await createIoServer(server, {
251
+ host,
252
+ path,
253
+ db,
254
+ port,
255
+ origins,
256
+ });
257
+ await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), port, {
258
+ runtime: 'nodejs',
259
+ client: null,
260
+ host,
261
+ path: options.path,
262
+ meta,
263
+ });
264
+ })();
441
265
 
442
- if (ws)
443
- await (async () => {
444
- const { createIoServer } = await import(`../ws/${ws}/${ws}.ws.server.js`);
445
- // logger.info('Load socket.io ws router', { host, ws });
446
- // start socket.io
447
- const { options, meta } = await createIoServer(server, {
266
+ if (peer) {
267
+ const peerPort = newInstance(currentPort);
268
+ const { options, meta, peerServer } = await createPeerServer({
269
+ port: peerPort,
270
+ devPort: port,
271
+ origins,
448
272
  host,
449
273
  path,
450
- db,
451
- port,
452
- origins,
453
274
  });
454
- await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), port, {
275
+
276
+ await UnderpostStartUp.API.listenPortController(peerServer, peerPort, {
455
277
  runtime: 'nodejs',
456
278
  client: null,
457
279
  host,
458
280
  path: options.path,
459
281
  meta,
460
282
  });
461
- })();
283
+ }
284
+ }
462
285
 
463
- if (peer) {
464
- currentPort++;
465
- const peerPort = newInstance(currentPort);
466
- const { options, meta, peerServer } = await createPeerServer({
467
- port: peerPort,
468
- devPort: port,
469
- origins,
286
+ // load ssr
287
+ const ssr = await ssrMiddlewareFactory({ app, directory, rootHostPath, path });
288
+ for (const [_, ssrMiddleware] of Object.entries(ssr)) app.use(ssrMiddleware);
289
+
290
+ await UnderpostStartUp.API.listenPortController(server, port, runningData);
291
+
292
+ break;
293
+
294
+ case 'lampp':
295
+ {
296
+ const { disabled } = await Lampp.createApp({
297
+ port,
470
298
  host,
471
299
  path,
300
+ directory,
301
+ rootHostPath,
302
+ redirect,
303
+ redirectTarget,
304
+ resetRouter: currentPort === initPort,
472
305
  });
473
-
474
- await UnderpostStartUp.API.listenPortController(peerServer, peerPort, {
475
- runtime: 'nodejs',
476
- client: null,
306
+ if (disabled) continue;
307
+ await UnderpostStartUp.API.listenPortController(
308
+ UnderpostStartUp.API.listenServerFactory(),
309
+ port,
310
+ runningData,
311
+ );
312
+ }
313
+ break;
314
+ case 'xampp':
315
+ {
316
+ const { disabled } = await Xampp.createApp({
317
+ port,
477
318
  host,
478
- path: options.path,
479
- meta,
319
+ path,
320
+ directory,
321
+ rootHostPath,
322
+ redirect,
323
+ redirectTarget,
324
+ resetRouter: currentPort === initPort,
480
325
  });
326
+ if (disabled) continue;
327
+ await UnderpostStartUp.API.listenPortController(
328
+ UnderpostStartUp.API.listenServerFactory(),
329
+ port,
330
+ runningData,
331
+ );
481
332
  }
482
-
483
- await UnderpostStartUp.API.listenPortController(server, port, runningData);
484
-
485
333
  break;
486
334
  default:
487
335
  break;
package/src/server/ssl.js CHANGED
@@ -50,8 +50,7 @@ const buildSSL = async (host) => {
50
50
 
51
51
  fs.writeFileSync(`./engine-private/ssl/${host}/_ca_bundle.crt`, ca, 'utf8');
52
52
  fs.writeFileSync(`./engine-private/ssl/${host}/_ca_full_bundle.crt`, caFull, 'utf8');
53
- // TODO: no repeat folderHost match
54
- // fs.removeSync(`${sslPath}/${folderHost}`);
53
+
55
54
  return true;
56
55
  }
57
56
  }
@@ -0,0 +1,85 @@
1
+ import fs from 'fs-extra';
2
+ import dotenv from 'dotenv';
3
+ import Underpost from '../index.js';
4
+
5
+ import { ssrFactory, JSONweb } from './client-formatted.js';
6
+ import { loggerFactory } from './logger.js';
7
+ import { getRootDirectory } from './process.js';
8
+
9
+ dotenv.config();
10
+
11
+ const logger = loggerFactory(import.meta);
12
+
13
+ const ssrMiddlewareFactory = async ({ app, directory, rootHostPath, path }) => {
14
+ const Render = await ssrFactory();
15
+ const ssrPath = path === '/' ? path : `${path}/`;
16
+
17
+ // Build default html src for 404 and 500
18
+
19
+ const defaultHtmlSrc404 = Render({
20
+ title: '404 Not Found',
21
+ ssrPath,
22
+ ssrHeadComponents: '',
23
+ ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/404.js`))(),
24
+ renderPayload: {
25
+ apiBasePath: process.env.BASE_API,
26
+ version: Underpost.version,
27
+ },
28
+ renderApi: {
29
+ JSONweb,
30
+ },
31
+ });
32
+ const path404 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/404/index.html`;
33
+ const page404 = fs.existsSync(path404) ? `${path === '/' ? '' : path}/404` : undefined;
34
+
35
+ const defaultHtmlSrc500 = Render({
36
+ title: '500 Server Error',
37
+ ssrPath,
38
+ ssrHeadComponents: '',
39
+ ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/500.js`))(),
40
+ renderPayload: {
41
+ apiBasePath: process.env.BASE_API,
42
+ version: Underpost.version,
43
+ },
44
+ renderApi: {
45
+ JSONweb,
46
+ },
47
+ });
48
+ const path500 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/500/index.html`;
49
+ const page500 = fs.existsSync(path500) ? `${path === '/' ? '' : path}/500` : undefined;
50
+
51
+ const sanitizeHtml = (res, req, html) => {
52
+ const nonce = res.locals.nonce;
53
+
54
+ return html
55
+ .replace(/<script(?=\s|>)/gi, `<script nonce="${nonce}"`)
56
+ .replace(/<style(?=\s|>)/gi, `<style nonce="${nonce}"`);
57
+ };
58
+
59
+ return {
60
+ error500: function (err, req, res, next) {
61
+ logger.error(err, err.stack);
62
+ if (page500) return res.status(500).redirect(page500);
63
+ else {
64
+ res.set('Content-Type', 'text/html');
65
+ return res.status(500).send(sanitizeHtml(res, req, defaultHtmlSrc500));
66
+ }
67
+ },
68
+ error400: function (req, res, next) {
69
+ // if /<path>/home redirect to /<path>
70
+ const homeRedirectPath = `${path === '/' ? '' : path}/home`;
71
+ if (req.url.startsWith(homeRedirectPath)) {
72
+ const redirectUrl = req.url.replace('/home', '');
73
+ return res.redirect(redirectUrl.startsWith('/') ? redirectUrl : `/${redirectUrl}`);
74
+ }
75
+
76
+ if (page404) return res.status(404).redirect(page404);
77
+ else {
78
+ res.set('Content-Type', 'text/html');
79
+ return res.status(404).send(sanitizeHtml(res, req, defaultHtmlSrc404));
80
+ }
81
+ },
82
+ };
83
+ };
84
+
85
+ export { ssrMiddlewareFactory };
@@ -86,9 +86,9 @@ class UnderpostStartUp {
86
86
  async build(deployId = 'dd-default', env = 'development') {
87
87
  const buildBasePath = `/home/dd`;
88
88
  const repoName = `engine-${deployId.split('-')[1]}`;
89
- shellExec(`cd ${buildBasePath} && underpost clone underpostnet/${repoName}`);
89
+ shellExec(`cd ${buildBasePath} && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}`);
90
90
  shellExec(`cd ${buildBasePath} && sudo mv ./${repoName} ./engine`);
91
- shellExec(`cd ${buildBasePath}/engine && underpost clone underpostnet/${repoName}-private`);
91
+ shellExec(`cd ${buildBasePath}/engine && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}-private`);
92
92
  shellExec(`cd ${buildBasePath}/engine && sudo mv ./${repoName}-private ./engine-private`);
93
93
  shellCd(`${buildBasePath}/engine`);
94
94
  shellExec(`npm install`);
@@ -107,12 +107,12 @@ class UnderpostStartUp {
107
107
  for (const replica of replicas) {
108
108
  if (!replica.match(deployId)) continue;
109
109
  shellExec(`node bin/deploy conf ${replica} ${env}`);
110
- shellExec(`npm ${runCmd} deploy deploy-id:${replica}`, { async: true });
110
+ shellExec(`npm ${runCmd} ${replica}`, { async: true });
111
111
  await awaitDeployMonitor(true);
112
112
  }
113
113
  }
114
114
  shellExec(`node bin/deploy conf ${deployId} ${env}`);
115
- shellExec(`npm ${runCmd} deploy deploy-id:${deployId}`, { async: true });
115
+ shellExec(`npm ${runCmd} ${deployId}`, { async: true });
116
116
  await awaitDeployMonitor(true);
117
117
  UnderpostRootEnv.API.set('container-status', `${deployId}-${env}-running-deployment`);
118
118
  },
@@ -148,7 +148,7 @@ const updateValkeyObject = async (options = { host: '', path: '' }, key = '', pa
148
148
  return await setValkeyObject(options, key, { ...base, ...payload });
149
149
  };
150
150
 
151
- const valkeyObjectFactory = async (options = { host: 'localhost', object: {} }, model = '') => {
151
+ const valkeyObjectFactory = async (options = { host: 'localhost', path: '', object: {} }, model = '') => {
152
152
  const idoDate = new Date().toISOString();
153
153
  options.object = options.object || {};
154
154
  const { object } = options;
@@ -173,6 +173,7 @@ const valkeyObjectFactory = async (options = { host: 'localhost', object: {} },
173
173
  emailConfirmed: false,
174
174
  recoverTimeOut: null,
175
175
  lastLoginDate: null,
176
+ activeSessions: [],
176
177
  };
177
178
  }
178
179
  default: