@underpostnet/underpost 2.8.4 → 2.8.5

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 (61) hide show
  1. package/.github/workflows/ghpkg.yml +13 -46
  2. package/.github/workflows/npmpkg.yml +67 -0
  3. package/.github/workflows/publish.yml +5 -5
  4. package/.github/workflows/pwa-microservices-template.page.yml +3 -2
  5. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  6. package/.vscode/settings.json +6 -1
  7. package/CHANGELOG.md +16 -0
  8. package/Dockerfile +6 -27
  9. package/bin/build.js +52 -169
  10. package/bin/deploy.js +6 -27
  11. package/bin/file.js +29 -15
  12. package/bin/index.js +158 -30
  13. package/bin/util.js +0 -8
  14. package/docker-compose.yml +1 -1
  15. package/manifests/mongodb/backup-access.yaml +16 -0
  16. package/manifests/mongodb/backup-cronjob.yaml +42 -0
  17. package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
  18. package/manifests/mongodb/configmap.yaml +26 -0
  19. package/manifests/mongodb/headless-service.yaml +10 -0
  20. package/manifests/mongodb/kustomization.yaml +11 -0
  21. package/manifests/mongodb/pv-pvc.yaml +23 -0
  22. package/manifests/mongodb/statefulset.yaml +125 -0
  23. package/manifests/valkey/kustomization.yaml +2 -2
  24. package/manifests/valkey/service.yaml +17 -0
  25. package/manifests/valkey/statefulset.yaml +39 -0
  26. package/package.json +21 -5
  27. package/src/api/core/core.service.js +1 -1
  28. package/src/cli/cluster.js +154 -0
  29. package/src/cli/cron.js +90 -0
  30. package/src/cli/db.js +148 -0
  31. package/src/cli/deploy.js +277 -0
  32. package/src/cli/env.js +52 -0
  33. package/src/cli/image.js +125 -0
  34. package/src/cli/repository.js +104 -0
  35. package/src/cli/script.js +29 -0
  36. package/src/cli/secrets.js +37 -0
  37. package/src/cli/test.js +83 -0
  38. package/src/client/components/core/Auth.js +22 -4
  39. package/src/client/components/core/CommonJs.js +82 -1
  40. package/src/client/components/core/Css.js +1 -0
  41. package/src/client/components/core/Input.js +1 -1
  42. package/src/client/components/core/Modal.js +0 -1
  43. package/src/client/components/core/Scroll.js +1 -0
  44. package/src/client/components/core/Translate.js +4 -0
  45. package/src/client/components/core/VanillaJs.js +0 -9
  46. package/src/client/components/core/Worker.js +34 -31
  47. package/src/client/ssr/body/CacheControl.js +2 -2
  48. package/src/index.js +77 -26
  49. package/src/server/backup.js +49 -93
  50. package/src/server/client-build.js +1 -10
  51. package/src/server/client-formatted.js +5 -3
  52. package/src/server/conf.js +68 -187
  53. package/src/server/dns.js +48 -65
  54. package/src/server/logger.js +7 -7
  55. package/src/server/network.js +17 -7
  56. package/src/server/runtime.js +8 -22
  57. package/src/dns.js +0 -22
  58. package/src/server/project.js +0 -39
  59. package/startup.cjs +0 -12
  60. /package/manifests/deployment/{mongo-express.yaml → mongo-express/deployment.yaml} +0 -0
  61. /package/manifests/deployment/{phpmyadmin.yaml → phpmyadmin/deployment.yaml} +0 -0
package/src/server/dns.js CHANGED
@@ -17,10 +17,8 @@ dotenv.config();
17
17
 
18
18
  const logger = loggerFactory(import.meta);
19
19
 
20
- const Dns = {
21
- repoUrl: `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USERNAME}/${process.env.GITHUB_DNS_REPO}.git`,
22
- callback: () => null,
23
- InitIpDaemon: async function ({ deployId }) {
20
+ class Dns {
21
+ static callback = async function (deployList) {
24
22
  // NAT-VPS modem/router device configuration:
25
23
  // LAN --> [NAT-VPS] --> WAN
26
24
  // enabled DMZ Host to proxy IP 80-443 (79-444) sometimes router block first port
@@ -30,56 +28,55 @@ const Dns = {
30
28
  // LAN server or device's local servers port -> 3000-3100 (2999-3101)
31
29
  // DNS Records: [ANAME](Address Dynamic) -> [A](ipv4) host | [AAAA](ipv6) host -> [public-ip]
32
30
  // Forward the router's TCP/UDP ports to the LAN device's IP address
33
-
31
+ for (const _deployId of deployList.split(',')) {
32
+ const deployId = _deployId.trim();
34
33
  const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
35
-
36
34
  const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
37
- let confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
38
- if (confCronData.ipDaemon.disabled) return;
39
- Dns.ip = confCronData.ipDaemon.ip;
40
- logger.info(`Current ip`, Dns.ip);
41
- const callback = async () => {
42
- logger.info('init dns ip callback');
43
- await logger.setUpInfo();
44
- let testIp;
45
- try {
46
- testIp = await ip.public.ipv4();
47
- } catch (error) {
48
- logger.error(error, { testIp, stack: error.stack });
49
- }
50
- if (testIp && typeof testIp === 'string' && validator.isIP(testIp) && Dns.ip !== testIp) {
51
- logger.info(`New ip`, testIp);
52
- for (const recordType of Object.keys(confCronData.records)) {
53
- switch (recordType) {
54
- case 'A':
55
- for (const dnsProvider of confCronData.records[recordType]) {
56
- if (typeof Dns.services.updateIp[dnsProvider.dns] === 'function')
57
- await Dns.services.updateIp[dnsProvider.dns]({ ...dnsProvider, ip: testIp });
58
- }
59
- break;
35
+ const confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
36
+
37
+ let testIp;
38
+
39
+ try {
40
+ testIp = await ip.public.ipv4();
41
+ } catch (error) {
42
+ logger.error(error, { testIp, stack: error.stack });
43
+ }
44
+ const ipFileName = `${deployId}.ip`;
45
+ const currentIp = fs.existsSync(`./engine-private/deploy/${ipFileName}`)
46
+ ? fs.readFileSync(`./engine-private/deploy/${ipFileName}`, 'utf8')
47
+ : undefined;
60
48
 
61
- default:
62
- break;
63
- }
49
+ if (testIp && typeof testIp === 'string' && validator.isIP(testIp) && currentIp !== testIp) {
50
+ logger.info(`new ip`, testIp);
51
+ for (const recordType of Object.keys(confCronData.records)) {
52
+ switch (recordType) {
53
+ case 'A':
54
+ for (const dnsProvider of confCronData.records[recordType]) {
55
+ if (typeof Dns.services.updateIp[dnsProvider.dns] === 'function')
56
+ await Dns.services.updateIp[dnsProvider.dns]({ ...dnsProvider, ip: testIp });
57
+ }
58
+ break;
59
+
60
+ default:
61
+ break;
64
62
  }
65
- try {
66
- const ipUrlTest = `https://${process.env.DEFAULT_DEPLOY_HOST}`;
67
- const response = await axios.get(ipUrlTest);
68
- const verifyIp = response.request.socket.remoteAddress;
69
- logger.info(ipUrlTest + ' IP', verifyIp);
70
- if (verifyIp === testIp) {
71
- await this.saveIp(confCronPath, confCronData, testIp);
72
- } else logger.error('ip not updated');
73
- } catch (error) {
74
- logger.error(error), 'ip not updated';
63
+ }
64
+ try {
65
+ const ipUrlTest = `https://${process.env.DEFAULT_DEPLOY_HOST}`;
66
+ const response = await axios.get(ipUrlTest);
67
+ const verifyIp = response.request.socket.remoteAddress;
68
+ logger.info(ipUrlTest + ' IP', verifyIp);
69
+ if (verifyIp === testIp) {
70
+ fs.writeFileSync(`./engine-private/deploy/${ipFileName}`, testIp, 'utf8');
71
+ } else logger.error('ip not updated');
72
+ } catch (error) {
73
+ logger.error(error), 'ip not updated';
75
74
  }
76
75
  }
77
- };
78
- await callback();
79
- this.callback = callback;
80
- return callback;
81
- },
82
- services: {
76
+ }
77
+ };
78
+
79
+ static services = {
83
80
  updateIp: {
84
81
  dondominio: (options) => {
85
82
  const { user, api_key, host, dns, ip } = options;
@@ -100,21 +97,7 @@ const Dns = {
100
97
  });
101
98
  },
102
99
  },
103
- },
104
- saveIp: async (confCronPath, confCronData, ip) => {
105
- Dns.ip = ip;
106
- confCronData.ipDaemon.ip = ip;
107
- fs.writeFileSync(confCronPath, JSON.stringify(confCronData, null, 4), 'utf8');
108
- shellExec(
109
- `cd ./engine-private` +
110
- ` && git pull ${Dns.repoUrl}` +
111
- ` && git add . && git commit -m "update ip ${new Date().toLocaleDateString()}"` +
112
- ` && git push ${Dns.repoUrl}`,
113
- {
114
- disableLog: true,
115
- },
116
- );
117
- },
118
- };
100
+ };
101
+ }
119
102
 
120
- export { Dns };
103
+ export default Dns;
@@ -84,8 +84,8 @@ const format = (meta) =>
84
84
  * @memberof Logger
85
85
  */
86
86
  const setUpInfo = async (logger = new winston.Logger()) => {
87
- logger.info('npm_package_version', process.env.npm_package_version);
88
87
  logger.info('argv', process.argv);
88
+ logger.info('cwd', process.cwd());
89
89
  logger.info('platform', process.platform);
90
90
  logger.info('env', process.env.NODE_ENV);
91
91
  logger.info('--max-old-space-size', {
@@ -112,10 +112,10 @@ const loggerFactory = (meta = { url: '' }) => {
112
112
  // Allow the use the terminal to print the messages
113
113
  new winston.transports.Console(),
114
114
  // Allow to print all the error level messages inside the error.log file
115
- new winston.transports.File({
116
- filename: `logs/${meta}/error.log`,
117
- level: 'error',
118
- }),
115
+ // new winston.transports.File({
116
+ // filename: `logs/${meta}/error.log`,
117
+ // level: 'error',
118
+ // }),
119
119
  // Allow to print all the error message inside the all.log file
120
120
  // (also the error log that are also printed inside the error.log(
121
121
  new winston.transports.File({ filename: `logs/${meta}/all.log` }),
@@ -186,11 +186,11 @@ const underpostASCI = () => `
186
186
  ░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚═╝░░░░░░╚════╝░╚═════╝░░░░╚═╝░░░
187
187
  `;
188
188
 
189
- const actionInitLog = (version = '0.0.0') =>
189
+ const actionInitLog = () =>
190
190
  console.log(
191
191
  underpostASCI() +
192
192
  `
193
- ${version} https://www.nexodev.org/docs
193
+ https://www.nexodev.org/docs
194
194
  `,
195
195
  );
196
196
 
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs-extra';
2
2
 
3
3
  import { publicIp, publicIpv4, publicIpv6 } from 'public-ip';
4
- import { loggerFactory } from './logger.js';
4
+ import { actionInitLog, loggerFactory } from './logger.js';
5
5
  import { DataBaseProvider } from '../db/DataBaseProvider.js';
6
6
  import { getDeployId } from './conf.js';
7
7
 
@@ -39,8 +39,8 @@ const saveRuntimeRouter = async () => {
39
39
  const host = process.env.DEFAULT_DEPLOY_HOST;
40
40
  const path = process.env.DEFAULT_DEPLOY_PATH;
41
41
  const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
42
- if (!deployId || !host || !path) {
43
- logger.warn('default deploy instance not found');
42
+ if (!deployId || !host || !path || !fs.existsSync(confServerPath)) {
43
+ // logger.warn('default deploy instance not found');
44
44
  return;
45
45
  }
46
46
  const confServer = JSON.parse(fs.readFileSync(confServerPath, 'utf8'));
@@ -77,7 +77,7 @@ const saveRuntimeRouter = async () => {
77
77
 
78
78
  if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
79
79
  } catch (error) {
80
- logger.error(error);
80
+ logger.error(error, error.stack);
81
81
  }
82
82
  };
83
83
 
@@ -114,20 +114,30 @@ const saveRuntimeCron = async () => {
114
114
 
115
115
  if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
116
116
  } catch (error) {
117
- logger.error(error);
117
+ logger.error(error, error.stack);
118
118
  }
119
119
  };
120
120
 
121
121
  const listenServerFactory = (logic = async () => {}) => {
122
122
  return {
123
- listen: async (...args) => (logic ? await logic(...args) : undefined, args[1]()),
123
+ listen: async (...args) => (
124
+ setTimeout(() => {
125
+ const message = 'Listen server factory timeout';
126
+ logger.error(message);
127
+ throw new Error(message);
128
+ }, 80000000), // ~ 55 days
129
+ (logic ? await logic(...args) : undefined, args[1]())
130
+ ),
124
131
  };
125
132
  };
126
133
 
127
134
  const listenPortController = async (server, port, metadata) =>
128
135
  new Promise((resolve) => {
129
136
  try {
130
- if (!server) server = listenServerFactory();
137
+ if (port === ':') {
138
+ server.listen(port, actionInitLog);
139
+ return resolve(true);
140
+ }
131
141
 
132
142
  const { host, path, client, runtime, meta } = metadata;
133
143
  const error = [];
@@ -15,7 +15,7 @@ import { getCapVariableName, newInstance } from '../client/components/core/Commo
15
15
  import { Xampp } from '../runtime/xampp/Xampp.js';
16
16
  import { MailerProvider } from '../mailer/MailerProvider.js';
17
17
  import { DataBaseProvider } from '../db/DataBaseProvider.js';
18
- import { createProxyMiddleware } from 'http-proxy-middleware';
18
+ // import { createProxyMiddleware } from 'http-proxy-middleware';
19
19
  import { createPeerServer } from './peer.js';
20
20
  import { Lampp } from '../runtime/lampp/Lampp.js';
21
21
  import { getDeployId } from './conf.js';
@@ -31,20 +31,6 @@ const buildRuntime = async () => {
31
31
  const collectDefaultMetrics = promClient.collectDefaultMetrics;
32
32
  collectDefaultMetrics();
33
33
 
34
- if (fs.existsSync(`/root/.bashrc`) && !fs.readFileSync(`/root/.bashrc`, 'utf8').match(`underpost-engine`)) {
35
- fs.writeFileSync(
36
- `/root/.bashrc`,
37
- `${fs.readFileSync(`/root/.bashrc`, 'utf8')}
38
- ` +
39
- `export NVM_DIR="$HOME/.nvm"
40
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
41
- [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm underpost-engine bash_completion
42
-
43
- export PATH=$PATH:/opt/lampp/bin`,
44
- 'utf8',
45
- );
46
- }
47
-
48
34
  const promCounterOption = {
49
35
  name: `${deployId.replaceAll('-', '_')}_http_requests_total`,
50
36
  help: 'Total number of HTTP requests',
@@ -54,7 +40,6 @@ export PATH=$PATH:/opt/lampp/bin`,
54
40
  // logger.info('promCounterOption', promCounterOption);
55
41
 
56
42
  const requestCounter = new promClient.Counter(promCounterOption);
57
-
58
43
  const ipInstance = ''; // await ip.public.ipv4();
59
44
  const initPort = parseInt(process.env.PORT) + 1;
60
45
  let currentPort = initPort;
@@ -101,12 +86,13 @@ export PATH=$PATH:/opt/lampp/bin`,
101
86
  apis,
102
87
  };
103
88
 
104
- let redirectUrl;
105
- let redirectTarget;
106
- if (redirect) {
107
- redirectUrl = new URL(redirect);
108
- redirectTarget = redirect[redirect.length - 1] === '/' ? redirect.slice(0, -1) : redirect;
109
- }
89
+ const redirectTarget = redirect
90
+ ? redirect[redirect.length - 1] === '/'
91
+ ? redirect.slice(0, -1)
92
+ : redirect
93
+ : undefined;
94
+
95
+ // if (redirect) logger.info('redirect', new URL(redirect));
110
96
 
111
97
  switch (runtime) {
112
98
  case 'lampp':
package/src/dns.js DELETED
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- // https://nodejs.org/api
4
- // https://expressjs.com/en/4x/api.html
5
-
6
- import dotenv from 'dotenv';
7
- import { loggerFactory } from './server/logger.js';
8
- import { Dns } from './server/dns.js';
9
- import { ProcessController } from './server/process.js';
10
- import { Config } from './server/conf.js';
11
-
12
- dotenv.config();
13
-
14
- await Config.build();
15
-
16
- const logger = loggerFactory(import.meta);
17
-
18
- await logger.setUpInfo();
19
-
20
- await Dns.InitIpDaemon();
21
-
22
- ProcessController.init(logger);
@@ -1,39 +0,0 @@
1
- import { loadConf, newProject, repoClone, repoCommit, repoPull, repoPush } from './conf.js';
2
-
3
- class Project {
4
- constructor(repositoryName, version) {
5
- return newProject(repositoryName, version);
6
- }
7
-
8
- static clone(gitUri = 'underpostnet/pwa-microservices-template') {
9
- return repoClone(gitUri);
10
- }
11
-
12
- static useEnv(deployId = 'default', env = 'production') {
13
- return loadConf(deployId, env);
14
- }
15
-
16
- static pull(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template') {
17
- return repoPull(repoPath, gitUri);
18
- }
19
-
20
- static commit(
21
- repoPath = './',
22
- commitType = 'feat',
23
- subModule = '',
24
- message = '',
25
- options = {
26
- copy: false,
27
- info: false,
28
- empty: false,
29
- },
30
- ) {
31
- return repoCommit(repoPath, commitType, subModule, message, options);
32
- }
33
-
34
- static push(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template') {
35
- return repoPush(repoPath, gitUri);
36
- }
37
- }
38
-
39
- export default Project;
package/startup.cjs DELETED
@@ -1,12 +0,0 @@
1
- const shell = require('shelljs');
2
-
3
- // /usr/bin/supervisord -n
4
- // /usr/sbin/sshd -D
5
-
6
- shell.exec(`/usr/bin/supervisord -n`, { async: true });
7
-
8
- // shell.exec(`sudo /opt/lampp/lampp start`, { async: true });
9
-
10
- // shell.exec(`/usr/bin/mongod -f /etc/mongod.conf`, { async: true });
11
-
12
- shell.exec(`underpost new app`);