underpost 2.8.1 → 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 (108) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/ghpkg.yml +19 -49
  3. package/.github/workflows/npmpkg.yml +67 -0
  4. package/.github/workflows/publish.yml +5 -5
  5. package/.github/workflows/pwa-microservices-template.page.yml +12 -4
  6. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  7. package/.vscode/extensions.json +17 -71
  8. package/.vscode/settings.json +18 -3
  9. package/AUTHORS.md +16 -5
  10. package/CHANGELOG.md +103 -3
  11. package/Dockerfile +24 -66
  12. package/README.md +1 -28
  13. package/bin/build.js +186 -0
  14. package/bin/db.js +2 -24
  15. package/bin/deploy.js +169 -144
  16. package/bin/file.js +59 -16
  17. package/bin/hwt.js +0 -10
  18. package/bin/index.js +201 -60
  19. package/bin/ssl.js +19 -11
  20. package/bin/util.js +9 -104
  21. package/bin/vs.js +26 -2
  22. package/conf.js +29 -138
  23. package/docker-compose.yml +1 -1
  24. package/manifests/deployment/mongo-express/deployment.yaml +60 -0
  25. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  26. package/manifests/kind-config-dev.yaml +12 -0
  27. package/manifests/kind-config.yaml +12 -0
  28. package/manifests/letsencrypt-prod.yaml +15 -0
  29. package/manifests/mariadb/config.yaml +10 -0
  30. package/manifests/mariadb/kustomization.yaml +9 -0
  31. package/manifests/mariadb/pv.yaml +12 -0
  32. package/manifests/mariadb/pvc.yaml +10 -0
  33. package/manifests/mariadb/secret.yaml +8 -0
  34. package/manifests/mariadb/service.yaml +10 -0
  35. package/manifests/mariadb/statefulset.yaml +55 -0
  36. package/manifests/mongodb/backup-access.yaml +16 -0
  37. package/manifests/mongodb/backup-cronjob.yaml +42 -0
  38. package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
  39. package/manifests/mongodb/configmap.yaml +26 -0
  40. package/manifests/mongodb/headless-service.yaml +10 -0
  41. package/manifests/mongodb/kustomization.yaml +11 -0
  42. package/manifests/mongodb/pv-pvc.yaml +23 -0
  43. package/manifests/mongodb/statefulset.yaml +125 -0
  44. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  45. package/manifests/mongodb-4.4/pv-pvc.yaml +23 -0
  46. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  47. package/manifests/valkey/kustomization.yaml +7 -0
  48. package/manifests/valkey/service.yaml +17 -0
  49. package/manifests/valkey/statefulset.yaml +39 -0
  50. package/package.json +133 -136
  51. package/src/api/core/core.service.js +1 -1
  52. package/src/api/user/user.model.js +16 -3
  53. package/src/api/user/user.service.js +1 -1
  54. package/src/cli/cluster.js +202 -0
  55. package/src/cli/cron.js +90 -0
  56. package/src/cli/db.js +212 -0
  57. package/src/cli/deploy.js +318 -0
  58. package/src/cli/env.js +52 -0
  59. package/src/cli/fs.js +149 -0
  60. package/src/cli/image.js +148 -0
  61. package/src/cli/repository.js +125 -0
  62. package/src/cli/script.js +53 -0
  63. package/src/cli/secrets.js +37 -0
  64. package/src/cli/test.js +118 -0
  65. package/src/client/components/core/Auth.js +22 -4
  66. package/src/client/components/core/CalendarCore.js +127 -50
  67. package/src/client/components/core/CommonJs.js +282 -19
  68. package/src/client/components/core/Css.js +1 -0
  69. package/src/client/components/core/CssCore.js +8 -4
  70. package/src/client/components/core/Docs.js +1 -2
  71. package/src/client/components/core/DropDown.js +5 -1
  72. package/src/client/components/core/Input.js +22 -6
  73. package/src/client/components/core/LoadingAnimation.js +8 -1
  74. package/src/client/components/core/Modal.js +40 -12
  75. package/src/client/components/core/Panel.js +92 -31
  76. package/src/client/components/core/PanelForm.js +25 -23
  77. package/src/client/components/core/Scroll.js +1 -0
  78. package/src/client/components/core/Translate.js +47 -9
  79. package/src/client/components/core/Validator.js +9 -1
  80. package/src/client/components/core/VanillaJs.js +0 -9
  81. package/src/client/components/core/Worker.js +34 -31
  82. package/src/client/services/core/core.service.js +15 -10
  83. package/src/client/services/default/default.management.js +4 -2
  84. package/src/client/ssr/Render.js +4 -1
  85. package/src/client/ssr/body/CacheControl.js +2 -3
  86. package/src/client/sw/default.sw.js +3 -3
  87. package/src/db/mongo/MongooseDB.js +29 -1
  88. package/src/index.js +85 -19
  89. package/src/runtime/lampp/Lampp.js +1 -13
  90. package/src/runtime/xampp/Xampp.js +0 -13
  91. package/src/server/auth.js +3 -3
  92. package/src/server/backup.js +49 -93
  93. package/src/server/client-build.js +36 -46
  94. package/src/server/client-formatted.js +6 -3
  95. package/src/server/conf.js +204 -54
  96. package/src/server/dns.js +30 -55
  97. package/src/server/downloader.js +0 -8
  98. package/src/server/logger.js +15 -10
  99. package/src/server/network.js +17 -43
  100. package/src/server/process.js +25 -2
  101. package/src/server/proxy.js +4 -26
  102. package/src/server/runtime.js +30 -30
  103. package/src/server/ssl.js +1 -1
  104. package/src/server/valkey.js +2 -0
  105. package/test/api.test.js +0 -8
  106. package/src/dns.js +0 -22
  107. package/src/server/prompt-optimizer.js +0 -28
  108. package/startup.js +0 -11
@@ -1,6 +1,13 @@
1
1
  import fs from 'fs-extra';
2
2
  import dotenv from 'dotenv';
3
- import { capFirst, getCapVariableName, newInstance, range, timer } from '../client/components/core/CommonJs.js';
3
+ import {
4
+ capFirst,
5
+ getCapVariableName,
6
+ newInstance,
7
+ orderArrayFromAttrInt,
8
+ range,
9
+ timer,
10
+ } from '../client/components/core/CommonJs.js';
4
11
  import * as dir from 'path';
5
12
  import cliProgress from 'cli-progress';
6
13
  import cliSpinners from 'cli-spinners';
@@ -9,22 +16,13 @@ import colors from 'colors';
9
16
  import { loggerFactory } from './logger.js';
10
17
  import { shellExec } from './process.js';
11
18
  import { DefaultConf } from '../../conf.js';
12
- import ncp from 'copy-paste';
13
19
  import read from 'read';
14
20
  import splitFile from 'split-file';
15
21
  import axios from 'axios';
16
- import https from 'https';
17
22
  import { ssrFactory } from './client-formatted.js';
18
23
 
19
- // axios.defaults.baseURL = BASE_URL;
20
-
21
- const httpsAgent = new https.Agent({
22
- rejectUnauthorized: false,
23
- });
24
-
25
- axios.defaults.httpsAgent = httpsAgent;
26
-
27
24
  colors.enable();
25
+
28
26
  dotenv.config();
29
27
 
30
28
  const logger = loggerFactory(import.meta);
@@ -33,21 +31,26 @@ const logger = loggerFactory(import.meta);
33
31
 
34
32
  const Config = {
35
33
  default: DefaultConf,
36
- build: async function (options = { folder: '' }) {
34
+ build: async function (options = { folder: '' }, deployContext, deployList, subConf) {
35
+ if (!deployContext) deployContext = process.argv[2];
37
36
  if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`, { recursive: true });
38
37
  fs.writeFileSync(`./tmp/await-deploy`, '', 'utf8');
39
- if (fs.existsSync(`./engine-private/conf/${process.argv[2]}`)) return loadConf(process.argv[2]);
40
- 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);
41
42
 
42
- if (process.argv[2] === 'deploy') return;
43
+ if (deployContext === 'deploy') return;
43
44
 
44
- if (process.argv[2] === 'proxy') {
45
+ if (deployContext === 'proxy') {
46
+ if (!deployList) deployList = process.argv[3];
47
+ if (!subConf) subConf = process.argv[4];
45
48
  this.default.server = {};
46
- for (const deployId of process.argv[3].split(',')) {
49
+ for (const deployId of deployList.split(',')) {
47
50
  let confPath = `./engine-private/conf/${deployId}/conf.server.json`;
48
51
  const privateConfDevPath = fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
49
52
  ? `./engine-private/replica/${deployId}/conf.server.json`
50
- : `./engine-private/conf/${deployId}/conf.server.dev.${process.argv[4]}.json`;
53
+ : `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
51
54
  const confDevPath = fs.existsSync(privateConfDevPath)
52
55
  ? privateConfDevPath
53
56
  : `./engine-private/conf/${deployId}/conf.server.dev.json`;
@@ -55,7 +58,7 @@ const Config = {
55
58
  if (process.env.NODE_ENV === 'development' && fs.existsSync(confDevPath)) confPath = confDevPath;
56
59
  const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
57
60
 
58
- for (const host of Object.keys(loadReplicas(serverConf))) {
61
+ for (const host of Object.keys(loadReplicas(serverConf, deployContext, subConf))) {
59
62
  if (serverConf[host]['/'])
60
63
  this.default.server[host] = {
61
64
  ...this.default.server[host],
@@ -85,7 +88,15 @@ const Config = {
85
88
  },
86
89
  };
87
90
 
88
- const loadConf = (deployId) => {
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
+ }
89
100
  const folder = fs.existsSync(`./engine-private/replica/${deployId}`)
90
101
  ? `./engine-private/replica/${deployId}`
91
102
  : `./engine-private/conf/${deployId}`;
@@ -102,7 +113,8 @@ const loadConf = (deployId) => {
102
113
  ? fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8')
103
114
  : JSON.stringify(Config.default[typeConf]);
104
115
  if (process.env.NODE_ENV === 'development' && typeConf === 'server') {
105
- 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`;
106
118
  if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
107
119
  }
108
120
  if (typeConf === 'server') srcConf = JSON.stringify(loadReplicas(JSON.parse(srcConf)), null, 4);
@@ -111,27 +123,34 @@ const loadConf = (deployId) => {
111
123
  fs.writeFileSync(`./.env.production`, fs.readFileSync(`${folder}/.env.production`, 'utf8'), 'utf8');
112
124
  fs.writeFileSync(`./.env.development`, fs.readFileSync(`${folder}/.env.development`, 'utf8'), 'utf8');
113
125
  fs.writeFileSync(`./.env.test`, fs.readFileSync(`${folder}/.env.test`, 'utf8'), 'utf8');
114
- if (process.env.NODE_ENV) {
115
- fs.writeFileSync(`./.env`, fs.readFileSync(`${folder}/.env.${process.env.NODE_ENV}`, 'utf8'), 'utf8');
116
- const env = dotenv.parse(fs.readFileSync(`${folder}/.env.${process.env.NODE_ENV}`, 'utf8'));
126
+ const NODE_ENV = envInput || process.env.NODE_ENV;
127
+ if (NODE_ENV) {
128
+ fs.writeFileSync(`./.env`, fs.readFileSync(`${folder}/.env.${NODE_ENV}`, 'utf8'), 'utf8');
129
+ const env = dotenv.parse(fs.readFileSync(`${folder}/.env.${NODE_ENV}`, 'utf8'));
117
130
  process.env = {
118
131
  ...process.env,
119
132
  ...env,
120
133
  };
121
134
  }
122
- 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');
123
140
  return { folder, deployId };
124
141
  };
125
142
 
126
- const loadReplicas = (confServer) => {
143
+ const loadReplicas = (confServer, deployContext, subConf) => {
144
+ if (!deployContext) deployContext = process.argv[2];
145
+ if (!subConf) subConf = process.argv[3];
127
146
  for (const host of Object.keys(confServer)) {
128
147
  for (const path of Object.keys(confServer[host])) {
129
148
  const { replicas, singleReplica } = confServer[host][path];
130
149
  if (
131
150
  replicas &&
132
- (process.argv[2] === 'proxy' ||
151
+ (deployContext === 'proxy' ||
133
152
  !singleReplica ||
134
- (singleReplica && process.env.NODE_ENV === 'development' && !process.argv[3]))
153
+ (singleReplica && process.env.NODE_ENV === 'development' && !subConf))
135
154
  )
136
155
  for (const replicaPath of replicas) {
137
156
  confServer[host][replicaPath] = newInstance(confServer[host][path]);
@@ -480,6 +499,48 @@ const buildProxyRouter = () => {
480
499
  return proxyRouter;
481
500
  };
482
501
 
502
+ const buildKindPorts = (from, to) =>
503
+ range(parseInt(from), parseInt(to))
504
+ .map(
505
+ (port) => ` - name: 'tcp-${port}'
506
+ protocol: TCP
507
+ port: ${port}
508
+ targetPort: ${port}
509
+ - name: 'udp-${port}'
510
+ protocol: UDP
511
+ port: ${port}
512
+ targetPort: ${port}
513
+ `,
514
+ )
515
+ .join('\n');
516
+
517
+ const buildPortProxyRouter = (port, proxyRouter) => {
518
+ const hosts = proxyRouter[port];
519
+ const router = {};
520
+ // build router
521
+ Object.keys(hosts).map((hostKey) => {
522
+ let { host, path, target, proxy, peer } = hosts[hostKey];
523
+ if (process.argv.includes('localhost') && process.env.NODE_ENV === 'development') host = `localhost`;
524
+
525
+ if (!proxy.includes(port)) return;
526
+ const absoluteHost = [80, 443].includes(port)
527
+ ? `${host}${path === '/' ? '' : path}`
528
+ : `${host}:${port}${path === '/' ? '' : path}`;
529
+
530
+ if (process.argv.includes('localhost')) {
531
+ if (!(absoluteHost in router)) router[absoluteHost] = target;
532
+ } else router[absoluteHost] = target;
533
+ }); // order router
534
+
535
+ if (Object.keys(router).length === 0) return router;
536
+
537
+ const reOrderRouter = {};
538
+ for (const absoluteHostKey of orderArrayFromAttrInt(Object.keys(router), 'length'))
539
+ reOrderRouter[absoluteHostKey] = router[absoluteHostKey];
540
+
541
+ return reOrderRouter;
542
+ };
543
+
483
544
  const cliBar = async (time = 5000) => {
484
545
  // create new progress bar
485
546
  const b = new cliProgress.SingleBar({
@@ -528,9 +589,25 @@ const cliSpinner = async (time = 5000, message0, message1, color, type = 'dots')
528
589
  const buildReplicaId = ({ deployId, replica }) => `${deployId}-${replica.slice(1)}`;
529
590
 
530
591
  const getDataDeploy = (
531
- options = { buildSingleReplica: false, deployGroupId: '', deployId: '', disableSyncEnvPort: false },
592
+ options = {
593
+ buildSingleReplica: false,
594
+ deployGroupId: '',
595
+ deployId: '',
596
+ disableSyncEnvPort: false,
597
+ deployIdConcat: [],
598
+ },
532
599
  ) => {
533
- 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);
534
611
 
535
612
  if (options.deployId) dataDeploy = dataDeploy.filter((d) => d === options.deployId);
536
613
 
@@ -588,6 +665,7 @@ const validateTemplatePath = (absolutePath = '') => {
588
665
  if (absolutePath.match('src/api') && !confServer.apis.find((p) => absolutePath.match(`src/api/${p}/`))) {
589
666
  return false;
590
667
  }
668
+ if (absolutePath.match('conf.dd-') && absolutePath.match('.js')) return false;
591
669
  if (
592
670
  absolutePath.match('src/client/services/') &&
593
671
  !clients.find((p) => absolutePath.match(`src/client/services/${p}/`))
@@ -764,15 +842,16 @@ const deployRun = async (dataDeploy, currentAttempt = 1) => {
764
842
  if (failed.length > 0) {
765
843
  for (const deploy of failed) logger.error(deploy.deployId, Cmd.run(deploy.deployId));
766
844
  if (currentAttempt === maxAttempts) return logger.error(`max deploy attempts exceeded`);
767
- 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' });
768
846
  currentAttempt++;
769
847
  await deployRun(failed, currentAttempt);
770
848
  } else logger.info(`Deploy process successfully`);
771
849
  };
772
850
 
773
- const restoreMacroDb = async (deployGroupId = '') => {
851
+ const restoreMacroDb = async (deployGroupId = '', deployId = null) => {
774
852
  const dataDeploy = await getDataDeploy({ deployGroupId, buildSingleReplica: false });
775
853
  for (const deployGroup of dataDeploy) {
854
+ if (deployId && deployGroup.deployId !== deployId) continue;
776
855
  if (!deployGroup.replicaHost) {
777
856
  const deployServerConfPath = `./engine-private/conf/${deployGroup.deployId}/conf.server.json`;
778
857
  const serverConf = JSON.parse(fs.readFileSync(deployServerConfPath, 'utf8'));
@@ -790,13 +869,10 @@ const restoreMacroDb = async (deployGroupId = '') => {
790
869
  }
791
870
  };
792
871
 
793
- const mergeBackUp = async (baseBackJsonPath, outputFilePath) => {
794
- const names = JSON.parse(fs.readFileSync(baseBackJsonPath, 'utf8')).map((p) =>
795
- p.replaceAll(`\\`, '/').replaceAll('C:/', '/').replaceAll('c:/', '/'),
796
- );
872
+ const mergeFile = async (parts = [], outputFilePath) => {
797
873
  await new Promise((resolve) => {
798
874
  splitFile
799
- .mergeFiles(names, outputFilePath)
875
+ .mergeFiles(parts, outputFilePath)
800
876
  .then(() => {
801
877
  resolve();
802
878
  })
@@ -848,11 +924,13 @@ const getRestoreCronCmd = async (options = { host: '', path: '', conf: {}, deplo
848
924
  {
849
925
  if (process.argv.includes('cron')) {
850
926
  cmd = `mysql -u ${user} -p${password} ${name} < ${baseBackUpPath}/${currentBackupTimestamp}/${name}.sql`;
851
- if (fs.existsSync(`${baseBackUpPath}/${currentBackupTimestamp}/${name}-parths.json`))
852
- await mergeBackUp(
853
- `${baseBackUpPath}/${currentBackupTimestamp}/${name}-parths.json`,
854
- `${baseBackUpPath}/${currentBackupTimestamp}/${name}.sql`,
855
- );
927
+ if (fs.existsSync(`${baseBackUpPath}/${currentBackupTimestamp}/${name}-parths.json`)) {
928
+ const names = JSON.parse(
929
+ fs.readFileSync(`${baseBackUpPath}/${currentBackupTimestamp}/${name}-parths.json`, 'utf8'),
930
+ ).map((p) => p.replaceAll(`\\`, '/').replaceAll('C:/', '/').replaceAll('c:/', '/'));
931
+
932
+ await mergeFile(names, `${baseBackUpPath}/${currentBackupTimestamp}/${name}.sql`);
933
+ }
856
934
  } else {
857
935
  cmd = `mysql -u ${user} -p${password} ${name} < ${
858
936
  backupPath ? backupPath : `./engine-private/sql-backups/${name}.sql`
@@ -863,15 +941,23 @@ const getRestoreCronCmd = async (options = { host: '', path: '', conf: {}, deplo
863
941
  backupPath ? backupPath.split('/').slice(0, -1).join('/') : `./engine-private/sql-backups`
864
942
  }/${name}-parths.json`,
865
943
  )
866
- )
867
- await mergeBackUp(
868
- `${
869
- backupPath ? backupPath.split('/').slice(0, -1).join('/') : `./engine-private/sql-backups`
870
- }/${name}-parths.json`,
944
+ ) {
945
+ const names = JSON.parse(
946
+ fs.readFileSync(
947
+ `${
948
+ backupPath ? backupPath.split('/').slice(0, -1).join('/') : `./engine-private/sql-backups`
949
+ }/${name}-parths.json`,
950
+ 'utf8',
951
+ ),
952
+ ).map((p) => p.replaceAll(`\\`, '/').replaceAll('C:/', '/').replaceAll('c:/', '/'));
953
+
954
+ await mergeFile(
955
+ names,
871
956
  `${
872
957
  backupPath ? backupPath.split('/').slice(0, -1).join('/') : `./engine-private/sql-backups`
873
958
  }/${name}.sql`,
874
959
  );
960
+ }
875
961
  }
876
962
  }
877
963
  break;
@@ -890,20 +976,31 @@ const getRestoreCronCmd = async (options = { host: '', path: '', conf: {}, deplo
890
976
  return cmd;
891
977
  };
892
978
 
979
+ const getPathsSSR = (conf) => {
980
+ const paths = ['src/client/ssr/Render.js'];
981
+ for (const o of conf.head) paths.push(`src/client/ssr/head/${o}.js`);
982
+ for (const o of conf.body) paths.push(`src/client/ssr/body/${o}.js`);
983
+ for (const o of Object.keys(conf.mailer)) paths.push(`src/client/ssr/mailer/${conf.mailer[o]}.js`);
984
+ for (const o of conf.offline) paths.push(`src/client/ssr/mailer/${o.client}.js`);
985
+ for (const o of conf.pages) paths.push(`src/client/ssr/pages/${o.client}.js`);
986
+ return paths;
987
+ };
988
+
893
989
  const Cmd = {
894
990
  delete: (deployId) => `pm2 delete ${deployId}`,
895
- run: (deployId) => `node bin/deploy run ${deployId}`,
991
+ run: () => `npm start`,
896
992
  build: (deployId) => `node bin/deploy build-full-client ${deployId}${process.argv.includes('l') ? ' l' : ''}`,
897
993
  conf: (deployId, env) => `node bin/deploy conf ${deployId} ${env ? env : 'production'}`,
898
994
  replica: (deployId, host, path) => `node bin/deploy build-single-replica ${deployId} ${host} ${path}`,
899
995
  syncPorts: (deployGroupId) => `node bin/deploy sync-env-port ${deployGroupId}`,
900
- cron: (deployId, job, expression) => {
901
- shellExec(Cmd.delete(`${deployId}-${job}`));
902
- return `env-cmd -f .env.production pm2 start bin/cron.js --no-autorestart --instances 1 --cron "${expression}" --name ${deployId}-${job} -- ${job} ${deployId}`;
903
- },
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}`,
904
1000
  };
905
1001
 
906
1002
  const fixDependencies = async () => {
1003
+ return;
907
1004
  // sed -i "$line_number s,.*,$new_text," "$file"
908
1005
  // sed -i "$line_number c \\$new_text" "$file"
909
1006
  const dep = fs.readFileSync(`./node_modules/peer/dist/module.mjs`, 'utf8');
@@ -933,14 +1030,60 @@ const maintenanceMiddleware = (req, res, port, proxyRouter) => {
933
1030
  }
934
1031
  };
935
1032
 
1033
+ const splitFileFactory = async (name, _path) => {
1034
+ const stats = fs.statSync(_path);
1035
+ const maxSizeInBytes = 1024 * 1024 * 50; // 50 mb
1036
+ const fileSizeInBytes = stats.size;
1037
+ if (fileSizeInBytes > maxSizeInBytes) {
1038
+ logger.info('splitFileFactory input', { name, from: _path });
1039
+ return await new Promise((resolve) => {
1040
+ splitFile
1041
+ .splitFileBySize(_path, maxSizeInBytes) // 50 mb
1042
+ .then((names) => {
1043
+ logger.info('splitFileFactory output', { parts: names });
1044
+ fs.writeFileSync(
1045
+ `${_path.split('/').slice(0, -1).join('/')}/${name}-parths.json`,
1046
+ JSON.stringify(names, null, 4),
1047
+ 'utf8',
1048
+ );
1049
+ fs.removeSync(_path);
1050
+ return resolve(true);
1051
+ })
1052
+ .catch((err) => {
1053
+ console.log('Error: ', err);
1054
+ return resolve(false);
1055
+ });
1056
+ });
1057
+ }
1058
+ return false;
1059
+ };
1060
+
936
1061
  const setUpProxyMaintenanceServer = ({ deployGroupId }) => {
937
1062
  shellExec(`pm2 kill`);
938
1063
  shellExec(`node bin/deploy valkey-service`);
939
1064
  const proxyDeployId = fs.readFileSync(`./engine-private/deploy/${deployGroupId}.proxy`, 'utf8').trim();
940
1065
  shellExec(`node bin/deploy conf ${proxyDeployId} production`);
941
- shellExec(`node bin/deploy run ${proxyDeployId} maintenance`);
1066
+ shellExec(`npm start ${proxyDeployId} maintenance`);
942
1067
  };
943
1068
 
1069
+ const getNpmRootPath = () =>
1070
+ shellExec(`npm root -g`, {
1071
+ stdout: true,
1072
+ disableLog: true,
1073
+ silent: true,
1074
+ }).trim();
1075
+
1076
+ const getUnderpostRootPath = () => `${getNpmRootPath()}/underpost`;
1077
+
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
+ );
1086
+
944
1087
  export {
945
1088
  Cmd,
946
1089
  Config,
@@ -967,9 +1110,16 @@ export {
967
1110
  deployRun,
968
1111
  getCronBackUpFolder,
969
1112
  getRestoreCronCmd,
970
- mergeBackUp,
1113
+ mergeFile,
971
1114
  fixDependencies,
972
1115
  getDeployId,
973
1116
  maintenanceMiddleware,
974
1117
  setUpProxyMaintenanceServer,
1118
+ getPathsSSR,
1119
+ buildKindPorts,
1120
+ buildPortProxyRouter,
1121
+ splitFileFactory,
1122
+ getNpmRootPath,
1123
+ getUnderpostRootPath,
1124
+ writeEnv,
975
1125
  };
package/src/server/dns.js CHANGED
@@ -1,29 +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 { isIPv4 } from 'is-ip';
9
- import { shellExec } from './process.js';
10
-
11
- const httpsAgent = new https.Agent({
12
- rejectUnauthorized: false,
13
- });
14
-
15
- axios.defaults.httpsAgent = httpsAgent;
7
+ import UnderpostRootEnv from '../cli/env.js';
16
8
 
17
9
  dotenv.config();
18
10
 
19
11
  const logger = loggerFactory(import.meta);
20
12
 
21
- const Dns = {
22
- repoUrl: `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USERNAME}/${process.env.GITHUB_DNS_REPO}.git`,
23
- callback: () => null,
24
- InitIpDaemon: async function ({ deployId }) {
25
- // NAT-VPS modem/router device configuration:
26
- // 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
27
17
  // enabled DMZ Host to proxy IP 80-443 (79-444) sometimes router block first port
28
18
  // disabled local red DHCP
29
19
  // verify inet ip proxy server address
@@ -31,25 +21,24 @@ const Dns = {
31
21
  // LAN server or device's local servers port -> 3000-3100 (2999-3101)
32
22
  // DNS Records: [ANAME](Address Dynamic) -> [A](ipv4) host | [AAAA](ipv6) host -> [public-ip]
33
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'));
34
29
 
35
- const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
36
-
37
- const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
38
- let confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
39
- if (confCronData.ipDaemon.disabled) return;
40
- Dns.ip = confCronData.ipDaemon.ip;
41
- logger.info(`Current ip`, Dns.ip);
42
- const callback = async () => {
43
- logger.info('init dns ip callback');
44
- await logger.setUpInfo();
45
30
  let testIp;
31
+
46
32
  try {
47
33
  testIp = await ip.public.ipv4();
48
34
  } catch (error) {
49
35
  logger.error(error, { testIp, stack: error.stack });
50
36
  }
51
- if (testIp && typeof testIp === 'string' && isIPv4(testIp) && Dns.ip !== testIp) {
52
- 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);
53
42
  for (const recordType of Object.keys(confCronData.records)) {
54
43
  switch (recordType) {
55
44
  case 'A':
@@ -67,20 +56,20 @@ const Dns = {
67
56
  const ipUrlTest = `https://${process.env.DEFAULT_DEPLOY_HOST}`;
68
57
  const response = await axios.get(ipUrlTest);
69
58
  const verifyIp = response.request.socket.remoteAddress;
70
- logger.info(ipUrlTest + ' IP', verifyIp);
59
+ logger.info(ipUrlTest + ' verify ip', verifyIp);
71
60
  if (verifyIp === testIp) {
72
- await this.saveIp(confCronPath, confCronData, testIp);
73
- } 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);
74
64
  } catch (error) {
75
- logger.error(error), 'ip not updated';
65
+ logger.error(error, error.stack);
66
+ logger.error('ip not updated', testIp);
76
67
  }
77
68
  }
78
- };
79
- await callback();
80
- this.callback = callback;
81
- return callback;
82
- },
83
- services: {
69
+ }
70
+ };
71
+
72
+ static services = {
84
73
  updateIp: {
85
74
  dondominio: (options) => {
86
75
  const { user, api_key, host, dns, ip } = options;
@@ -101,21 +90,7 @@ const Dns = {
101
90
  });
102
91
  },
103
92
  },
104
- },
105
- saveIp: async (confCronPath, confCronData, ip) => {
106
- Dns.ip = ip;
107
- confCronData.ipDaemon.ip = ip;
108
- fs.writeFileSync(confCronPath, JSON.stringify(confCronData, null, 4), 'utf8');
109
- shellExec(
110
- `cd ./engine-private` +
111
- ` && git pull ${Dns.repoUrl}` +
112
- ` && git add . && git commit -m "update ip ${new Date().toLocaleDateString()}"` +
113
- ` && git push ${Dns.repoUrl}`,
114
- {
115
- disableLog: true,
116
- },
117
- );
118
- },
119
- };
93
+ };
94
+ }
120
95
 
121
- 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' }) =>
@@ -12,7 +12,6 @@ import morgan from 'morgan';
12
12
  import colorize from 'json-colorizer';
13
13
  import colors from 'colors';
14
14
  import v8 from 'v8';
15
- import isAdmin from 'is-admin';
16
15
  import { clearTerminalStringColor, formatBytes } from '../client/components/core/CommonJs.js';
17
16
 
18
17
  colors.enable();
@@ -79,18 +78,16 @@ const format = (meta) =>
79
78
  *
80
79
  * This function is used to log details about
81
80
  * the execution context, such as command-line arguments,
82
- * environment variables, the process's administrative privileges,
83
- * and the maximum available heap space size.
81
+ * environment variables, and the maximum available heap space size.
84
82
  *
85
83
  * @param {winston.Logger} logger - A pre-configured Winston logger object.
86
84
  * @memberof Logger
87
85
  */
88
86
  const setUpInfo = async (logger = new winston.Logger()) => {
89
- logger.info('npm_package_version', process.env.npm_package_version);
90
87
  logger.info('argv', process.argv);
88
+ logger.info('cwd', process.cwd());
91
89
  logger.info('platform', process.platform);
92
90
  logger.info('env', process.env.NODE_ENV);
93
- logger.info('admin', await isAdmin());
94
91
  logger.info('--max-old-space-size', {
95
92
  total_available_size: formatBytes(v8.getHeapStatistics().total_available_size),
96
93
  });
@@ -115,10 +112,10 @@ const loggerFactory = (meta = { url: '' }) => {
115
112
  // Allow the use the terminal to print the messages
116
113
  new winston.transports.Console(),
117
114
  // Allow to print all the error level messages inside the error.log file
118
- new winston.transports.File({
119
- filename: `logs/${meta}/error.log`,
120
- level: 'error',
121
- }),
115
+ // new winston.transports.File({
116
+ // filename: `logs/${meta}/error.log`,
117
+ // level: 'error',
118
+ // }),
122
119
  // Allow to print all the error message inside the all.log file
123
120
  // (also the error log that are also printed inside the error.log(
124
121
  new winston.transports.File({ filename: `logs/${meta}/all.log` }),
@@ -189,4 +186,12 @@ const underpostASCI = () => `
189
186
  ░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚═╝░░░░░░╚════╝░╚═════╝░░░░╚═╝░░░
190
187
  `;
191
188
 
192
- export { loggerFactory, loggerMiddleware, setUpInfo, underpostASCI };
189
+ const actionInitLog = () =>
190
+ console.log(
191
+ underpostASCI() +
192
+ `
193
+ https://www.nexodev.org/docs
194
+ `,
195
+ );
196
+
197
+ export { loggerFactory, loggerMiddleware, setUpInfo, underpostASCI, actionInitLog };