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