underpost 3.2.4 → 3.2.8

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 (141) hide show
  1. package/.github/workflows/release.cd.yml +1 -2
  2. package/CHANGELOG.md +268 -1
  3. package/CLI-HELP.md +26 -13
  4. package/Dockerfile +0 -4
  5. package/README.md +3 -3
  6. package/bin/build.js +13 -3
  7. package/bin/deploy.js +570 -1
  8. package/bin/file.js +5 -0
  9. package/conf.js +11 -2
  10. package/jsconfig.json +1 -1
  11. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -3
  12. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +2 -3
  13. package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
  14. package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
  15. package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
  16. package/package.json +20 -11
  17. package/src/api/core/core.controller.js +10 -10
  18. package/src/api/core/core.service.js +10 -10
  19. package/src/api/default/default.controller.js +10 -10
  20. package/src/api/default/default.service.js +10 -10
  21. package/src/api/document/document.controller.js +12 -12
  22. package/src/api/document/document.model.js +10 -16
  23. package/src/api/file/file.controller.js +8 -8
  24. package/src/api/file/file.model.js +10 -10
  25. package/src/api/file/file.service.js +36 -36
  26. package/src/api/test/test.controller.js +8 -8
  27. package/src/api/test/test.service.js +8 -8
  28. package/src/api/user/guest.service.js +99 -0
  29. package/src/api/user/user.controller.js +6 -6
  30. package/src/api/user/user.model.js +8 -13
  31. package/src/api/user/user.service.js +3 -20
  32. package/src/cli/deploy.js +33 -30
  33. package/src/cli/fs.js +62 -5
  34. package/src/cli/image.js +43 -1
  35. package/src/cli/index.js +5 -1
  36. package/src/cli/release.js +58 -2
  37. package/src/cli/repository.js +35 -3
  38. package/src/cli/run.js +304 -38
  39. package/src/cli/ssh.js +1 -1
  40. package/src/cli/static.js +43 -115
  41. package/src/client/Default.index.js +21 -33
  42. package/src/client/components/core/404.js +4 -4
  43. package/src/client/components/core/500.js +4 -4
  44. package/src/client/components/core/Account.js +73 -60
  45. package/src/client/components/core/AgGrid.js +23 -33
  46. package/src/client/components/core/Alert.js +12 -13
  47. package/src/client/components/core/AppStore.js +1 -1
  48. package/src/client/components/core/Auth.js +20 -32
  49. package/src/client/components/core/Badge.js +7 -13
  50. package/src/client/components/core/BtnIcon.js +15 -17
  51. package/src/client/components/core/CalendarCore.js +42 -63
  52. package/src/client/components/core/Chat.js +13 -15
  53. package/src/client/components/core/ClientEvents.js +87 -0
  54. package/src/client/components/core/ColorPaletteElement.js +309 -0
  55. package/src/client/components/core/Content.js +17 -14
  56. package/src/client/components/core/Css.js +15 -71
  57. package/src/client/components/core/CssCore.js +12 -16
  58. package/src/client/components/core/D3Chart.js +4 -4
  59. package/src/client/components/core/Docs.js +60 -59
  60. package/src/client/components/core/DropDown.js +69 -91
  61. package/src/client/components/core/EventBus.js +92 -0
  62. package/src/client/components/core/EventsUI.js +14 -17
  63. package/src/client/components/core/FileExplorer.js +102 -234
  64. package/src/client/components/core/FullScreen.js +47 -75
  65. package/src/client/components/core/Input.js +24 -69
  66. package/src/client/components/core/Keyboard.js +25 -18
  67. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  68. package/src/client/components/core/LoadingAnimation.js +25 -31
  69. package/src/client/components/core/LogIn.js +41 -41
  70. package/src/client/components/core/LogOut.js +23 -14
  71. package/src/client/components/core/Modal.js +397 -176
  72. package/src/client/components/core/NotificationManager.js +14 -18
  73. package/src/client/components/core/Panel.js +54 -50
  74. package/src/client/components/core/PanelForm.js +25 -125
  75. package/src/client/components/core/Polyhedron.js +110 -214
  76. package/src/client/components/core/PublicProfile.js +39 -32
  77. package/src/client/components/core/Recover.js +52 -48
  78. package/src/client/components/core/Responsive.js +88 -32
  79. package/src/client/components/core/RichText.js +9 -18
  80. package/src/client/components/core/Router.js +24 -3
  81. package/src/client/components/core/SearchBox.js +37 -37
  82. package/src/client/components/core/SignUp.js +39 -30
  83. package/src/client/components/core/SocketIo.js +31 -2
  84. package/src/client/components/core/SocketIoHandler.js +6 -6
  85. package/src/client/components/core/ToggleSwitch.js +8 -20
  86. package/src/client/components/core/ToolTip.js +5 -17
  87. package/src/client/components/core/Translate.js +56 -59
  88. package/src/client/components/core/Validator.js +26 -16
  89. package/src/client/components/core/Wallet.js +15 -26
  90. package/src/client/components/core/Worker.js +140 -25
  91. package/src/client/components/core/windowGetDimensions.js +7 -7
  92. package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
  93. package/src/client/components/default/CssDefault.js +12 -12
  94. package/src/client/components/default/LogInDefault.js +6 -4
  95. package/src/client/components/default/LogOutDefault.js +6 -4
  96. package/src/client/components/default/RouterDefault.js +47 -0
  97. package/src/client/components/default/SettingsDefault.js +4 -4
  98. package/src/client/components/default/SignUpDefault.js +6 -4
  99. package/src/client/components/default/TranslateDefault.js +3 -3
  100. package/src/client/services/core/core.service.js +17 -49
  101. package/src/client/services/default/default.management.js +139 -242
  102. package/src/client/services/default/default.service.js +10 -16
  103. package/src/client/services/document/document.service.js +14 -19
  104. package/src/client/services/file/file.service.js +8 -13
  105. package/src/client/services/test/test.service.js +8 -13
  106. package/src/client/services/user/guest.service.js +79 -0
  107. package/src/client/services/user/user.management.js +5 -5
  108. package/src/client/services/user/user.service.js +14 -20
  109. package/src/client/ssr/body/404.js +3 -3
  110. package/src/client/ssr/body/500.js +3 -3
  111. package/src/client/ssr/body/CacheControl.js +5 -2
  112. package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
  113. package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
  114. package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
  115. package/src/client/ssr/offline/Maintenance.js +12 -11
  116. package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
  117. package/src/client/ssr/pages/Test.js +2 -2
  118. package/src/client/sw/core.sw.js +212 -0
  119. package/src/index.js +1 -1
  120. package/src/runtime/express/Dockerfile +4 -4
  121. package/src/runtime/lampp/Dockerfile +8 -7
  122. package/src/runtime/wp/Dockerfile +11 -17
  123. package/src/server/backup.js +1 -2
  124. package/src/server/client-build-docs.js +45 -46
  125. package/src/server/client-build.js +334 -60
  126. package/src/server/client-formatted.js +47 -16
  127. package/src/server/conf.js +29 -13
  128. package/src/server/cron.js +6 -8
  129. package/src/server/dns.js +2 -1
  130. package/src/server/ipfs-client.js +232 -91
  131. package/src/server/process.js +13 -27
  132. package/src/server/start.js +6 -3
  133. package/src/server/valkey.js +134 -235
  134. package/tsconfig.docs.json +15 -0
  135. package/typedoc.json +20 -0
  136. package/jsdoc.json +0 -52
  137. package/src/client/components/core/ColorPalette.js +0 -5267
  138. package/src/client/components/core/JoyStick.js +0 -80
  139. package/src/client/components/default/RoutesDefault.js +0 -49
  140. package/src/client/sw/default.sw.js +0 -127
  141. package/src/client/sw/template.sw.js +0 -84
package/src/cli/static.js CHANGED
@@ -3,7 +3,6 @@
3
3
  * @module src/cli/static.js
4
4
  * @namespace UnderpostStatic
5
5
  */
6
-
7
6
  import fs from 'fs-extra';
8
7
  import path from 'path';
9
8
  import express from 'express';
@@ -12,9 +11,7 @@ import { shellExec } from '../server/process.js';
12
11
  import Underpost from '../index.js';
13
12
  import { JSONweb } from '../server/client-formatted.js';
14
13
  import { loggerFactory, loggerMiddleware } from '../server/logger.js';
15
-
16
14
  const logger = loggerFactory(import.meta);
17
-
18
15
  /**
19
16
  * @typedef {Object} MetadataOptions
20
17
  * @memberof UnderpostStatic
@@ -30,7 +27,6 @@ const logger = loggerFactory(import.meta);
30
27
  * @property {Object} [openGraph={}] - Additional Open Graph metadata
31
28
  * @property {Object} [twitter={}] - Twitter card metadata
32
29
  */
33
-
34
30
  /**
35
31
  * @typedef {Object} ScriptOptions
36
32
  * @memberof UnderpostStatic
@@ -43,7 +39,6 @@ const logger = loggerFactory(import.meta);
43
39
  * @property {string} [crossorigin] - CORS settings
44
40
  * @property {Object} [attributes={}] - Additional HTML attributes
45
41
  */
46
-
47
42
  /**
48
43
  * @typedef {Object} StyleOptions
49
44
  * @memberof UnderpostStatic
@@ -53,7 +48,6 @@ const logger = loggerFactory(import.meta);
53
48
  * @property {string} [integrity] - Subresource integrity hash
54
49
  * @property {string} [crossorigin] - CORS settings
55
50
  */
56
-
57
51
  /**
58
52
  * @typedef {Object} IconOptions
59
53
  * @memberof UnderpostStatic
@@ -62,7 +56,6 @@ const logger = loggerFactory(import.meta);
62
56
  * @property {string} [manifest] - Web manifest path
63
57
  * @property {Object[]} [additional=[]] - Additional icon definitions
64
58
  */
65
-
66
59
  /**
67
60
  * @typedef {Object} StaticGenerationOptions
68
61
  * @memberof UnderpostStatic
@@ -88,43 +81,40 @@ const logger = loggerFactory(import.meta);
88
81
  * @property {string} [dir='ltr'] - HTML dir attribute
89
82
  * @property {Object} [microdata=[]] - Structured data (JSON-LD)
90
83
  */
91
-
92
- const DefaultStaticGenerationOptions = {
93
- page: '',
94
- title: '',
95
- outputPath: '',
96
- buildPath: '/',
97
- env: 'production',
98
- dev: false,
99
- minify: true,
100
- metadata: {},
101
- scripts: {},
102
- styles: [],
103
- headComponents: [],
104
- bodyComponents: [],
105
- icons: {},
106
- customPayload: {},
107
- templateHelpers: {},
108
- configFile: '',
109
- lang: 'en',
110
- dir: 'ltr',
111
- microdata: [],
112
- };
113
-
84
+ class DefaultStaticGenerationOptions {
85
+ static page = '';
86
+ static title = '';
87
+ static outputPath = '';
88
+ static buildPath = '/';
89
+ static env = 'production';
90
+ static dev = false;
91
+ static minify = true;
92
+ static metadata = {};
93
+ static scripts = {};
94
+ static styles = [];
95
+ static headComponents = [];
96
+ static bodyComponents = [];
97
+ static icons = {};
98
+ static customPayload = {};
99
+ static templateHelpers = {};
100
+ static configFile = '';
101
+ static lang = 'en';
102
+ static dir = 'ltr';
103
+ static microdata = [];
104
+ }
114
105
  /**
115
106
  * Template helper functions for common SSR patterns
116
107
  * @namespace TemplateHelpers
117
108
  */
118
- const TemplateHelpers = {
109
+ class TemplateHelpers {
119
110
  /**
120
111
  * Generates a script tag from options
121
112
  * @param {ScriptOptions} options - Script options
122
113
  * @returns {string} HTML script tag
123
114
  * @memberof TemplateHelpers
124
115
  */
125
- createScriptTag(options) {
116
+ static createScriptTag(options) {
126
117
  const attrs = [];
127
-
128
118
  if (options.type && options.type !== 'text/javascript') {
129
119
  attrs.push(`type="${options.type}"`);
130
120
  }
@@ -133,49 +123,41 @@ const TemplateHelpers = {
133
123
  if (options.src) attrs.push(`src="${options.src}"`);
134
124
  if (options.integrity) attrs.push(`integrity="${options.integrity}"`);
135
125
  if (options.crossorigin) attrs.push(`crossorigin="${options.crossorigin}"`);
136
-
137
126
  // Add custom attributes
138
127
  if (options.attributes) {
139
128
  Object.entries(options.attributes).forEach(([key, value]) => {
140
129
  attrs.push(`${key}="${value}"`);
141
130
  });
142
131
  }
143
-
144
132
  const attrString = attrs.length > 0 ? ` ${attrs.join(' ')}` : '';
145
133
  const content = options.content || '';
146
-
147
134
  return `<script${attrString}>${content}</script>`;
148
- },
149
-
135
+ }
150
136
  /**
151
137
  * Generates a link/style tag from options
152
138
  * @param {StyleOptions} options - Style options
153
139
  * @returns {string} HTML link or style tag
154
140
  * @memberof TemplateHelpers
155
141
  */
156
- createStyleTag(options) {
142
+ static createStyleTag(options) {
157
143
  if (options.content) {
158
144
  return `<style>${options.content}</style>`;
159
145
  }
160
-
161
146
  const attrs = [`rel="stylesheet"`];
162
147
  if (options.href) attrs.push(`href="${options.href}"`);
163
148
  if (options.media) attrs.push(`media="${options.media}"`);
164
149
  if (options.integrity) attrs.push(`integrity="${options.integrity}"`);
165
150
  if (options.crossorigin) attrs.push(`crossorigin="${options.crossorigin}"`);
166
-
167
151
  return `<link ${attrs.join(' ')}>`;
168
- },
169
-
152
+ }
170
153
  /**
171
154
  * Generates icon link tags
172
155
  * @param {IconOptions} icons - Icon options
173
156
  * @returns {string} HTML icon link tags
174
157
  * @memberof TemplateHelpers
175
158
  */
176
- createIconTags(icons) {
159
+ static createIconTags(icons) {
177
160
  const tags = [];
178
-
179
161
  if (icons.favicon) {
180
162
  tags.push(`<link rel="icon" type="image/x-icon" href="${icons.favicon}">`);
181
163
  }
@@ -193,19 +175,16 @@ const TemplateHelpers = {
193
175
  tags.push(`<link ${attrs}>`);
194
176
  });
195
177
  }
196
-
197
178
  return tags.join('\n');
198
- },
199
-
179
+ }
200
180
  /**
201
181
  * Generates meta tags from metadata object
202
182
  * @param {MetadataOptions} metadata - Metadata options
203
183
  * @returns {string} HTML meta tags
204
184
  * @memberof TemplateHelpers
205
185
  */
206
- createMetaTags(metadata) {
186
+ static createMetaTags(metadata) {
207
187
  const tags = [];
208
-
209
188
  if (metadata.description) {
210
189
  tags.push(`<meta name="description" content="${metadata.description}">`);
211
190
  }
@@ -218,7 +197,6 @@ const TemplateHelpers = {
218
197
  if (metadata.themeColor) {
219
198
  tags.push(`<meta name="theme-color" content="${metadata.themeColor}">`);
220
199
  }
221
-
222
200
  // Open Graph
223
201
  if (metadata.title) {
224
202
  tags.push(`<meta property="og:title" content="${metadata.title}">`);
@@ -239,7 +217,6 @@ const TemplateHelpers = {
239
217
  if (metadata.locale) {
240
218
  tags.push(`<meta property="og:locale" content="${metadata.locale}">`);
241
219
  }
242
-
243
220
  // Twitter Card
244
221
  tags.push(`<meta name="twitter:card" content="summary_large_image">`);
245
222
  if (metadata.twitter) {
@@ -247,53 +224,46 @@ const TemplateHelpers = {
247
224
  tags.push(`<meta name="twitter:${key}" content="${value}">`);
248
225
  });
249
226
  }
250
-
251
227
  // Additional Open Graph
252
228
  if (metadata.openGraph) {
253
229
  Object.entries(metadata.openGraph).forEach(([key, value]) => {
254
230
  tags.push(`<meta property="og:${key}" content="${value}">`);
255
231
  });
256
232
  }
257
-
258
233
  return tags.join('\n');
259
- },
260
-
234
+ }
261
235
  /**
262
236
  * Generates JSON-LD structured data script tags
263
237
  * @param {Object[]} microdata - Array of structured data objects
264
238
  * @returns {string} HTML script tags with JSON-LD
265
239
  * @memberof TemplateHelpers
266
240
  */
267
- createMicrodataTags(microdata) {
241
+ static createMicrodataTags(microdata) {
268
242
  if (!microdata || !Array.isArray(microdata) || microdata.length === 0) {
269
243
  return '';
270
244
  }
271
-
272
245
  return microdata
273
246
  .map((data) => `<script type="application/ld+json">\n${JSON.stringify(data, null, 2)}\n</script>`)
274
247
  .join('\n');
275
- },
276
- };
277
-
248
+ }
249
+ }
278
250
  /**
279
251
  * Configuration validator
280
252
  * @namespace ConfigValidator
281
253
  */
282
- const ConfigValidator = {
254
+ class ConfigValidator {
283
255
  /**
284
256
  * Validates static generation options
285
257
  * @param {StaticGenerationOptions} options - Options to validate
286
258
  * @returns {Object} Validation result with isValid flag and errors array
287
259
  * @memberof ConfigValidator
288
260
  */
289
- validate(options) {
261
+ static validate(options) {
290
262
  const errors = [];
291
-
292
263
  // Validate page path
293
264
  if (options.page && !fs.existsSync(options.page)) {
294
265
  errors.push(`Page component does not exist: ${options.page}`);
295
266
  }
296
-
297
267
  // Validate head components
298
268
  if (options.headComponents && Array.isArray(options.headComponents)) {
299
269
  options.headComponents.forEach((comp) => {
@@ -302,7 +272,6 @@ const ConfigValidator = {
302
272
  }
303
273
  });
304
274
  }
305
-
306
275
  // Validate body components
307
276
  if (options.bodyComponents && Array.isArray(options.bodyComponents)) {
308
277
  options.bodyComponents.forEach((comp) => {
@@ -311,61 +280,55 @@ const ConfigValidator = {
311
280
  }
312
281
  });
313
282
  }
314
-
315
283
  // Validate environment
316
284
  if (options.env && !['development', 'production'].includes(options.env)) {
317
285
  logger.warn(`Invalid environment: ${options.env}. Using 'production' as default.`);
318
286
  }
319
-
320
287
  return {
321
288
  isValid: errors.length === 0,
322
289
  errors,
323
290
  };
324
- },
325
- };
326
-
291
+ }
292
+ }
327
293
  /**
328
294
  * Configuration file loader
329
295
  * @namespace ConfigLoader
330
296
  */
331
- const ConfigLoader = {
297
+ class ConfigLoader {
332
298
  /**
333
299
  * Loads configuration from a JSON file
334
300
  * @param {string} configPath - Path to config file
335
301
  * @returns {Object} Configuration object
336
302
  * @memberof ConfigLoader
337
303
  */
338
- load(configPath) {
304
+ static load(configPath) {
339
305
  try {
340
306
  if (!fs.existsSync(configPath)) {
341
307
  logger.error(`Config file not found: ${configPath}`);
342
308
  return {};
343
309
  }
344
-
345
310
  const content = fs.readFileSync(configPath, 'utf8');
346
311
  return JSON.parse(content);
347
312
  } catch (error) {
348
313
  logger.error(`Error loading config file: ${error.message}`);
349
314
  return {};
350
315
  }
351
- },
352
-
316
+ }
353
317
  /**
354
318
  * Saves configuration to a JSON file
355
319
  * @param {string} configPath - Path to save config
356
320
  * @param {Object} config - Configuration object
357
321
  * @memberof ConfigLoader
358
322
  */
359
- save(configPath, config) {
323
+ static save(configPath, config) {
360
324
  try {
361
325
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
362
326
  logger.info(`Config saved to: ${configPath}`);
363
327
  } catch (error) {
364
328
  logger.error(`Error saving config file: ${error.message}`);
365
329
  }
366
- },
367
- };
368
-
330
+ }
331
+ }
369
332
  /**
370
333
  * @class UnderpostStatic
371
334
  * @description Enhanced static site generation class with comprehensive customization
@@ -406,7 +369,6 @@ class UnderpostStatic {
406
369
  const configPath = typeof options.generateConfig === 'string' ? options.generateConfig : './static-config.json';
407
370
  return Underpost.static.generateConfigTemplate(configPath);
408
371
  }
409
-
410
372
  // Parse comma-separated options
411
373
  if (options.keywords) {
412
374
  options.keywords = options.keywords.split(',').map((k) => k.trim());
@@ -428,7 +390,6 @@ class UnderpostStatic {
428
390
  if (options.bodyComponents) {
429
391
  options.bodyComponents = options.bodyComponents.split(',').map((c) => c.trim());
430
392
  }
431
-
432
393
  // Build metadata object from individual options
433
394
  options.metadata = {
434
395
  ...(options.title && { title: options.title }),
@@ -441,7 +402,6 @@ class UnderpostStatic {
441
402
  ...(options.locale && { locale: options.locale }),
442
403
  ...(options.siteName && { siteName: options.siteName }),
443
404
  };
444
-
445
405
  // Build icons object
446
406
  if (options.favicon || options.appleTouchIcon || options.manifest) {
447
407
  options.icons = {
@@ -450,13 +410,11 @@ class UnderpostStatic {
450
410
  ...(options.manifest && { manifest: options.manifest }),
451
411
  };
452
412
  }
453
-
454
413
  // Load config from file if specified
455
414
  if (options.configFile) {
456
415
  const fileConfig = ConfigLoader.load(options.configFile);
457
416
  options = { ...fileConfig, ...options }; // CLI options override file config
458
417
  }
459
-
460
418
  // Set defaults
461
419
  if (!options.outputPath) options.outputPath = '.';
462
420
  if (!options.buildPath) options.buildPath = '/';
@@ -465,7 +423,6 @@ class UnderpostStatic {
465
423
  if (!options.metadata) options.metadata = {};
466
424
  if (!options.lang) options.lang = 'en';
467
425
  if (!options.dir) options.dir = 'ltr';
468
-
469
426
  // Merge title for backwards compatibility
470
427
  if (options.title && !options.metadata.title) {
471
428
  options.metadata.title = options.title;
@@ -473,7 +430,6 @@ class UnderpostStatic {
473
430
  if (!options.metadata.title) {
474
431
  options.metadata.title = 'Home';
475
432
  }
476
-
477
433
  // Validate options
478
434
  const validation = ConfigValidator.validate(options);
479
435
  if (!validation.isValid) {
@@ -483,44 +439,35 @@ class UnderpostStatic {
483
439
  return; // Exit if critical path errors
484
440
  }
485
441
  }
486
-
487
442
  // Generate page HTML
488
443
  if (options.page) {
489
444
  try {
490
445
  logger.info(`Generating static page: ${options.page}`);
491
-
492
446
  const Render = await ssrFactory();
493
447
  const SsrComponent = await ssrFactory(options.page);
494
-
495
448
  // Build head components
496
449
  let ssrHeadComponents = '';
497
-
498
450
  // Add custom meta tags
499
451
  if (options.metadata) {
500
452
  ssrHeadComponents += TemplateHelpers.createMetaTags(options.metadata);
501
453
  }
502
-
503
454
  // Add custom icons
504
455
  if (options.icons) {
505
456
  ssrHeadComponents += '\n' + TemplateHelpers.createIconTags(options.icons);
506
457
  }
507
-
508
458
  // Add custom styles
509
459
  if (options.styles && Array.isArray(options.styles)) {
510
460
  ssrHeadComponents += '\n' + options.styles.map((style) => TemplateHelpers.createStyleTag(style)).join('\n');
511
461
  }
512
-
513
462
  // Add custom head scripts
514
463
  if (options.scripts?.head && Array.isArray(options.scripts.head)) {
515
464
  ssrHeadComponents +=
516
465
  '\n' + options.scripts.head.map((script) => TemplateHelpers.createScriptTag(script)).join('\n');
517
466
  }
518
-
519
467
  // Add microdata/structured data
520
468
  if (options.microdata && Array.isArray(options.microdata)) {
521
469
  ssrHeadComponents += '\n' + TemplateHelpers.createMicrodataTags(options.microdata);
522
470
  }
523
-
524
471
  // Load additional head components
525
472
  if (options.headComponents && Array.isArray(options.headComponents)) {
526
473
  for (const compPath of options.headComponents) {
@@ -538,10 +485,8 @@ class UnderpostStatic {
538
485
  }
539
486
  }
540
487
  }
541
-
542
488
  // Build body components
543
489
  let ssrBodyComponents = SsrComponent();
544
-
545
490
  // Load additional body components
546
491
  if (options.bodyComponents && Array.isArray(options.bodyComponents)) {
547
492
  for (const compPath of options.bodyComponents) {
@@ -553,20 +498,17 @@ class UnderpostStatic {
553
498
  }
554
499
  }
555
500
  }
556
-
557
501
  // Add custom body scripts
558
502
  if (options.scripts?.body && Array.isArray(options.scripts.body)) {
559
503
  ssrBodyComponents +=
560
504
  '\n' + options.scripts.body.map((script) => TemplateHelpers.createScriptTag(script)).join('\n');
561
505
  }
562
-
563
506
  // Build render payload
564
507
  const renderPayload = {
565
508
  version: Underpost.version,
566
509
  ...(options.env === 'development' ? { dev: true } : undefined),
567
510
  ...options.customPayload,
568
511
  };
569
-
570
512
  // Generate HTML
571
513
  const htmlSrc = Render({
572
514
  title: options.metadata.title,
@@ -578,13 +520,11 @@ class UnderpostStatic {
578
520
  JSONweb,
579
521
  },
580
522
  });
581
-
582
523
  // Write output file
583
524
  const outputDir = path.dirname(options.outputPath);
584
525
  if (!fs.existsSync(outputDir)) {
585
526
  fs.mkdirSync(outputDir, { recursive: true });
586
527
  }
587
-
588
528
  fs.writeFileSync(options.outputPath, htmlSrc, 'utf8');
589
529
  logger.info(`Static page generated: ${options.outputPath}`);
590
530
  } catch (error) {
@@ -593,7 +533,6 @@ class UnderpostStatic {
593
533
  throw error;
594
534
  }
595
535
  }
596
-
597
536
  // Start standalone static file server if --run-sv is specified
598
537
  if (options.runSv !== undefined) {
599
538
  const port = typeof options.runSv === 'string' ? parseInt(options.runSv, 10) : 5000;
@@ -601,25 +540,19 @@ class UnderpostStatic {
601
540
  options.outputPath && options.outputPath !== '.'
602
541
  ? path.dirname(path.resolve(options.outputPath))
603
542
  : path.resolve('.');
604
-
605
543
  if (!fs.existsSync(servePath)) {
606
544
  logger.error(`Serve path does not exist: ${servePath}`);
607
545
  return;
608
546
  }
609
-
610
547
  const app = express();
611
-
612
548
  app.use(loggerMiddleware(import.meta, 'debug', () => false));
613
-
614
549
  app.use('/', express.static(servePath));
615
-
616
550
  app.listen(port, () => {
617
551
  logger.info(`Static file server running at http://localhost:${port}`);
618
552
  logger.info(`Serving files from: ${servePath}`);
619
553
  });
620
554
  }
621
555
  },
622
-
623
556
  /**
624
557
  * Helper method to generate a config template file
625
558
  *
@@ -693,26 +626,22 @@ class UnderpostStatic {
693
626
  customFeature: true,
694
627
  },
695
628
  };
696
-
697
629
  ConfigLoader.save(outputPath, template);
698
630
  logger.info(`Config template generated: ${outputPath}`);
699
631
  },
700
632
  };
701
-
702
633
  /**
703
634
  * Export template helpers for external use
704
635
  * @static
705
636
  * @memberof UnderpostStatic
706
637
  */
707
638
  static TemplateHelpers = TemplateHelpers;
708
-
709
639
  /**
710
640
  * Export config validator for external use
711
641
  * @static
712
642
  * @memberof UnderpostStatic
713
643
  */
714
644
  static ConfigValidator = ConfigValidator;
715
-
716
645
  /**
717
646
  * Export config loader for external use
718
647
  * @static
@@ -720,6 +649,5 @@ class UnderpostStatic {
720
649
  */
721
650
  static ConfigLoader = ConfigLoader;
722
651
  }
723
-
724
652
  export default UnderpostStatic;
725
653
  export { TemplateHelpers, ConfigValidator, ConfigLoader };
@@ -1,24 +1,17 @@
1
1
  'use strict';
2
2
 
3
- import { Css } from './components/core/Css.js';
4
- import { Responsive } from './components/core/Responsive.js';
5
- import { TranslateCore } from './components/core/Translate.js';
3
+ import { Worker } from './components/core/Worker.js';
4
+ import { RouterDefault } from './components/default/RouterDefault.js';
5
+ import { AppShellDefault } from './components/default/AppShellDefault.js';
6
+ import { AppStoreDefault } from './components/default/AppStoreDefault.js';
7
+ import { SocketIoDefault } from './components/default/SocketIoDefault.js';
6
8
  import { LogInDefault } from './components/default/LogInDefault.js';
7
9
  import { LogOutDefault } from './components/default/LogOutDefault.js';
8
10
  import { SignUpDefault } from './components/default/SignUpDefault.js';
9
- import { MenuDefault } from './components/default/MenuDefault.js';
10
- import { RouterDefault } from './components/default/RoutesDefault.js';
11
- import { TranslateDefault } from './components/default/TranslateDefault.js';
12
- import { Worker } from './components/core/Worker.js';
13
- import { Keyboard } from './components/core/Keyboard.js';
14
- import { SocketIo } from './components/core/SocketIo.js';
15
- import { SocketIoDefault } from './components/default/SocketIoDefault.js';
16
- import { AppStoreDefault } from './components/default/AppStoreDefault.js';
17
11
  import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
12
+ import { TranslateDefault } from './components/default/TranslateDefault.js';
18
13
  import { EventsUI } from './components/core/EventsUI.js';
19
- import { Modal } from './components/core/Modal.js';
20
-
21
- const htmlMainBody = async () => {
14
+ const DefaultTemplate = async () => {
22
15
  setTimeout(() => {
23
16
  EventsUI.onClick('.get-started-button', (e) => {
24
17
  e.preventDefault();
@@ -32,11 +25,10 @@ const htmlMainBody = async () => {
32
25
  <span class="greeting">Hello, World!</span>
33
26
  <span class="subtitle">Welcome to Our Platform</span>
34
27
  </h1>
35
-
36
28
  <div class="features">
37
29
  <div class="feature-card">
38
30
  <i class="icon">🚀</i>
39
- <h3>Fast & Reliable</h3>
31
+ <h3>Fast &amp; Reliable</h3>
40
32
  <p>Lightning-fast performance with 99.9% uptime</p>
41
33
  </div>
42
34
  <div class="feature-card">
@@ -50,7 +42,6 @@ const htmlMainBody = async () => {
50
42
  <p>Everything you need in one place</p>
51
43
  </div>
52
44
  </div>
53
-
54
45
  <button class="cta-button get-started-button">
55
46
  Get Started
56
47
  <span class="button-icon">→</span>
@@ -60,24 +51,21 @@ const htmlMainBody = async () => {
60
51
  `;
61
52
  };
62
53
 
54
+ const CssDefaultThemes = [CssDefaultDark, CssDefaultLight];
55
+
63
56
  window.onload = () =>
64
57
  Worker.instance({
65
58
  router: RouterDefault,
66
- render: async () => {
67
- await Css.loadThemes([CssDefaultLight, CssDefaultDark]);
68
- await TranslateCore.Init();
69
- await TranslateDefault.Init();
70
- await Responsive.Init();
71
- await MenuDefault.Render({ htmlMainBody });
72
- await SocketIo.Init({
73
- channels: AppStoreDefault.Data,
74
- path: `/`,
75
- });
76
- await SocketIoDefault.Init();
77
- await LogInDefault();
78
- await LogOutDefault();
79
- await SignUpDefault();
80
- await Keyboard.Init();
81
- await Modal.RenderSeoSanitizer();
59
+ template: DefaultTemplate,
60
+ themes: CssDefaultThemes,
61
+ translate: TranslateDefault,
62
+ render: AppShellDefault,
63
+ appStore: AppStoreDefault,
64
+ socketPath: '/',
65
+ session: {
66
+ socket: SocketIoDefault,
67
+ login: LogInDefault,
68
+ signout: LogOutDefault,
69
+ signup: SignUpDefault,
82
70
  },
83
71
  });
@@ -2,8 +2,8 @@ import { Alert } from './Alert.js';
2
2
  import { Modal } from './Modal.js';
3
3
  import { s } from './VanillaJs.js';
4
4
 
5
- const Page404 = {
6
- Render: async function (options = { idModal: '' }) {
5
+ class Page404 {
6
+ static async instance(options = { idModal: '' }) {
7
7
  setTimeout(() => {
8
8
  Modal.Data[options.idModal].onObserverListener['404'] = () => {
9
9
  if (s(`.container-404-${options.idModal}`))
@@ -14,7 +14,7 @@ const Page404 = {
14
14
  Modal.Data[options.idModal].onObserverListener['404']();
15
15
  });
16
16
  return html`<div class="in container-404-${options.idModal}">${await Alert.e404()}</div>`;
17
- },
18
- };
17
+ }
18
+ }
19
19
 
20
20
  export { Page404 };
@@ -2,8 +2,8 @@ import { Alert } from './Alert.js';
2
2
  import { Modal } from './Modal.js';
3
3
  import { s } from './VanillaJs.js';
4
4
 
5
- const Page500 = {
6
- Render: async function (options = { idModal: '' }) {
5
+ class Page500 {
6
+ static async instance(options = { idModal: '' }) {
7
7
  setTimeout(() => {
8
8
  Modal.Data[options.idModal].onObserverListener['500'] = () => {
9
9
  if (s(`.container-500-${options.idModal}`))
@@ -14,7 +14,7 @@ const Page500 = {
14
14
  Modal.Data[options.idModal].onObserverListener['500']();
15
15
  });
16
16
  return html`<div class="in container-500-${options.idModal}">${await Alert.e500()}</div>`;
17
- },
18
- };
17
+ }
18
+ }
19
19
 
20
20
  export { Page500 };