underpost 2.7.83 → 2.7.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.github/workflows/ghpkg.yml +41 -1
  2. package/.github/workflows/pwa-microservices-template.page.yml +54 -0
  3. package/.vscode/settings.json +7 -0
  4. package/CHANGELOG.md +64 -16
  5. package/bin/cron.js +47 -0
  6. package/bin/db.js +60 -7
  7. package/bin/deploy.js +358 -26
  8. package/bin/file.js +18 -1
  9. package/bin/hwt.js +59 -0
  10. package/bin/index.js +1 -1
  11. package/bin/util.js +31 -1
  12. package/conf.js +46 -8
  13. package/docker-compose.yml +1 -1
  14. package/package.json +133 -133
  15. package/src/api/core/core.router.js +9 -9
  16. package/src/api/core/core.service.js +12 -4
  17. package/src/api/default/default.service.js +4 -4
  18. package/src/api/file/file.service.js +3 -3
  19. package/src/api/user/user.service.js +10 -8
  20. package/src/client/components/core/404.js +20 -0
  21. package/src/client/components/core/500.js +20 -0
  22. package/src/client/{ssr/common → components/core}/Alert.js +13 -11
  23. package/src/client/components/core/CommonJs.js +3 -0
  24. package/src/client/components/core/CssCore.js +30 -3
  25. package/src/client/components/core/Docs.js +110 -10
  26. package/src/client/components/core/LoadingAnimation.js +4 -2
  27. package/src/client/components/core/Modal.js +223 -22
  28. package/src/client/components/core/Panel.js +1 -1
  29. package/src/client/components/core/PanelForm.js +2 -1
  30. package/src/client/components/core/Responsive.js +34 -5
  31. package/src/client/components/core/RichText.js +4 -2
  32. package/src/client/components/core/Translate.js +21 -5
  33. package/src/client/components/core/VanillaJs.js +2 -1
  34. package/src/client/components/core/WebComponent.js +44 -0
  35. package/src/client/components/core/Worker.js +15 -18
  36. package/src/client/components/default/MenuDefault.js +68 -0
  37. package/src/client/components/default/RoutesDefault.js +2 -0
  38. package/src/client/public/default/plantuml/client-conf.svg +1 -1
  39. package/src/client/public/default/plantuml/client-schema.svg +1 -1
  40. package/src/client/public/default/plantuml/cron-conf.svg +1 -1
  41. package/src/client/public/default/plantuml/cron-schema.svg +1 -1
  42. package/src/client/public/default/plantuml/server-conf.svg +1 -1
  43. package/src/client/public/default/plantuml/server-schema.svg +1 -1
  44. package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
  45. package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
  46. package/src/client/public/default/site.webmanifest +69 -0
  47. package/src/client/ssr/Render.js +1 -6
  48. package/src/client/ssr/{components/body → body}/CacheControl.js +1 -1
  49. package/src/client/ssr/head/Production.js +1 -0
  50. package/src/client/ssr/head/Pwa.js +146 -0
  51. package/src/client/ssr/head/Seo.js +14 -0
  52. package/src/client/ssr/mailer/DefaultRecoverEmail.js +21 -0
  53. package/src/client/ssr/mailer/DefaultVerifyEmail.js +17 -0
  54. package/src/client/ssr/offline/NoNetworkConnection.js +65 -0
  55. package/src/client/ssr/pages/Test.js +196 -0
  56. package/src/client/ssr/pages/maintenance.js +14 -0
  57. package/src/client/ssr/pages/offline.js +21 -0
  58. package/src/client/sw/default.sw.js +44 -165
  59. package/src/db/DataBaseProvider.js +12 -1
  60. package/src/db/mongo/MongooseDB.js +0 -1
  61. package/src/mailer/EmailRender.js +2 -4
  62. package/src/mailer/MailerProvider.js +4 -1
  63. package/src/runtime/lampp/Lampp.js +9 -9
  64. package/src/server/backup.js +82 -70
  65. package/src/server/client-build.js +133 -155
  66. package/src/server/client-formatted.js +2 -4
  67. package/src/server/conf.js +114 -23
  68. package/src/server/crypto.js +91 -0
  69. package/src/server/dns.js +48 -16
  70. package/src/server/network.js +94 -7
  71. package/src/server/proxy.js +26 -28
  72. package/src/server/runtime.js +42 -12
  73. package/src/server/ssl.js +2 -2
  74. package/src/client/ssr/common/SsrCore.js +0 -91
  75. package/src/client/ssr/common/Translate.js +0 -26
  76. package/src/client/ssr/common/Worker.js +0 -28
  77. package/src/client/ssr/components/head/PwaDefault.js +0 -60
  78. package/src/client/ssr/offline/default.index.js +0 -31
  79. package/src/cron.js +0 -30
  80. package/src/server/cron.js +0 -35
  81. /package/src/client/ssr/{components/body → body}/DefaultSplashScreen.js +0 -0
  82. /package/src/client/ssr/{components/email → email}/DefaultRecoverEmail.js +0 -0
  83. /package/src/client/ssr/{components/email → email}/DefaultVerifyEmail.js +0 -0
  84. /package/src/client/ssr/{components/head → head}/Css.js +0 -0
  85. /package/src/client/ssr/{components/head → head}/DefaultScripts.js +0 -0
@@ -9,100 +9,112 @@ dotenv.config();
9
9
  const logger = loggerFactory(import.meta);
10
10
 
11
11
  const BackUpManagement = {
12
- repoUrl: `https://${process.env.GITHUB_BACKUP_TOKEN}@github.com/${process.env.GITHUB_BACKUP_USERNAME}/${process.env.GITHUB_BACKUP_REPO}.git`,
13
- Init: async function () {
14
- await this.Callback();
15
- return this.Callback;
16
- },
17
- Callback: async function () {
18
- const privateCronConfPath = `./engine-private/conf/${process.argv[2]}/conf.cron.json`;
12
+ repoUrl: `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USERNAME}/${process.env.GITHUB_BACKUP_REPO}.git`,
13
+ Init: async function ({ deployId }) {
14
+ const Callback = async function () {
15
+ const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
19
16
 
20
- const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
17
+ const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
21
18
 
22
- const { backups } = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
19
+ const { backups } = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
23
20
 
24
- if (!backups) return;
21
+ if (!backups) return;
25
22
 
26
- const currentDate = new Date().getTime();
23
+ logger.info('init backups callback');
24
+ await logger.setUpInfo();
27
25
 
28
- if (!fs.existsSync('./engine-private/cron-backups'))
29
- fs.mkdirSync('./engine-private/cron-backups', { recursive: true });
26
+ const currentDate = new Date().getTime();
30
27
 
31
- for (const deployGroupData of backups) {
32
- const { deployGroupId } = deployGroupData;
33
- const dataDeploy = getDataDeploy({ deployGroupId });
28
+ if (!fs.existsSync('./engine-private/cron-backups'))
29
+ fs.mkdirSync('./engine-private/cron-backups', { recursive: true });
34
30
 
35
- for (const deployObj of dataDeploy) {
36
- const { deployId, replicaHost } = deployObj;
31
+ for (const deployGroupData of backups) {
32
+ const { deployGroupId } = deployGroupData;
33
+ const dataDeploy = getDataDeploy({ deployGroupId });
37
34
 
38
- if (replicaHost) continue;
35
+ for (const deployObj of dataDeploy) {
36
+ const { deployId, replicaHost } = deployObj;
39
37
 
40
- const confServer = JSON.parse(
41
- fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
42
- ? fs.readFileSync(`./engine-private/replica/${deployId}/conf.server.json`, 'utf8')
43
- : fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
44
- );
38
+ if (replicaHost) continue;
45
39
 
46
- for (const host of Object.keys(confServer))
47
- for (const path of Object.keys(confServer[host])) {
48
- // retention policy
49
- let { db, backupFrequency, maxBackupRetention, singleReplica, wp, git, directory } = confServer[host][path];
40
+ const confServer = JSON.parse(
41
+ fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
42
+ ? fs.readFileSync(`./engine-private/replica/${deployId}/conf.server.json`, 'utf8')
43
+ : fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
44
+ );
50
45
 
51
- if (!db || singleReplica) continue;
46
+ for (const host of Object.keys(confServer))
47
+ for (const path of Object.keys(confServer[host])) {
48
+ // retention policy
49
+ let { db, backupFrequency, maxBackupRetention, singleReplica, wp, git, directory } =
50
+ confServer[host][path];
52
51
 
53
- if (!backupFrequency) backupFrequency = 'daily';
54
- if (!maxBackupRetention) maxBackupRetention = 5;
52
+ if (!db || singleReplica) continue;
55
53
 
56
- const backUpPath = `${process.cwd()}/engine-private/cron-backups/${getCronBackUpFolder(host, path)}`;
57
- if (!fs.existsSync(backUpPath)) fs.mkdirSync(`${backUpPath}`, { recursive: true });
58
- // .isDirectory()
59
- const files = await fs.readdir(backUpPath, { withFileTypes: true });
54
+ if (!backupFrequency) backupFrequency = 'daily';
55
+ if (!maxBackupRetention) maxBackupRetention = 5;
60
56
 
61
- const currentBackupsDirs = files
62
- .map((fileObj) => parseInt(fileObj.name))
63
- .sort((a, b) => a - b)
64
- .reverse();
57
+ const backUpPath = `${process.cwd()}/engine-private/cron-backups/${getCronBackUpFolder(host, path)}`;
58
+ if (!fs.existsSync(backUpPath)) fs.mkdirSync(`${backUpPath}`, { recursive: true });
59
+ // .isDirectory()
60
+ const files = await fs.readdir(backUpPath, { withFileTypes: true });
65
61
 
66
- switch (backupFrequency) {
67
- case 'daily':
62
+ const currentBackupsDirs = files
63
+ .map((fileObj) => parseInt(fileObj.name))
64
+ .sort((a, b) => a - b)
65
+ .reverse();
68
66
 
69
- default:
70
- // if (currentBackupsDirs[0] && currentDate - currentBackupsDirs[0] < 1000 * 60 * 60 * 24) continue;
71
- break;
72
- }
67
+ switch (backupFrequency) {
68
+ case 'daily':
73
69
 
74
- for (const retentionPath of currentBackupsDirs.filter((t, i) => i >= maxBackupRetention - 1)) {
75
- const removePathRetention = `${backUpPath}/${retentionPath}`;
76
- logger.info('Remove backup folder', removePathRetention);
77
- fs.removeSync(removePathRetention);
78
- }
70
+ default:
71
+ // if (currentBackupsDirs[0] && currentDate - currentBackupsDirs[0] < 1000 * 60 * 60 * 24) continue;
72
+ break;
73
+ }
74
+
75
+ for (const retentionPath of currentBackupsDirs.filter((t, i) => i >= maxBackupRetention - 1)) {
76
+ const removePathRetention = `${backUpPath}/${retentionPath}`;
77
+ logger.info('Remove backup folder', removePathRetention);
78
+ fs.removeSync(removePathRetention);
79
+ }
79
80
 
80
- fs.mkdirSync(`${backUpPath}/${currentDate}`, { recursive: true });
81
+ fs.mkdirSync(`${backUpPath}/${currentDate}`, { recursive: true });
81
82
 
82
- shellExec(`node bin/db ${host}${path} export ${deployId} ${backUpPath}/${currentDate}`);
83
+ shellExec(`node bin/db ${host}${path} export ${deployId} ${backUpPath}/${currentDate}`);
83
84
 
84
- if (wp) {
85
- const repoUrl = `https://${process.env.GITHUB_BACKUP_TOKEN}@github.com/${
86
- process.env.GITHUB_BACKUP_USERNAME
87
- }/${git.split('/').pop()}.git`;
85
+ if (wp) {
86
+ const repoUrl = `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USERNAME}/${git
87
+ .split('/')
88
+ .pop()}.git`;
88
89
 
89
- shellExec(
90
- `cd ${directory}` +
91
- ` && git pull ${repoUrl}` +
92
- ` && git add . && git commit -m "backup ${new Date().toLocaleDateString()}"` +
93
- ` && git push ${repoUrl}`,
94
- );
90
+ shellExec(
91
+ `cd ${directory}` +
92
+ ` && git pull ${repoUrl}` +
93
+ ` && git add . && git commit -m "backup ${new Date().toLocaleDateString()}"` +
94
+ ` && git push ${repoUrl}`,
95
+ {
96
+ disableLog: true,
97
+ },
98
+ );
99
+ }
95
100
  }
96
- }
101
+ }
97
102
  }
98
- }
99
- shellExec(
100
- `cd ./engine-private/cron-backups` +
101
- ` && git pull ${BackUpManagement.repoUrl}` +
102
- ` && git add . && git commit -m "backup ${new Date().toLocaleDateString()}"` +
103
- ` && git push ${BackUpManagement.repoUrl}`,
104
- );
103
+ shellExec(
104
+ `cd ./engine-private/cron-backups` +
105
+ ` && git pull ${BackUpManagement.repoUrl}` +
106
+ ` && git add . && git commit -m "backup ${new Date().toLocaleDateString()}"` +
107
+ ` && git push ${BackUpManagement.repoUrl}`,
108
+ {
109
+ disableLog: true,
110
+ },
111
+ );
112
+ };
113
+ await Callback();
114
+ BackUpManagement.Callback = Callback;
115
+ return Callback;
105
116
  },
117
+ Callback: async function (params) {},
106
118
  };
107
119
 
108
120
  export { BackUpManagement };
@@ -1,9 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  import fs from 'fs-extra';
4
- import { srcFormatted, componentFormatted, viewFormatted, ssrFactory } from './client-formatted.js';
4
+ import { srcFormatted, componentFormatted, viewFormatted, ssrFactory, JSONweb } from './client-formatted.js';
5
5
  import { loggerFactory } from './logger.js';
6
- import { cap, newInstance, orderArrayFromAttrInt, titleFormatted } from '../client/components/core/CommonJs.js';
6
+ import {
7
+ cap,
8
+ getCapVariableName,
9
+ newInstance,
10
+ orderArrayFromAttrInt,
11
+ titleFormatted,
12
+ uniqueArray,
13
+ } from '../client/components/core/CommonJs.js';
7
14
  import UglifyJS from 'uglify-js';
8
15
  import { minify } from 'html-minifier-terser';
9
16
  import dotenv from 'dotenv';
@@ -40,10 +47,22 @@ const fullBuild = async ({
40
47
  }) => {
41
48
  logger.warn('Full build', rootClientPath);
42
49
 
43
- fs.removeSync(rootClientPath);
44
-
45
50
  buildAcmeChallengePath(acmeChallengeFullPath);
46
51
 
52
+ if (publicClientId && publicClientId.startsWith('html-website-templates')) {
53
+ if (!fs.existsSync(`/dd/html-website-templates/`))
54
+ shellExec(`cd /dd && git clone https://github.com/designmodo/html-website-templates.git`);
55
+ if (!fs.existsSync(`${rootClientPath}/index.php`)) {
56
+ fs.copySync(`/dd/html-website-templates/${publicClientId.split('-publicClientId-')[1]}`, rootClientPath);
57
+ shellExec(`cd ${rootClientPath} && git init && git add . && git commit -m "Base template implementation"`);
58
+ // git remote add origin git@github.com:<username>/<repo>.git
59
+ fs.writeFileSync(`${rootClientPath}/.git/.htaccess`, `Deny from all`, 'utf8');
60
+ }
61
+ return;
62
+ }
63
+
64
+ fs.removeSync(rootClientPath);
65
+
47
66
  if (fs.existsSync(`./src/client/public/${publicClientId}`)) {
48
67
  if (iconsBuild) {
49
68
  const defaultBaseIconFolderPath = `src/client/public/${publicClientId}/assets/logo`;
@@ -52,7 +71,7 @@ const fullBuild = async ({
52
71
  if (!fs.existsSync(defaultBaseIconPath))
53
72
  await buildTextImg(metadata.title, { debugFilename: defaultBaseIconPath });
54
73
 
55
- if (path === '/' && !fs.existsSync(`./src/client/public/${publicClientId}/site.webmanifest`))
74
+ if (!fs.existsSync(`./src/client/public/${publicClientId}/site.webmanifest`))
56
75
  await buildIcons({ publicClientId, metadata });
57
76
  }
58
77
  fs.copySync(
@@ -89,8 +108,15 @@ const fullBuild = async ({
89
108
  if (dists)
90
109
  for (const dist of dists) {
91
110
  if ('folder' in dist) {
92
- fs.mkdirSync(`${rootClientPath}${dist.public_folder}`, { recursive: true });
93
- fs.copySync(dist.folder, `${rootClientPath}${dist.public_folder}`);
111
+ if (fs.statSync(dist.folder).isDirectory()) {
112
+ fs.mkdirSync(`${rootClientPath}${dist.public_folder}`, { recursive: true });
113
+ fs.copySync(dist.folder, `${rootClientPath}${dist.public_folder}`);
114
+ } else {
115
+ const folder = dist.public_folder.split('/');
116
+ folder.pop();
117
+ fs.mkdirSync(`${rootClientPath}${folder.join('/')}`, { recursive: true });
118
+ fs.copyFileSync(dist.folder, `${rootClientPath}${dist.public_folder}`);
119
+ }
94
120
  }
95
121
  if ('styles' in dist) {
96
122
  fs.mkdirSync(`${rootClientPath}${dist.public_styles_folder}`, { recursive: true });
@@ -112,16 +138,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
112
138
  const enableLiveRebuild =
113
139
  options && options.liveClientBuildPaths && options.liveClientBuildPaths.length > 0 ? true : false;
114
140
 
115
- // common ssr components
116
- let jsSsrCommonComponents = '';
117
- {
118
- const files = await fs.readdir(`./src/client/ssr/common`);
119
- for (const relativePath of files)
120
- jsSsrCommonComponents += await srcFormatted(
121
- fs.readFileSync(`./src/client/ssr/common/${relativePath}`, 'utf8').split('export')[0],
122
- );
123
- }
124
-
125
141
  let currentPort = parseInt(process.env.PORT) + 1;
126
142
  for (const host of Object.keys(confServer)) {
127
143
  const paths = orderArrayFromAttrInt(Object.keys(confServer[host]), 'length', 'asc');
@@ -148,6 +164,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
148
164
  apiBaseHost,
149
165
  ttiLoadTimeLimit,
150
166
  singleReplica,
167
+ offlineBuild,
151
168
  } = confServer[host][path];
152
169
  if (singleReplica) continue;
153
170
  if (!confClient[client]) confClient[client] = {};
@@ -188,7 +205,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
188
205
  iconsBuild,
189
206
  metadata,
190
207
  });
191
- if (apis)
208
+ if (apis && false)
192
209
  for (const apiBuildScript of apis) {
193
210
  const scriptPath = `src/api/${apiBuildScript}/${apiBuildScript}.build.js`;
194
211
  if (fs.existsSync(`./${scriptPath}`)) {
@@ -248,8 +265,13 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
248
265
  'const getBaseHost = () => location.host;',
249
266
  `const getBaseHost = () => '${apiBaseHost}';`,
250
267
  );
251
- if (apiBaseProxyPath)
268
+ if (apiBaseProxyPath) {
252
269
  jsSrc = jsSrc.replace('${getProxyPath()}api/', `${apiBaseProxyPath}${process.env.BASE_API}/`);
270
+ jsSrc = jsSrc.replace(
271
+ "const getWsBasePath = () => (getProxyPath() !== '/' ? `${getProxyPath()}socket.io/` : undefined);",
272
+ `const getWsBasePath = () => '${apiBaseProxyPath}socket.io/';`,
273
+ );
274
+ }
253
275
  }
254
276
  fs.writeFileSync(
255
277
  jsPublicPath,
@@ -284,87 +306,22 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
284
306
 
285
307
  const buildId = `${client}.index`;
286
308
  const siteMapLinks = [];
287
- let Render = () => '';
288
- eval(await srcFormatted(fs.readFileSync(`./src/client/ssr/Render.js`, 'utf8')));
309
+ const ssrPath = path === '/' ? path : `${path}/`;
310
+ const Render = await ssrFactory();
289
311
 
290
312
  if (views) {
291
- const buildJsSrcPage = async (jsSrcPath, jsPublicPath) => {
292
- if (!(enableLiveRebuild && !options.liveClientBuildPaths.find((p) => p.srcBuildPath === jsSrcPath))) {
293
- let jsSrc = viewFormatted(await srcFormatted(fs.readFileSync(jsSrcPath, 'utf8')), dists, path, baseHost);
294
- if (jsSrc.split('/*imports*/')[1]) jsSrc = jsSrc.split('/*imports*/')[1];
313
+ const jsSrcPath = fs.existsSync(`./src/client/sw/${publicClientId}.sw.js`)
314
+ ? `./src/client/sw/${publicClientId}.sw.js`
315
+ : `./src/client/sw/default.sw.js`;
295
316
 
296
- fs.writeFileSync(
297
- jsPublicPath,
298
- minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
299
- 'utf8',
300
- );
301
- }
302
- };
317
+ const jsPublicPath = `${rootClientPath}/sw.js`;
303
318
 
304
- if (path === '/') {
305
- // service woker
306
- await buildJsSrcPage(
307
- fs.existsSync(`./src/client/sw/${publicClientId}.sw.js`)
308
- ? `./src/client/sw/${publicClientId}.sw.js`
309
- : `./src/client/sw/default.sw.js`,
310
- `${rootClientPath}/sw.js`,
311
- );
312
- }
313
-
314
- // offline html
315
- {
316
- await buildJsSrcPage(
317
- fs.existsSync(`./src/client/ssr/offline/${publicClientId}.index.js`)
318
- ? `./src/client/ssr/offline/${publicClientId}.index.js`
319
- : `./src/client/ssr/offline/default.index.js`,
320
- `${rootClientPath}/offline.js`,
321
- );
322
-
323
- const htmlSrc = Render({
324
- title: metadata?.title ? metadata.title : cap(client),
325
- ssrPath: '/',
326
- ssrHeadComponents: '',
327
- ssrBodyComponents: '',
328
- baseSsrLib: jsSsrCommonComponents + fs.readFileSync(`${rootClientPath}/offline.js`, 'utf8'),
329
- });
319
+ if (!(enableLiveRebuild && !options.liveClientBuildPaths.find((p) => p.srcBuildPath === jsSrcPath))) {
320
+ const jsSrc = viewFormatted(await srcFormatted(fs.readFileSync(jsSrcPath, 'utf8')), dists, path, baseHost);
330
321
 
331
322
  fs.writeFileSync(
332
- `${rootClientPath}offline.html`,
333
- minifyBuild || process.env.NODE_ENV === 'production'
334
- ? await minify(htmlSrc, {
335
- minifyCSS: true,
336
- minifyJS: true,
337
- collapseBooleanAttributes: true,
338
- collapseInlineTagWhitespace: true,
339
- collapseWhitespace: true,
340
- })
341
- : htmlSrc,
342
- 'utf8',
343
- );
344
- }
345
- // ssr pages
346
- for (const page of await fs.readdir('./src/client/ssr/pages')) {
347
- await buildJsSrcPage(`./src/client/ssr/pages/${page}`, `${rootClientPath}/${page}`);
348
-
349
- const htmlSrc = Render({
350
- title: metadata?.title ? metadata.title : cap(client),
351
- ssrPath: '/',
352
- ssrHeadComponents: '',
353
- ssrBodyComponents: '',
354
- baseSsrLib: jsSsrCommonComponents + fs.readFileSync(`${rootClientPath}/${page}`, 'utf8'),
355
- });
356
-
357
- fs.writeFileSync(
358
- `${rootClientPath}${page.slice(0, -3)}.html`,
359
- minifyBuild || process.env.NODE_ENV === 'production'
360
- ? await minify(htmlSrc, {
361
- minifyCSS: true,
362
- minifyJS: true,
363
- collapseBooleanAttributes: true,
364
- collapseInlineTagWhitespace: true,
365
- collapseWhitespace: true,
366
- })
367
- : htmlSrc,
323
+ jsPublicPath,
324
+ minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
368
325
  'utf8',
369
326
  );
370
327
  }
@@ -410,7 +367,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
410
367
  const canonicalURL = `https://${host}${path}${
411
368
  view.path === '/' ? (path === '/' ? '' : '/') : path === '/' ? `${view.path.slice(1)}/` : `${view.path}/`
412
369
  }`;
413
- const ssrPath = path === '/' ? path : `${path}/`;
414
370
 
415
371
  let ssrHeadComponents = ``;
416
372
  let ssrBodyComponents = ``;
@@ -420,10 +376,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
420
376
  confSSR[view.ssr].head.unshift('Production');
421
377
 
422
378
  for (const ssrHeadComponent of confSSR[view.ssr].head) {
423
- const SrrComponent = await ssrFactory(
424
- `./src/client/ssr/components/head/${ssrHeadComponent}.js`,
425
- jsSsrCommonComponents,
426
- );
379
+ const SrrComponent = await ssrFactory(`./src/client/ssr/head/${ssrHeadComponent}.js`);
427
380
 
428
381
  switch (ssrHeadComponent) {
429
382
  case 'Pwa':
@@ -432,7 +385,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
432
385
  fs.existsSync(`./src/client/public/${publicClientId}/browserconfig.xml`) &&
433
386
  fs.existsSync(`./src/client/public/${publicClientId}/site.webmanifest`);
434
387
 
435
- if (view.path === '/' && validPwaBuild) {
388
+ if (validPwaBuild) {
436
389
  // build webmanifest
437
390
  const webmanifestJson = JSON.parse(
438
391
  fs.readFileSync(`./src/client/public/${publicClientId}/site.webmanifest`, 'utf8'),
@@ -504,10 +457,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
504
457
  }
505
458
 
506
459
  for (const ssrBodyComponent of confSSR[view.ssr].body) {
507
- const SrrComponent = await ssrFactory(
508
- `./src/client/ssr/components/body/${ssrBodyComponent}.js`,
509
- jsSsrCommonComponents,
510
- );
460
+ const SrrComponent = await ssrFactory(`./src/client/ssr/body/${ssrBodyComponent}.js`);
511
461
  switch (ssrBodyComponent) {
512
462
  case 'UnderpostDefaultSplashScreen':
513
463
  case 'CyberiaDefaultSplashScreen':
@@ -540,48 +490,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
540
490
  host,
541
491
  path,
542
492
  ttiLoadTimeLimit,
543
- storage: {
544
- // 'space-background': fs.readFileSync('./src/client/public/cyberia/space-background', 'utf8'),
545
- lore0: `data:image/jpeg;base64,${fs
546
- .readFileSync('./src/client/public/cyberia/assets/lore/lore0.jpeg')
547
- .toString('base64')}`,
548
- lore1: `data:image/jpeg;base64,${fs
549
- .readFileSync('./src/client/public/cyberia/assets/lore/lore1.jpeg')
550
- .toString('base64')}`,
551
- lore2: `data:image/jpeg;base64,${fs
552
- .readFileSync('./src/client/public/cyberia/assets/lore/lore2.jpeg')
553
- .toString('base64')}`,
554
- lore3: `data:image/jpeg;base64,${fs
555
- .readFileSync('./src/client/public/cyberia/assets/lore/lore3.jpeg')
556
- .toString('base64')}`,
557
- lore4: `data:image/jpeg;base64,${fs
558
- .readFileSync('./src/client/public/cyberia/assets/lore/lore4.jpeg')
559
- .toString('base64')}`,
560
- lore5: `data:image/jpeg;base64,${fs
561
- .readFileSync('./src/client/public/cyberia/assets/lore/lore5.jpeg')
562
- .toString('base64')}`,
563
- lore6: `data:image/jpeg;base64,${fs
564
- .readFileSync('./src/client/public/cyberia/assets/lore/lore6.jpeg')
565
- .toString('base64')}`,
566
- lore7: `data:image/jpeg;base64,${fs
567
- .readFileSync('./src/client/public/cyberia/assets/lore/lore7.jpeg')
568
- .toString('base64')}`,
569
- lore8: `data:image/jpeg;base64,${fs
570
- .readFileSync('./src/client/public/cyberia/assets/lore/lore8.jpeg')
571
- .toString('base64')}`,
572
- ['arrow-left']: `data:image/png;base64,${fs
573
- .readFileSync('./src/client/public/cyberia/assets/ui-icons/arrow-left.png')
574
- .toString('base64')}`,
575
- ['arrow-right']: `data:image/png;base64,${fs
576
- .readFileSync('./src/client/public/cyberia/assets/ui-icons/arrow-right.png')
577
- .toString('base64')}`,
578
- ['fullscreen']: `data:image/png;base64,${fs
579
- .readFileSync('./src/client/public/cyberia/assets/ui-icons/fullscreen.png')
580
- .toString('base64')}`,
581
- ['cyberia-logo']: `data:image/png;base64,${fs
582
- .readFileSync('./src/client/public/cyberia/assets/util/cyberia-retro-banner.png')
583
- .toString('base64')}`,
584
- },
585
493
  });
586
494
  break;
587
495
  }
@@ -592,14 +500,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
592
500
  }
593
501
  }
594
502
  }
595
- const htmlSrc = Render({
596
- title,
597
- buildId,
598
- ssrPath,
599
- ssrHeadComponents,
600
- ssrBodyComponents,
601
- baseSsrLib: jsSsrCommonComponents,
602
- });
603
503
 
604
504
  /** @type {import('sitemap').SitemapItem} */
605
505
  const siteMapLink = {
@@ -609,6 +509,14 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
609
509
  };
610
510
  siteMapLinks.push(siteMapLink);
611
511
 
512
+ const htmlSrc = Render({
513
+ title,
514
+ buildId,
515
+ ssrPath,
516
+ ssrHeadComponents,
517
+ ssrBodyComponents,
518
+ });
519
+
612
520
  fs.writeFileSync(
613
521
  `${buildPath}index.html`,
614
522
  minifyBuild || process.env.NODE_ENV === 'production'
@@ -686,7 +594,7 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
686
594
  fs.copySync(`./coverage`, coverageBuildPath);
687
595
 
688
596
  // uml
689
- shellExec(`node bin/deploy uml ${host} ${path}`);
597
+ // shellExec(`node bin/deploy uml ${host} ${path}`);
690
598
 
691
599
  // https://swagger-autogen.github.io/docs/
692
600
 
@@ -814,6 +722,76 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
814
722
 
815
723
  zip.writeZip(`./build/${buildId}.zip`);
816
724
  }
725
+ if (client) {
726
+ let PRE_CACHED_RESOURCES = [];
727
+
728
+ if (views && offlineBuild && fs.existsSync(`${rootClientPath}/sw.js`)) {
729
+ PRE_CACHED_RESOURCES = await fs.readdir(rootClientPath, { recursive: true });
730
+ PRE_CACHED_RESOURCES = views
731
+ .map((view) => `${path === '/' ? '' : path}${view.path}`)
732
+ .concat(
733
+ PRE_CACHED_RESOURCES.map((p) => `/${p}`).filter(
734
+ (p) => p[1] !== '.' && !fs.statSync(`${rootClientPath}${p}`).isDirectory(),
735
+ ),
736
+ );
737
+ }
738
+
739
+ for (const pageType of ['offline', 'pages']) {
740
+ if (confSSR[getCapVariableName(client)] && confSSR[getCapVariableName(client)][pageType]) {
741
+ for (const page of confSSR[getCapVariableName(client)][pageType]) {
742
+ const SsrComponent = await ssrFactory(`./src/client/ssr/${pageType}/${page.client}.js`);
743
+
744
+ const htmlSrc = Render({
745
+ title: page.title,
746
+ ssrPath,
747
+ ssrHeadComponents: '',
748
+ ssrBodyComponents: SsrComponent(),
749
+ });
750
+
751
+ const buildPath = `${
752
+ rootClientPath[rootClientPath.length - 1] === '/' ? rootClientPath.slice(0, -1) : rootClientPath
753
+ }${page.path === '/' ? page.path : `${page.path}/`}`;
754
+
755
+ PRE_CACHED_RESOURCES.push(`${path === '/' ? '' : path}${page.path === '/' ? '' : page.path}/index.html`);
756
+
757
+ if (!fs.existsSync(buildPath)) fs.mkdirSync(buildPath, { recursive: true });
758
+
759
+ const buildHtmlPath = `${buildPath}index.html`;
760
+
761
+ logger.info('ssr page build', buildHtmlPath);
762
+
763
+ fs.writeFileSync(
764
+ buildHtmlPath,
765
+ minifyBuild || process.env.NODE_ENV === 'production'
766
+ ? await minify(htmlSrc, {
767
+ minifyCSS: true,
768
+ minifyJS: true,
769
+ collapseBooleanAttributes: true,
770
+ collapseInlineTagWhitespace: true,
771
+ collapseWhitespace: true,
772
+ })
773
+ : htmlSrc,
774
+ 'utf8',
775
+ );
776
+ }
777
+ }
778
+ }
779
+
780
+ {
781
+ const PRE_CACHED_JSON = `PRE_CACHED_RESOURCES = ${JSONweb(uniqueArray(PRE_CACHED_RESOURCES))}`;
782
+ const PROXY_PATH = `PROXY_PATH = '${path}'`;
783
+ fs.writeFileSync(
784
+ `${rootClientPath}/sw.js`,
785
+ fs
786
+ .readFileSync(`${rootClientPath}/sw.js`, 'utf8')
787
+ .replaceAll(`PRE_CACHED_RESOURCES = []`, PRE_CACHED_JSON)
788
+ .replaceAll(`PRE_CACHED_RESOURCES=[]`, PRE_CACHED_JSON)
789
+ .replaceAll(`PROXY_PATH = '/'`, PROXY_PATH)
790
+ .replaceAll(`PROXY_PATH='/'`, PROXY_PATH),
791
+ 'utf8',
792
+ );
793
+ }
794
+ }
817
795
  }
818
796
  }
819
797
  };
@@ -47,11 +47,9 @@ const viewFormatted = (src, dists, proxyPath, baseHost = '') => {
47
47
  return src.replaceAll(`from './`, componentFromFormatted).replaceAll(`from '../`, componentFromFormatted);
48
48
  };
49
49
 
50
- const ssrFactory = async (componentPath = '', jsSsrCommonComponents) => {
50
+ const ssrFactory = async (componentPath = `./src/client/ssr/Render.js`) => {
51
51
  let SrrComponent = () => {};
52
- let render = await srcFormatted(fs.readFileSync(componentPath, 'utf8'));
53
- if (render.split('/*imports*/')[1]) render = render.split('/*imports*/')[1];
54
- eval(jsSsrCommonComponents + render);
52
+ eval(await srcFormatted(fs.readFileSync(componentPath, 'utf8')));
55
53
  return SrrComponent;
56
54
  };
57
55