@underpostnet/underpost 2.8.4 → 2.8.6

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 (82) hide show
  1. package/.github/workflows/ghpkg.yml +12 -45
  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 +2 -1
  5. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  6. package/.vscode/settings.json +10 -1
  7. package/CHANGELOG.md +40 -0
  8. package/Dockerfile +6 -27
  9. package/bin/build.js +73 -165
  10. package/bin/deploy.js +76 -101
  11. package/bin/file.js +29 -15
  12. package/bin/hwt.js +0 -10
  13. package/bin/index.js +191 -32
  14. package/bin/util.js +0 -15
  15. package/bin/vs.js +1 -0
  16. package/conf.js +0 -2
  17. package/docker-compose.yml +1 -1
  18. package/manifests/kind-config-dev.yaml +12 -0
  19. package/manifests/{core/underpost-engine-mongodb-backup-cronjob.yaml → mongodb/backup-cronjob.yaml} +14 -12
  20. package/manifests/mongodb/kustomization.yaml +11 -0
  21. package/manifests/mongodb/pv-pvc.yaml +23 -0
  22. package/manifests/{core/underpost-engine-statefulset.yaml → mongodb/statefulset.yaml} +34 -0
  23. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  24. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  25. package/manifests/valkey/kustomization.yaml +2 -2
  26. package/package.json +22 -4
  27. package/src/api/core/core.service.js +1 -1
  28. package/src/cli/cluster.js +202 -0
  29. package/src/cli/cron.js +90 -0
  30. package/src/cli/db.js +212 -0
  31. package/src/cli/deploy.js +318 -0
  32. package/src/cli/env.js +52 -0
  33. package/src/cli/fs.js +149 -0
  34. package/src/cli/image.js +148 -0
  35. package/src/cli/repository.js +125 -0
  36. package/src/cli/script.js +53 -0
  37. package/src/cli/secrets.js +37 -0
  38. package/src/cli/test.js +118 -0
  39. package/src/client/components/core/Auth.js +22 -4
  40. package/src/client/components/core/CalendarCore.js +12 -1
  41. package/src/client/components/core/CommonJs.js +134 -2
  42. package/src/client/components/core/Css.js +1 -0
  43. package/src/client/components/core/CssCore.js +2 -4
  44. package/src/client/components/core/Docs.js +1 -2
  45. package/src/client/components/core/Input.js +5 -3
  46. package/src/client/components/core/LoadingAnimation.js +8 -1
  47. package/src/client/components/core/Modal.js +30 -7
  48. package/src/client/components/core/Panel.js +8 -6
  49. package/src/client/components/core/PanelForm.js +23 -7
  50. package/src/client/components/core/Scroll.js +1 -0
  51. package/src/client/components/core/Translate.js +4 -0
  52. package/src/client/components/core/VanillaJs.js +0 -9
  53. package/src/client/components/core/Worker.js +34 -31
  54. package/src/client/services/core/core.service.js +15 -10
  55. package/src/client/ssr/Render.js +4 -1
  56. package/src/client/ssr/body/CacheControl.js +2 -3
  57. package/src/client/sw/default.sw.js +3 -3
  58. package/src/db/mongo/MongooseDB.js +17 -1
  59. package/src/index.js +85 -26
  60. package/src/server/backup.js +49 -93
  61. package/src/server/client-build.js +33 -33
  62. package/src/server/client-formatted.js +6 -3
  63. package/src/server/conf.js +82 -199
  64. package/src/server/dns.js +29 -53
  65. package/src/server/downloader.js +0 -8
  66. package/src/server/logger.js +7 -7
  67. package/src/server/network.js +17 -7
  68. package/src/server/runtime.js +24 -23
  69. package/test/api.test.js +0 -8
  70. package/manifests/core/kustomization.yaml +0 -11
  71. package/src/dns.js +0 -22
  72. package/src/server/project.js +0 -39
  73. package/startup.cjs +0 -12
  74. /package/manifests/deployment/{mongo-express.yaml → mongo-express/deployment.yaml} +0 -0
  75. /package/manifests/deployment/{phpmyadmin.yaml → phpmyadmin/deployment.yaml} +0 -0
  76. /package/manifests/{core/underpost-engine-backup-access.yaml → mongodb/backup-access.yaml} +0 -0
  77. /package/manifests/{core/underpost-engine-backup-pv-pvc.yaml → mongodb/backup-pv-pvc.yaml} +0 -0
  78. /package/manifests/{core/underpost-engine-mongodb-configmap.yaml → mongodb/configmap.yaml} +0 -0
  79. /package/manifests/{core/underpost-engine-headless-service.yaml → mongodb/headless-service.yaml} +0 -0
  80. /package/manifests/{core/underpost-engine-pv-pvc.yaml → mongodb-4.4/pv-pvc.yaml} +0 -0
  81. /package/manifests/valkey/{underpost-engine-valkey-service.yaml → service.yaml} +0 -0
  82. /package/manifests/valkey/{underpost-engine-valkey-statefulset.yaml → statefulset.yaml} +0 -0
@@ -13,23 +13,14 @@ import cliProgress from 'cli-progress';
13
13
  import cliSpinners from 'cli-spinners';
14
14
  import logUpdate from 'log-update';
15
15
  import colors from 'colors';
16
- import { actionInitLog, loggerFactory } from './logger.js';
17
- import { pbcopy, shellExec } from './process.js';
16
+ import { loggerFactory } from './logger.js';
17
+ import { shellExec } from './process.js';
18
18
  import { DefaultConf } from '../../conf.js';
19
19
  import read from 'read';
20
20
  import splitFile from 'split-file';
21
21
  import axios from 'axios';
22
- import https from 'https';
23
22
  import { ssrFactory } from './client-formatted.js';
24
23
 
25
- // axios.defaults.baseURL = BASE_URL;
26
-
27
- // const httpsAgent = new https.Agent({
28
- // rejectUnauthorized: false,
29
- // });
30
-
31
- // axios.defaults.httpsAgent = httpsAgent;
32
-
33
24
  colors.enable();
34
25
 
35
26
  dotenv.config();
@@ -40,21 +31,26 @@ const logger = loggerFactory(import.meta);
40
31
 
41
32
  const Config = {
42
33
  default: DefaultConf,
43
- build: async function (options = { folder: '' }) {
34
+ build: async function (options = { folder: '' }, deployContext, deployList, subConf) {
35
+ if (!deployContext) deployContext = process.argv[2];
44
36
  if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`, { recursive: true });
45
37
  fs.writeFileSync(`./tmp/await-deploy`, '', 'utf8');
46
- if (fs.existsSync(`./engine-private/conf/${process.argv[2]}`)) return loadConf(process.argv[2]);
47
- if (fs.existsSync(`./engine-private/replica/${process.argv[2]}`)) return loadConf(process.argv[2]);
38
+ if (fs.existsSync(`./engine-private/conf/${deployContext}`))
39
+ return loadConf(deployContext, process.env.NODE_ENV, subConf);
40
+ if (fs.existsSync(`./engine-private/replica/${deployContext}`))
41
+ return loadConf(deployContext, process.env.NODE_ENV, subConf);
48
42
 
49
- if (process.argv[2] === 'deploy') return;
43
+ if (deployContext === 'deploy') return;
50
44
 
51
- if (process.argv[2] === 'proxy') {
45
+ if (deployContext === 'proxy') {
46
+ if (!deployList) deployList = process.argv[3];
47
+ if (!subConf) subConf = process.argv[4];
52
48
  this.default.server = {};
53
- for (const deployId of process.argv[3].split(',')) {
49
+ for (const deployId of deployList.split(',')) {
54
50
  let confPath = `./engine-private/conf/${deployId}/conf.server.json`;
55
51
  const privateConfDevPath = fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
56
52
  ? `./engine-private/replica/${deployId}/conf.server.json`
57
- : `./engine-private/conf/${deployId}/conf.server.dev.${process.argv[4]}.json`;
53
+ : `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
58
54
  const confDevPath = fs.existsSync(privateConfDevPath)
59
55
  ? privateConfDevPath
60
56
  : `./engine-private/conf/${deployId}/conf.server.dev.json`;
@@ -62,7 +58,7 @@ const Config = {
62
58
  if (process.env.NODE_ENV === 'development' && fs.existsSync(confDevPath)) confPath = confDevPath;
63
59
  const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
64
60
 
65
- for (const host of Object.keys(loadReplicas(serverConf))) {
61
+ for (const host of Object.keys(loadReplicas(serverConf, deployContext, subConf))) {
66
62
  if (serverConf[host]['/'])
67
63
  this.default.server[host] = {
68
64
  ...this.default.server[host],
@@ -92,7 +88,15 @@ const Config = {
92
88
  },
93
89
  };
94
90
 
95
- const loadConf = (deployId, envInput) => {
91
+ const loadConf = (deployId, envInput, subConf) => {
92
+ if (deployId === 'clean') {
93
+ shellExec(`git checkout package.json`);
94
+ shellExec(`git checkout .env.production`);
95
+ shellExec(`git checkout .env.development`);
96
+ shellExec(`git checkout .env.test`);
97
+ shellExec(`git checkout jsdoc.json`);
98
+ return;
99
+ }
96
100
  const folder = fs.existsSync(`./engine-private/replica/${deployId}`)
97
101
  ? `./engine-private/replica/${deployId}`
98
102
  : `./engine-private/conf/${deployId}`;
@@ -109,7 +113,8 @@ const loadConf = (deployId, envInput) => {
109
113
  ? fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8')
110
114
  : JSON.stringify(Config.default[typeConf]);
111
115
  if (process.env.NODE_ENV === 'development' && typeConf === 'server') {
112
- const devConfPath = `${folder}/conf.${typeConf}.dev${process.argv[3] ? `.${process.argv[3]}` : ''}.json`;
116
+ if (!subConf) subConf = process.argv[3];
117
+ const devConfPath = `${folder}/conf.${typeConf}.dev${subConf ? `.${subConf}` : ''}.json`;
113
118
  if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
114
119
  }
115
120
  if (typeConf === 'server') srcConf = JSON.stringify(loadReplicas(JSON.parse(srcConf)), null, 4);
@@ -127,19 +132,25 @@ const loadConf = (deployId, envInput) => {
127
132
  ...env,
128
133
  };
129
134
  }
130
- fs.writeFileSync(`./package.json`, fs.readFileSync(`${folder}/package.json`, 'utf8'), 'utf8');
135
+ const originPackageJson = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
136
+ const packageJson = JSON.parse(fs.readFileSync(`${folder}/package.json`, 'utf8'));
137
+ originPackageJson.scripts.start = packageJson.scripts.start;
138
+ packageJson.scripts = originPackageJson.scripts;
139
+ fs.writeFileSync(`./package.json`, JSON.stringify(packageJson, null, 4), 'utf8');
131
140
  return { folder, deployId };
132
141
  };
133
142
 
134
- const loadReplicas = (confServer) => {
143
+ const loadReplicas = (confServer, deployContext, subConf) => {
144
+ if (!deployContext) deployContext = process.argv[2];
145
+ if (!subConf) subConf = process.argv[3];
135
146
  for (const host of Object.keys(confServer)) {
136
147
  for (const path of Object.keys(confServer[host])) {
137
148
  const { replicas, singleReplica } = confServer[host][path];
138
149
  if (
139
150
  replicas &&
140
- (process.argv[2] === 'proxy' ||
151
+ (deployContext === 'proxy' ||
141
152
  !singleReplica ||
142
- (singleReplica && process.env.NODE_ENV === 'development' && !process.argv[3]))
153
+ (singleReplica && process.env.NODE_ENV === 'development' && !subConf))
143
154
  )
144
155
  for (const replicaPath of replicas) {
145
156
  confServer[host][replicaPath] = newInstance(confServer[host][path]);
@@ -509,21 +520,25 @@ const buildPortProxyRouter = (port, proxyRouter) => {
509
520
  // build router
510
521
  Object.keys(hosts).map((hostKey) => {
511
522
  let { host, path, target, proxy, peer } = hosts[hostKey];
512
- if (process.env.NODE_ENV === 'development') host = `localhost`;
523
+ if (process.argv.includes('localhost') && process.env.NODE_ENV === 'development') host = `localhost`;
513
524
 
514
525
  if (!proxy.includes(port)) return;
515
526
  const absoluteHost = [80, 443].includes(port)
516
527
  ? `${host}${path === '/' ? '' : path}`
517
528
  : `${host}:${port}${path === '/' ? '' : path}`;
518
529
 
519
- if (!(absoluteHost in router)) router[absoluteHost] = target;
530
+ if (process.argv.includes('localhost')) {
531
+ if (!(absoluteHost in router)) router[absoluteHost] = target;
532
+ } else router[absoluteHost] = target;
520
533
  }); // order router
521
534
 
522
535
  if (Object.keys(router).length === 0) return router;
523
536
 
537
+ const reOrderRouter = {};
524
538
  for (const absoluteHostKey of orderArrayFromAttrInt(Object.keys(router), 'length'))
525
- router[absoluteHostKey] = router[absoluteHostKey];
526
- return router;
539
+ reOrderRouter[absoluteHostKey] = router[absoluteHostKey];
540
+
541
+ return reOrderRouter;
527
542
  };
528
543
 
529
544
  const cliBar = async (time = 5000) => {
@@ -574,9 +589,25 @@ const cliSpinner = async (time = 5000, message0, message1, color, type = 'dots')
574
589
  const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1)}`;
575
590
 
576
591
  const getDataDeploy = (
577
- options = { buildSingleReplica: false, deployGroupId: '', deployId: '', disableSyncEnvPort: false },
592
+ options = {
593
+ buildSingleReplica: false,
594
+ deployGroupId: '',
595
+ deployId: '',
596
+ disableSyncEnvPort: false,
597
+ deployIdConcat: [],
598
+ },
578
599
  ) => {
579
- let dataDeploy = JSON.parse(fs.readFileSync(`./engine-private/deploy/${options.deployGroupId}.json`, 'utf8'));
600
+ let dataDeploy =
601
+ options.deployGroupId === 'dd'
602
+ ? fs.readFileSync(`./engine-private/deploy/${options.deployGroupId}.router`, 'utf8')
603
+ : fs.readFileSync(`./engine-private/deploy/${options.deployGroupId}`, 'utf8');
604
+
605
+ dataDeploy = dataDeploy
606
+ .split(',')
607
+ .map((deployId) => deployId.trim())
608
+ .filter((deployId) => deployId);
609
+
610
+ if (options.deployIdConcat) dataDeploy = dataDeploy.concat(options.deployIdConcat);
580
611
 
581
612
  if (options.deployId) dataDeploy = dataDeploy.filter((d) => d === options.deployId);
582
613
 
@@ -811,7 +842,7 @@ const deployRun = async (dataDeploy, currentAttempt = 1) => {
811
842
  if (failed.length > 0) {
812
843
  for (const deploy of failed) logger.error(deploy.deployId, Cmd.run(deploy.deployId));
813
844
  if (currentAttempt === maxAttempts) return logger.error(`max deploy attempts exceeded`);
814
- if (process.argv.includes('manual')) await read({ prompt: 'Press enter to retry failed processes\n' });
845
+ await read({ prompt: 'Press enter to retry failed processes\n' });
815
846
  currentAttempt++;
816
847
  await deployRun(failed, currentAttempt);
817
848
  } else logger.info(`Deploy process successfully`);
@@ -957,15 +988,15 @@ const getPathsSSR = (conf) => {
957
988
 
958
989
  const Cmd = {
959
990
  delete: (deployId) => `pm2 delete ${deployId}`,
960
- run: (deployId) => `node bin/deploy run ${deployId}`,
991
+ run: () => `npm start`,
961
992
  build: (deployId) => `node bin/deploy build-full-client ${deployId}${process.argv.includes('l') ? ' l' : ''}`,
962
993
  conf: (deployId, env) => `node bin/deploy conf ${deployId} ${env ? env : 'production'}`,
963
994
  replica: (deployId, host, path) => `node bin/deploy build-single-replica ${deployId} ${host} ${path}`,
964
995
  syncPorts: (deployGroupId) => `node bin/deploy sync-env-port ${deployGroupId}`,
965
- cron: (deployId, job, expression) => {
966
- shellExec(Cmd.delete(`${deployId}-${job}`));
967
- return `env-cmd -f .env.production pm2 start bin/cron.js --no-autorestart --instances 1 --cron "${expression}" --name ${deployId}-${job} -- ${job} ${deployId}`;
968
- },
996
+ cron: (deployList, jobList, name, expression, options) =>
997
+ `pm2 start ./bin/index.js --no-autorestart --instances 1 --cron "${expression}" --name ${name} -- cron ${
998
+ options?.itc ? `--itc ` : ''
999
+ }${options?.git ? `--git ` : ''}${deployList} ${jobList}`,
969
1000
  };
970
1001
 
971
1002
  const fixDependencies = async () => {
@@ -1032,170 +1063,26 @@ const setUpProxyMaintenanceServer = ({ deployGroupId }) => {
1032
1063
  shellExec(`node bin/deploy valkey-service`);
1033
1064
  const proxyDeployId = fs.readFileSync(`./engine-private/deploy/${deployGroupId}.proxy`, 'utf8').trim();
1034
1065
  shellExec(`node bin/deploy conf ${proxyDeployId} production`);
1035
- shellExec(`node bin/deploy run ${proxyDeployId} maintenance`);
1036
- };
1037
-
1038
- const repoClone = (gitUri = 'underpostnet/pwa-microservices-template') => {
1039
- const repoName = gitUri.split('/').pop();
1040
- if (fs.existsSync(`./${repoName}`)) fs.removeSync(`./${repoName}`);
1041
- shellExec(
1042
- `git clone https://${process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''}github.com/${gitUri}.git`,
1043
- );
1044
- if (process.env.GITHUB_TOKEN) {
1045
- shellExec(
1046
- `git clone https://${
1047
- process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''
1048
- }github.com/${gitUri}-private.git`,
1049
- );
1050
- fs.moveSync(`./${repoName}-private`, `./${repoName}/engine-private`, {
1051
- overwrite: true,
1052
- });
1053
- }
1054
- };
1055
-
1056
- const repoPull = (repoPath = './', gitUri = 'underpostnet/pwa-microservices-template') => {
1057
- shellExec(`cd ${repoPath} && git pull https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}.git`, {
1058
- disableLog: true,
1059
- });
1060
- };
1061
-
1062
- const commitData = {
1063
- feat: {
1064
- description: 'A new feature',
1065
- title: 'Features',
1066
- emoji: '✨',
1067
- },
1068
- fix: {
1069
- description: 'A bug fix',
1070
- title: 'Bug Fixes',
1071
- emoji: '🐛',
1072
- },
1073
- docs: {
1074
- description: 'Documentation only changes',
1075
- title: 'Documentation',
1076
- emoji: '📚',
1077
- },
1078
- style: {
1079
- description:
1080
- 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
1081
- title: 'Styles',
1082
- emoji: '💎',
1083
- },
1084
- refactor: {
1085
- description: 'A code change that neither fixes a bug nor adds a feature',
1086
- title: 'Code Refactoring',
1087
- emoji: '📦',
1088
- },
1089
- perf: {
1090
- description: 'A code change that improves performance',
1091
- title: 'Performance Improvements',
1092
- emoji: '⚡️',
1093
- },
1094
- cd: {
1095
- description:
1096
- 'Changes to our Continuous Delivery configuration files and scripts (example scopes: Jenkins, Spinnaker, ArgoCD)',
1097
- title: 'Continuous Delivery',
1098
- emoji: '🚀',
1099
- },
1100
- test: {
1101
- description: 'Adding missing tests or correcting existing tests',
1102
- title: 'Tests',
1103
- emoji: '🚨',
1104
- },
1105
- build: {
1106
- description: 'Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)',
1107
- title: 'Builds',
1108
- emoji: '🛠',
1109
- },
1110
- ci: {
1111
- description:
1112
- 'Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)',
1113
- title: 'Continuous Integrations',
1114
- emoji: '⚙️',
1115
- },
1116
- chore: {
1117
- description: "Other changes that don't modify src or test files",
1118
- title: 'Chores',
1119
- emoji: '♻️',
1120
- },
1121
- revert: {
1122
- description: 'Reverts a previous commit',
1123
- title: 'Reverts',
1124
- emoji: '🗑',
1125
- },
1126
- backup: {
1127
- description: 'Changes related to backups, including creation, restoration, and maintenance.',
1128
- title: 'Backups',
1129
- emoji: '💾',
1130
- },
1131
- };
1132
-
1133
- const repoCommit = (
1134
- repoPath = './',
1135
- commitType = 'feat',
1136
- subModule = '',
1137
- message = '',
1138
- options = {
1139
- copy: false,
1140
- info: false,
1141
- empty: false,
1142
- },
1143
- ) => {
1144
- if (options.info) return logger.info('', commitData);
1145
- const _message = `${commitType}${subModule ? `(${subModule})` : ''}${process.argv.includes('!') ? '!' : ''}: ${
1146
- commitData[commitType].emoji
1147
- } ${message ? message : commitData[commitType].description}`;
1148
- if (options.copy) return pbcopy(_message);
1149
- shellExec(`cd ${repoPath} && git commit ${options?.empty ? `--allow-empty ` : ''}-m "${_message}"`);
1150
- };
1151
-
1152
- const repoPush = (repoPath = './', gitUri = 'underpostnet/pwa-microservices-template') => {
1153
- shellExec(`cd ${repoPath} && git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}.git`, {
1154
- disableLog: true,
1155
- });
1156
- logger.info(
1157
- 'commit url',
1158
- `http://github.com/${gitUri}/commit/${shellExec(`cd ${repoPath} && git rev-parse --verify HEAD`, {
1159
- stdout: true,
1160
- }).trim()}`,
1161
- );
1066
+ shellExec(`npm start ${proxyDeployId} maintenance`);
1162
1067
  };
1163
1068
 
1164
1069
  const getNpmRootPath = () =>
1165
1070
  shellExec(`npm root -g`, {
1166
1071
  stdout: true,
1072
+ disableLog: true,
1073
+ silent: true,
1167
1074
  }).trim();
1168
1075
 
1169
- const newProject = (repositoryName, version) => {
1170
- return new Promise(async (resolve, reject) => {
1171
- try {
1172
- const exeRootPath = `${getNpmRootPath()}/underpost`;
1173
- // const exeRootPath = '/home/dd/pwa-microservices-template';
1174
- actionInitLog(version);
1175
- await logger.setUpInfo();
1176
- const destFolder = `${process.cwd()}/${repositoryName}`;
1177
- logger.info('Note: This process may take several minutes to complete');
1178
- logger.info('build app', { destFolder });
1179
- fs.mkdirSync(destFolder, { recursive: true });
1180
- fs.copySync(exeRootPath, destFolder);
1181
- if (fs.existsSync(`${destFolder}/node_modules`)) fs.removeSync(`${destFolder}/node_modules`);
1182
- fs.writeFileSync(`${destFolder}/.gitignore`, fs.readFileSync(`${exeRootPath}/.dockerignore`, 'utf8'), 'utf8');
1183
- shellExec(`cd ${destFolder} && git init && git add . && git commit -m "Base template implementation"`);
1184
- shellExec(`cd ${destFolder} && npm install`);
1185
- shellExec(`cd ${destFolder} && npm run build`);
1186
- shellExec(`cd ${destFolder} && npm run dev`);
1187
- return resolve();
1188
- } catch (error) {
1189
- logger.error(error, error.stack);
1190
- return reject(error.message);
1191
- }
1192
- });
1193
- };
1076
+ const getUnderpostRootPath = () => `${getNpmRootPath()}/underpost`;
1194
1077
 
1195
- const runTest = (version) => {
1196
- actionInitLog(version);
1197
- shellExec(`cd ${getNpmRootPath()}/underpost && npm run test`);
1198
- };
1078
+ const writeEnv = (envPath, envObj) =>
1079
+ fs.writeFileSync(
1080
+ envPath,
1081
+ Object.keys(envObj)
1082
+ .map((key) => `${key}=${envObj[key]}`)
1083
+ .join(`\n`),
1084
+ 'utf8',
1085
+ );
1199
1086
 
1200
1087
  export {
1201
1088
  Cmd,
@@ -1232,11 +1119,7 @@ export {
1232
1119
  buildKindPorts,
1233
1120
  buildPortProxyRouter,
1234
1121
  splitFileFactory,
1235
- repoClone,
1236
- repoPull,
1237
- repoCommit,
1238
- repoPush,
1239
- newProject,
1240
- runTest,
1241
1122
  getNpmRootPath,
1123
+ getUnderpostRootPath,
1124
+ writeEnv,
1242
1125
  };
package/src/server/dns.js CHANGED
@@ -1,28 +1,19 @@
1
1
  import axios from 'axios';
2
2
  import dotenv from 'dotenv';
3
3
  import fs from 'fs';
4
- import https from 'https';
5
4
  import validator from 'validator';
6
5
  import { ip } from './network.js';
7
6
  import { loggerFactory } from './logger.js';
8
- import { shellExec } from './process.js';
9
-
10
- const httpsAgent = new https.Agent({
11
- rejectUnauthorized: false,
12
- });
13
-
14
- axios.defaults.httpsAgent = httpsAgent;
7
+ import UnderpostRootEnv from '../cli/env.js';
15
8
 
16
9
  dotenv.config();
17
10
 
18
11
  const logger = loggerFactory(import.meta);
19
12
 
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 }) {
24
- // NAT-VPS modem/router device configuration:
25
- // LAN --> [NAT-VPS] --> WAN
13
+ class Dns {
14
+ static callback = async function (deployList) {
15
+ // Network topology configuration:
16
+ // LAN -> [NAT-VPS](modem/router device) -> WAN
26
17
  // enabled DMZ Host to proxy IP 80-443 (79-444) sometimes router block first port
27
18
  // disabled local red DHCP
28
19
  // verify inet ip proxy server address
@@ -30,25 +21,24 @@ const Dns = {
30
21
  // LAN server or device's local servers port -> 3000-3100 (2999-3101)
31
22
  // DNS Records: [ANAME](Address Dynamic) -> [A](ipv4) host | [AAAA](ipv6) host -> [public-ip]
32
23
  // Forward the router's TCP/UDP ports to the LAN device's IP address
24
+ for (const _deployId of deployList.split(',')) {
25
+ const deployId = _deployId.trim();
26
+ const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
27
+ const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
28
+ const confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
33
29
 
34
- const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
35
-
36
- 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
30
  let testIp;
31
+
45
32
  try {
46
33
  testIp = await ip.public.ipv4();
47
34
  } catch (error) {
48
35
  logger.error(error, { testIp, stack: error.stack });
49
36
  }
50
- if (testIp && typeof testIp === 'string' && validator.isIP(testIp) && Dns.ip !== testIp) {
51
- logger.info(`New ip`, testIp);
37
+
38
+ const currentIp = UnderpostRootEnv.API.get('ip');
39
+
40
+ if (testIp && typeof testIp === 'string' && validator.isIP(testIp) && currentIp !== testIp) {
41
+ logger.info(`new ip`, testIp);
52
42
  for (const recordType of Object.keys(confCronData.records)) {
53
43
  switch (recordType) {
54
44
  case 'A':
@@ -66,20 +56,20 @@ const Dns = {
66
56
  const ipUrlTest = `https://${process.env.DEFAULT_DEPLOY_HOST}`;
67
57
  const response = await axios.get(ipUrlTest);
68
58
  const verifyIp = response.request.socket.remoteAddress;
69
- logger.info(ipUrlTest + ' IP', verifyIp);
59
+ logger.info(ipUrlTest + ' verify ip', verifyIp);
70
60
  if (verifyIp === testIp) {
71
- await this.saveIp(confCronPath, confCronData, testIp);
72
- } else logger.error('ip not updated');
61
+ logger.info('ip updated successfully', testIp);
62
+ UnderpostRootEnv.API.set('ip', testIp);
63
+ } else logger.error('ip not updated', testIp);
73
64
  } catch (error) {
74
- logger.error(error), 'ip not updated';
65
+ logger.error(error, error.stack);
66
+ logger.error('ip not updated', testIp);
75
67
  }
76
68
  }
77
- };
78
- await callback();
79
- this.callback = callback;
80
- return callback;
81
- },
82
- services: {
69
+ }
70
+ };
71
+
72
+ static services = {
83
73
  updateIp: {
84
74
  dondominio: (options) => {
85
75
  const { user, api_key, host, dns, ip } = options;
@@ -100,21 +90,7 @@ const Dns = {
100
90
  });
101
91
  },
102
92
  },
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
- };
93
+ };
94
+ }
119
95
 
120
- export { Dns };
96
+ export default Dns;
@@ -2,16 +2,8 @@ import axios from 'axios';
2
2
  import fs from 'fs';
3
3
  import { loggerFactory } from './logger.js';
4
4
  import dotenv from 'dotenv';
5
- import https from 'https';
6
-
7
5
  dotenv.config();
8
6
 
9
- const httpsAgent = new https.Agent({
10
- rejectUnauthorized: false,
11
- });
12
-
13
- axios.defaults.httpsAgent = httpsAgent;
14
-
15
7
  const logger = loggerFactory(import.meta);
16
8
 
17
9
  const Downloader = (url, fullPath, options = { method: 'get', responseType: 'stream' }) =>
@@ -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 = [];