@underpostnet/underpost 2.98.1 → 2.99.0

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 (43) hide show
  1. package/README.md +2 -3
  2. package/bin/build.js +5 -5
  3. package/bin/deploy.js +10 -1
  4. package/cli.md +109 -110
  5. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  6. package/manifests/deployment/dd-test-development/deployment.yaml +4 -4
  7. package/package.json +1 -2
  8. package/src/api/user/user.router.js +7 -40
  9. package/src/cli/baremetal.js +67 -71
  10. package/src/cli/cloud-init.js +11 -12
  11. package/src/cli/cluster.js +22 -24
  12. package/src/cli/db.js +43 -50
  13. package/src/cli/deploy.js +162 -60
  14. package/src/cli/env.js +20 -5
  15. package/src/cli/fs.js +19 -21
  16. package/src/cli/index.js +35 -32
  17. package/src/cli/lxd.js +5 -5
  18. package/src/cli/monitor.js +66 -88
  19. package/src/cli/repository.js +7 -6
  20. package/src/cli/run.js +369 -261
  21. package/src/cli/secrets.js +3 -3
  22. package/src/cli/ssh.js +31 -32
  23. package/src/cli/static.js +1 -1
  24. package/src/cli/test.js +6 -7
  25. package/src/client/components/core/Content.js +42 -40
  26. package/src/client/components/core/FullScreen.js +202 -9
  27. package/src/client/components/core/PanelForm.js +4 -2
  28. package/src/client/components/core/VanillaJs.js +80 -29
  29. package/src/index.js +49 -32
  30. package/src/runtime/express/Express.js +7 -6
  31. package/src/server/auth.js +6 -1
  32. package/src/server/backup.js +11 -1
  33. package/src/server/conf.js +4 -4
  34. package/src/{cli → server}/cron.js +56 -29
  35. package/src/server/dns.js +39 -31
  36. package/src/server/peer.js +2 -2
  37. package/src/server/process.js +2 -2
  38. package/src/server/proxy.js +8 -7
  39. package/src/server/runtime.js +4 -7
  40. package/src/server/start.js +28 -15
  41. package/src/ws/IoServer.js +2 -3
  42. package/src/cli/script.js +0 -85
  43. package/src/monitor.js +0 -34
@@ -174,52 +174,103 @@ const disableOptionsClick = (element, types) => {
174
174
 
175
175
  /**
176
176
  * The function `checkFullScreen` checks if the document is in full screen mode and returns a boolean
177
- * value accordingly.
178
- * @returns The function `checkFullScreen` is returning `true` if `document.fullscreenElement` is
179
- * truthy, otherwise it returns `false`.
177
+ * value accordingly. Checks all vendor-prefixed APIs for maximum compatibility.
178
+ * @returns The function `checkFullScreen` is returning `true` if any fullscreen API indicates
179
+ * fullscreen mode is active, otherwise it returns `false`.
180
180
  * @memberof VanillaJS
181
181
  */
182
182
  const checkFullScreen = () => {
183
- // !(!window.screenTop && !window.screenY) ||
184
- return document.fullscreenElement ? true : false;
183
+ return !!(
184
+ document.fullscreenElement ||
185
+ document.webkitFullscreenElement ||
186
+ document.mozFullScreenElement ||
187
+ document.msFullscreenElement ||
188
+ document.fullscreen ||
189
+ document.webkitIsFullScreen ||
190
+ document.mozFullScreen
191
+ );
185
192
  };
186
193
 
187
194
  /**
188
195
  * The function `fullScreenOut` is used to exit full screen mode in a web browser.
196
+ * Handles all vendor-prefixed APIs and returns a promise for better control flow.
197
+ * @returns {Promise<boolean>} Promise that resolves to true if exit was attempted
189
198
  * @memberof VanillaJS
190
199
  */
191
200
  const fullScreenOut = () => {
192
- if (document.exitFullscreen) {
193
- document.exitFullscreen();
194
- } else if (document.mozCancelFullScreen) {
195
- document.mozCancelFullScreen();
196
- } else if (document.webkitExitFullscreen) {
197
- document.webkitExitFullscreen();
198
- } else if (document.msExitFullscreen) {
199
- window.top.document.msExitFullscreen();
200
- }
201
+ return new Promise((resolve) => {
202
+ if (!checkFullScreen()) {
203
+ resolve(true);
204
+ return;
205
+ }
206
+
207
+ try {
208
+ if (document.exitFullscreen) {
209
+ document
210
+ .exitFullscreen()
211
+ .then(() => resolve(true))
212
+ .catch(() => resolve(false));
213
+ } else if (document.webkitExitFullscreen) {
214
+ document.webkitExitFullscreen();
215
+ setTimeout(() => resolve(true), 100);
216
+ } else if (document.mozCancelFullScreen) {
217
+ document.mozCancelFullScreen();
218
+ setTimeout(() => resolve(true), 100);
219
+ } else if (document.msExitFullscreen) {
220
+ document.msExitFullscreen();
221
+ setTimeout(() => resolve(true), 100);
222
+ } else {
223
+ resolve(false);
224
+ }
225
+ } catch (err) {
226
+ console.warn('Fullscreen exit error:', err);
227
+ resolve(false);
228
+ }
229
+ });
201
230
  };
202
231
 
203
232
  /**
204
233
  * The `fullScreenIn` function is used to request full screen mode in a web browser using different
205
- * vendor-specific methods.
234
+ * vendor-specific methods. Returns a promise for better control flow.
235
+ * @returns {Promise<boolean>} Promise that resolves to true if fullscreen was requested
206
236
  * @memberof VanillaJS
207
237
  */
208
238
  const fullScreenIn = () => {
209
- const elem = document.documentElement;
210
- if (elem.requestFullscreen) {
211
- elem.requestFullscreen();
212
- } else if (elem.mozRequestFullScreen) {
213
- /* Firefox */
214
- elem.mozRequestFullScreen();
215
- } else if (elem.webkitRequestFullscreen) {
216
- /* Chrome, Safari & Opera */
217
- elem.webkitRequestFullscreen();
218
- } else if (elem.msRequestFullscreen) {
219
- /* IE/Edge */
220
- elem = window.top.document.body; //To break out of frame in IE
221
- elem.msRequestFullscreen();
222
- }
239
+ return new Promise((resolve) => {
240
+ if (checkFullScreen()) {
241
+ resolve(true);
242
+ return;
243
+ }
244
+
245
+ const elem = document.documentElement;
246
+
247
+ try {
248
+ if (elem.requestFullscreen) {
249
+ elem
250
+ .requestFullscreen()
251
+ .then(() => resolve(true))
252
+ .catch(() => resolve(false));
253
+ } else if (elem.webkitRequestFullscreen) {
254
+ /* Chrome, Safari & Opera */
255
+ elem.webkitRequestFullscreen();
256
+ setTimeout(() => resolve(true), 100);
257
+ } else if (elem.mozRequestFullScreen) {
258
+ /* Firefox */
259
+ elem.mozRequestFullScreen();
260
+ setTimeout(() => resolve(true), 100);
261
+ } else if (elem.msRequestFullscreen) {
262
+ /* IE/Edge */
263
+ const msElem = window.top.document.body;
264
+ msElem.msRequestFullscreen();
265
+ setTimeout(() => resolve(true), 100);
266
+ } else {
267
+ resolve(false);
268
+ }
269
+ } catch (err) {
270
+ console.warn('Fullscreen request error:', err);
271
+ resolve(false);
272
+ }
273
+ });
223
274
  };
224
275
 
225
276
  /**
package/src/index.js CHANGED
@@ -7,7 +7,6 @@
7
7
  import UnderpostBaremetal from './cli/baremetal.js';
8
8
  import UnderpostCloudInit from './cli/cloud-init.js';
9
9
  import UnderpostCluster from './cli/cluster.js';
10
- import UnderpostCron from './cli/cron.js';
11
10
  import UnderpostDB from './cli/db.js';
12
11
  import UnderpostDeploy from './cli/deploy.js';
13
12
  import UnderpostRootEnv from './cli/env.js';
@@ -17,11 +16,14 @@ import UnderpostLxd from './cli/lxd.js';
17
16
  import UnderpostMonitor from './cli/monitor.js';
18
17
  import UnderpostRepository from './cli/repository.js';
19
18
  import UnderpostRun from './cli/run.js';
20
- import UnderpostScript from './cli/script.js';
21
19
  import UnderpostSecret from './cli/secrets.js';
22
20
  import UnderpostSSH from './cli/ssh.js';
23
21
  import UnderpostStatic from './cli/static.js';
24
22
  import UnderpostTest from './cli/test.js';
23
+
24
+ import UnderpostDns from './server/dns.js';
25
+ import UnderpostBackup from './server/backup.js';
26
+ import UnderpostCron from './server/cron.js';
25
27
  import UnderpostStartUp from './server/start.js';
26
28
 
27
29
  /**
@@ -36,7 +38,7 @@ class Underpost {
36
38
  * @type {String}
37
39
  * @memberof Underpost
38
40
  */
39
- static version = 'v2.98.1';
41
+ static version = 'v2.99.0';
40
42
  /**
41
43
  * Repository cli API
42
44
  * @static
@@ -64,15 +66,7 @@ class Underpost {
64
66
  static get test() {
65
67
  return UnderpostTest.API;
66
68
  }
67
- /**
68
- * Underpost Start Up cli API
69
- * @static
70
- * @type {UnderpostStartUp.API}
71
- * @memberof Underpost
72
- */
73
- static get start() {
74
- return UnderpostStartUp.API;
75
- }
69
+
76
70
  /**
77
71
  * Static cli API
78
72
  * @static
@@ -110,15 +104,6 @@ class Underpost {
110
104
  static get secret() {
111
105
  return UnderpostSecret.API;
112
106
  }
113
- /**
114
- * Scripts cli API
115
- * @static
116
- * @type {UnderpostScript.API}
117
- * @memberof Underpost
118
- */
119
- static get script() {
120
- return UnderpostScript.API;
121
- }
122
107
  /**
123
108
  * Database cli API
124
109
  * @static
@@ -137,15 +122,6 @@ class Underpost {
137
122
  static get deploy() {
138
123
  return UnderpostDeploy.API;
139
124
  }
140
- /**
141
- * Cron cli API
142
- * @static
143
- * @type {UnderpostCron.API}
144
- * @memberof Underpost
145
- */
146
- static get cron() {
147
- return UnderpostCron.API;
148
- }
149
125
  /**
150
126
  * File Storage cli API
151
127
  * @static
@@ -212,6 +188,46 @@ class Underpost {
212
188
  static get baremetal() {
213
189
  return UnderpostBaremetal.API;
214
190
  }
191
+
192
+ /**
193
+ * Dns cli API
194
+ * @static
195
+ * @type {UnderpostDns.API}
196
+ * @memberof Underpost
197
+ */
198
+ static get dns() {
199
+ return UnderpostDns.API;
200
+ }
201
+
202
+ /**
203
+ * BackUp cli API
204
+ * @static
205
+ * @type {UnderpostBackup.API}
206
+ * @memberof Underpost
207
+ */
208
+ static get backup() {
209
+ return UnderpostBackup.API;
210
+ }
211
+
212
+ /**
213
+ * Cron cli API
214
+ * @static
215
+ * @type {UnderpostCron.API}
216
+ * @memberof Underpost
217
+ */
218
+ static get cron() {
219
+ return UnderpostCron.API;
220
+ }
221
+
222
+ /**
223
+ * Start Up cli API
224
+ * @static
225
+ * @type {UnderpostStartUp.API}
226
+ * @memberof Underpost
227
+ */
228
+ static get start() {
229
+ return UnderpostStartUp.API;
230
+ }
215
231
  }
216
232
 
217
233
  const up = Underpost;
@@ -225,7 +241,6 @@ export {
225
241
  UnderpostBaremetal,
226
242
  UnderpostCloudInit,
227
243
  UnderpostCluster,
228
- UnderpostCron,
229
244
  UnderpostDB,
230
245
  UnderpostDeploy,
231
246
  UnderpostRootEnv,
@@ -236,10 +251,12 @@ export {
236
251
  UnderpostMonitor,
237
252
  UnderpostRepository,
238
253
  UnderpostRun,
239
- UnderpostScript,
240
254
  UnderpostSecret,
241
255
  UnderpostSSH,
242
256
  UnderpostTest,
257
+ UnderpostDns,
258
+ UnderpostBackup,
259
+ UnderpostCron,
243
260
  UnderpostStartUp,
244
261
  };
245
262
 
@@ -12,7 +12,6 @@ import swaggerUi from 'swagger-ui-express';
12
12
  import compression from 'compression';
13
13
  import { createServer } from 'http';
14
14
 
15
- import UnderpostStartUp from '../../server/start.js';
16
15
  import { loggerFactory, loggerMiddleware } from '../../server/logger.js';
17
16
  import { getCapVariableName, newInstance } from '../../client/components/core/CommonJs.js';
18
17
  import { MailerProvider } from '../../mailer/MailerProvider.js';
@@ -25,6 +24,8 @@ import { TLS } from '../../server/tls.js';
25
24
  import { shellExec } from '../../server/process.js';
26
25
  import { devProxyHostFactory, isDevProxyContext, isTlsDevProxy } from '../../server/conf.js';
27
26
 
27
+ import Underpost from '../../index.js';
28
+
28
29
  const logger = loggerFactory(import.meta);
29
30
 
30
31
  /**
@@ -143,7 +144,7 @@ class ExpressService {
143
144
  }
144
145
  return next();
145
146
  });
146
- await UnderpostStartUp.API.listenPortController(app, port, runningData);
147
+ await Underpost.start.listenPortController(app, port, runningData);
147
148
  return { portsUsed };
148
149
  }
149
150
 
@@ -214,7 +215,7 @@ class ExpressService {
214
215
  const { options, meta, ioServer } = await createIoServer(server, { host, path, db, port, origins });
215
216
 
216
217
  // Listen on the main port for the WS server
217
- await UnderpostStartUp.API.listenPortController(ioServer, port, {
218
+ await Underpost.start.listenPortController(ioServer, port, {
218
219
  runtime: 'nodejs',
219
220
  client: null,
220
221
  host,
@@ -232,7 +233,7 @@ class ExpressService {
232
233
  origins,
233
234
  path,
234
235
  });
235
- await UnderpostStartUp.API.listenPortController(peerServer, peerPort, {
236
+ await Underpost.start.listenPortController(peerServer, peerPort, {
236
237
  runtime: 'nodejs',
237
238
  client: null,
238
239
  host,
@@ -250,8 +251,8 @@ class ExpressService {
250
251
  if (useLocalSsl && process.env.NODE_ENV === 'development') {
251
252
  if (!TLS.validateSecureContext()) shellExec(`node bin/deploy tls`);
252
253
  const { ServerSSL } = await TLS.createSslServer(app);
253
- await UnderpostStartUp.API.listenPortController(ServerSSL, port, runningData);
254
- } else await UnderpostStartUp.API.listenPortController(server, port, runningData);
254
+ await Underpost.start.listenPortController(ServerSSL, port, runningData);
255
+ } else await Underpost.start.listenPortController(server, port, runningData);
255
256
 
256
257
  return { portsUsed };
257
258
  }
@@ -349,7 +349,12 @@ const cookieOptionsFactory = (req, host) => {
349
349
  secure,
350
350
  sameSite,
351
351
  path: '/',
352
- domain: process.env.NODE_ENV === 'production' || isDevProxyContext() ? host : 'localhost',
352
+ domain:
353
+ process.env.NODE_ENV === 'production' ||
354
+ isDevProxyContext() ||
355
+ (req.headers.host && req.headers.host.toLocaleLowerCase().match(host))
356
+ ? host
357
+ : 'localhost',
353
358
  maxAge,
354
359
  };
355
360
 
@@ -43,5 +43,15 @@ class BackUp {
43
43
  }
44
44
  };
45
45
  }
46
+ /**
47
+ * Main UnderpostBakcup class for backup operations.
48
+ * @class UnderpostBakcup
49
+ * @memberof UnderpostBakcup
50
+ */
51
+ class UnderpostBakcUp {
52
+ static API = BackUp;
53
+ }
54
+
55
+ export default UnderpostBakcUp;
46
56
 
47
- export default BackUp;
57
+ export { BackUp, UnderpostBakcUp };
@@ -22,7 +22,7 @@ import { loggerFactory } from './logger.js';
22
22
  import { shellExec } from './process.js';
23
23
  import { DefaultConf } from '../../conf.js';
24
24
  import splitFile from 'split-file';
25
- import UnderpostRootEnv from '../cli/env.js';
25
+ import Underpost from '../index.js';
26
26
 
27
27
  colors.enable();
28
28
 
@@ -59,7 +59,7 @@ const Config = {
59
59
  if (!subConf && process.argv[3] && typeof process.argv[3] === 'string') subConf = process.argv[3];
60
60
  if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`);
61
61
  if (!fs.existsSync(`./conf`)) fs.mkdirSync(`./conf`);
62
- UnderpostRootEnv.API.set('await-deploy', new Date().toISOString());
62
+ Underpost.env.set('await-deploy', new Date().toISOString());
63
63
  if (deployContext.startsWith('dd-')) loadConf(deployContext, subConf);
64
64
  if (deployContext === 'proxy') await Config.buildProxy(deployList, subConf);
65
65
  },
@@ -1050,9 +1050,9 @@ const validateTemplatePath = (absolutePath = '') => {
1050
1050
  * @memberof ServerConfBuilder
1051
1051
  */
1052
1052
  const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
1053
- if (init) UnderpostRootEnv.API.set('await-deploy', new Date().toISOString());
1053
+ if (init) Underpost.env.set('await-deploy', new Date().toISOString());
1054
1054
  await timer(deltaMs);
1055
- if (UnderpostRootEnv.API.get('await-deploy')) return await awaitDeployMonitor();
1055
+ if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor();
1056
1056
  };
1057
1057
 
1058
1058
  /**
@@ -1,15 +1,14 @@
1
1
  /**
2
- * UnderpostCron CLI index module
3
- * @module src/cli/cron.js
2
+ * UnderpostCron server module
3
+ * @module src/server/cron.js
4
4
  * @namespace UnderpostCron
5
5
  */
6
6
 
7
- import BackUp from '../server/backup.js';
8
- import { Cmd } from '../server/conf.js';
9
- import Dns from '../server/dns.js';
10
- import { loggerFactory } from '../server/logger.js';
11
- import { shellExec } from '../server/process.js';
7
+ import { Cmd } from './conf.js';
8
+ import { loggerFactory } from './logger.js';
9
+ import { shellExec } from './process.js';
12
10
  import fs from 'fs-extra';
11
+ import Underpost from '../index.js';
13
12
 
14
13
  const logger = loggerFactory(import.meta);
15
14
 
@@ -19,22 +18,30 @@ const logger = loggerFactory(import.meta);
19
18
  * @memberof UnderpostCron
20
19
  */
21
20
  class UnderpostCron {
22
- static JOB = {
23
- /**
24
- * DNS cli API
25
- * @static
26
- * @type {Dns}
27
- * @memberof UnderpostCron
28
- */
29
- dns: Dns,
30
- /**
31
- * BackUp cli API
32
- * @static
33
- * @type {BackUp}
34
- * @memberof UnderpostCron
35
- */
36
- backup: BackUp,
37
- };
21
+ /**
22
+ * Get the JOB static member
23
+ * @static
24
+ * @type {Object}
25
+ * @memberof UnderpostCron
26
+ */
27
+ static get JOB() {
28
+ return {
29
+ /**
30
+ * DNS cli API
31
+ * @static
32
+ * @type {Dns}
33
+ * @memberof UnderpostCron
34
+ */
35
+ dns: Underpost.dns,
36
+ /**
37
+ * BackUp cli API
38
+ * @static
39
+ * @type {BackUp}
40
+ * @memberof UnderpostCron
41
+ */
42
+ backup: Underpost.backup,
43
+ };
44
+ }
38
45
 
39
46
  static API = {
40
47
  /**
@@ -48,25 +55,25 @@ class UnderpostCron {
48
55
  */
49
56
  callback: async function (
50
57
  deployList = 'default',
51
- jobList = Object.keys(UnderpostCron.JOB).join(','),
58
+ jobList = Object.keys(Underpost.cron.JOB).join(','),
52
59
  options = { initPm2Cronjobs: false, git: false, updatePackageScripts: false },
53
60
  ) {
54
61
  if (options.updatePackageScripts === true) {
55
- await UnderpostCron.API.updatePackageScripts(deployList);
62
+ await Underpost.cron.updatePackageScripts(deployList);
56
63
  return;
57
64
  }
58
65
 
59
66
  if (options.initPm2Cronjobs === true) {
60
- await UnderpostCron.API.initCronJobs(options);
67
+ await Underpost.cron.initCronJobs(options);
61
68
  return;
62
69
  }
63
70
 
64
71
  // Execute the requested jobs
65
72
  for (const _jobId of jobList.split(',')) {
66
73
  const jobId = _jobId.trim();
67
- if (UnderpostCron.JOB[jobId]) {
74
+ if (Underpost.cron.JOB[jobId]) {
68
75
  logger.info(`Executing cron job: ${jobId}`);
69
- await UnderpostCron.JOB[jobId].callback(deployList, options);
76
+ await Underpost.cron.JOB[jobId].callback(deployList, options);
70
77
  } else {
71
78
  logger.warn(`Unknown cron job: ${jobId}`);
72
79
  }
@@ -115,7 +122,7 @@ class UnderpostCron {
115
122
  }
116
123
 
117
124
  const name = `${jobDeployId}-${job}`;
118
- const deployIdList = UnderpostCron.API.getRelatedDeployIdList(job);
125
+ const deployIdList = Underpost.cron.getRelatedDeployIdList(job);
119
126
  const expression = jobConfig.expression || '0 0 * * *'; // Default: daily at midnight
120
127
  const instances = jobConfig.instances || 1; // Default: 1 instance
121
128
 
@@ -221,6 +228,26 @@ class UnderpostCron {
221
228
  // Return the deploy-id list from the file (may be single or comma-separated)
222
229
  return fs.readFileSync(deployFilePath, 'utf8').trim();
223
230
  },
231
+
232
+ /**
233
+ * Get the JOB static object
234
+ * @static
235
+ * @type {Object}
236
+ * @memberof UnderpostCron
237
+ */
238
+ get JOB() {
239
+ return UnderpostCron.JOB;
240
+ },
241
+
242
+ /**
243
+ * Get the list of available job IDs
244
+ * @static
245
+ * @return {Array<String>} List of job IDs
246
+ * @memberof UnderpostCron
247
+ */
248
+ getJobsIDs: function () {
249
+ return Object.keys(UnderpostCron.JOB);
250
+ },
224
251
  };
225
252
  }
226
253