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.
- package/.dockerignore +1 -0
- package/.github/workflows/ghpkg.yml +19 -49
- package/.github/workflows/npmpkg.yml +67 -0
- package/.github/workflows/publish.yml +5 -5
- package/.github/workflows/pwa-microservices-template.page.yml +12 -4
- package/.github/workflows/pwa-microservices-template.test.yml +2 -2
- package/.vscode/extensions.json +17 -71
- package/.vscode/settings.json +18 -3
- package/AUTHORS.md +16 -5
- package/CHANGELOG.md +103 -3
- package/Dockerfile +24 -66
- package/README.md +1 -28
- package/bin/build.js +186 -0
- package/bin/db.js +2 -24
- package/bin/deploy.js +169 -144
- package/bin/file.js +59 -16
- package/bin/hwt.js +0 -10
- package/bin/index.js +201 -60
- package/bin/ssl.js +19 -11
- package/bin/util.js +9 -104
- package/bin/vs.js +26 -2
- package/conf.js +29 -138
- package/docker-compose.yml +1 -1
- package/manifests/deployment/mongo-express/deployment.yaml +60 -0
- package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
- package/manifests/kind-config-dev.yaml +12 -0
- package/manifests/kind-config.yaml +12 -0
- package/manifests/letsencrypt-prod.yaml +15 -0
- package/manifests/mariadb/config.yaml +10 -0
- package/manifests/mariadb/kustomization.yaml +9 -0
- package/manifests/mariadb/pv.yaml +12 -0
- package/manifests/mariadb/pvc.yaml +10 -0
- package/manifests/mariadb/secret.yaml +8 -0
- package/manifests/mariadb/service.yaml +10 -0
- package/manifests/mariadb/statefulset.yaml +55 -0
- package/manifests/mongodb/backup-access.yaml +16 -0
- package/manifests/mongodb/backup-cronjob.yaml +42 -0
- package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
- package/manifests/mongodb/configmap.yaml +26 -0
- package/manifests/mongodb/headless-service.yaml +10 -0
- package/manifests/mongodb/kustomization.yaml +11 -0
- package/manifests/mongodb/pv-pvc.yaml +23 -0
- package/manifests/mongodb/statefulset.yaml +125 -0
- package/manifests/mongodb-4.4/kustomization.yaml +7 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +23 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
- package/manifests/valkey/kustomization.yaml +7 -0
- package/manifests/valkey/service.yaml +17 -0
- package/manifests/valkey/statefulset.yaml +39 -0
- package/package.json +133 -136
- package/src/api/core/core.service.js +1 -1
- package/src/api/user/user.model.js +16 -3
- package/src/api/user/user.service.js +1 -1
- package/src/cli/cluster.js +202 -0
- package/src/cli/cron.js +90 -0
- package/src/cli/db.js +212 -0
- package/src/cli/deploy.js +318 -0
- package/src/cli/env.js +52 -0
- package/src/cli/fs.js +149 -0
- package/src/cli/image.js +148 -0
- package/src/cli/repository.js +125 -0
- package/src/cli/script.js +53 -0
- package/src/cli/secrets.js +37 -0
- package/src/cli/test.js +118 -0
- package/src/client/components/core/Auth.js +22 -4
- package/src/client/components/core/CalendarCore.js +127 -50
- package/src/client/components/core/CommonJs.js +282 -19
- package/src/client/components/core/Css.js +1 -0
- package/src/client/components/core/CssCore.js +8 -4
- package/src/client/components/core/Docs.js +1 -2
- package/src/client/components/core/DropDown.js +5 -1
- package/src/client/components/core/Input.js +22 -6
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +40 -12
- package/src/client/components/core/Panel.js +92 -31
- package/src/client/components/core/PanelForm.js +25 -23
- package/src/client/components/core/Scroll.js +1 -0
- package/src/client/components/core/Translate.js +47 -9
- package/src/client/components/core/Validator.js +9 -1
- package/src/client/components/core/VanillaJs.js +0 -9
- package/src/client/components/core/Worker.js +34 -31
- package/src/client/services/core/core.service.js +15 -10
- package/src/client/services/default/default.management.js +4 -2
- package/src/client/ssr/Render.js +4 -1
- package/src/client/ssr/body/CacheControl.js +2 -3
- package/src/client/sw/default.sw.js +3 -3
- package/src/db/mongo/MongooseDB.js +29 -1
- package/src/index.js +85 -19
- package/src/runtime/lampp/Lampp.js +1 -13
- package/src/runtime/xampp/Xampp.js +0 -13
- package/src/server/auth.js +3 -3
- package/src/server/backup.js +49 -93
- package/src/server/client-build.js +36 -46
- package/src/server/client-formatted.js +6 -3
- package/src/server/conf.js +204 -54
- package/src/server/dns.js +30 -55
- package/src/server/downloader.js +0 -8
- package/src/server/logger.js +15 -10
- package/src/server/network.js +17 -43
- package/src/server/process.js +25 -2
- package/src/server/proxy.js +4 -26
- package/src/server/runtime.js +30 -30
- package/src/server/ssl.js +1 -1
- package/src/server/valkey.js +2 -0
- package/test/api.test.js +0 -8
- package/src/dns.js +0 -22
- package/src/server/prompt-optimizer.js +0 -28
- package/startup.js +0 -11
package/src/server/conf.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
|
-
import {
|
|
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/${
|
|
40
|
-
|
|
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 (
|
|
43
|
+
if (deployContext === 'deploy') return;
|
|
43
44
|
|
|
44
|
-
if (
|
|
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
|
|
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.${
|
|
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
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
151
|
+
(deployContext === 'proxy' ||
|
|
133
152
|
!singleReplica ||
|
|
134
|
-
(singleReplica && process.env.NODE_ENV === 'development' && !
|
|
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 = {
|
|
592
|
+
options = {
|
|
593
|
+
buildSingleReplica: false,
|
|
594
|
+
deployGroupId: '',
|
|
595
|
+
deployId: '',
|
|
596
|
+
disableSyncEnvPort: false,
|
|
597
|
+
deployIdConcat: [],
|
|
598
|
+
},
|
|
532
599
|
) => {
|
|
533
|
-
let dataDeploy =
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
853
|
-
`${baseBackUpPath}/${currentBackupTimestamp}/${name}-parths.json`,
|
|
854
|
-
|
|
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
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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: (
|
|
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: (
|
|
901
|
-
|
|
902
|
-
|
|
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(`
|
|
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
|
-
|
|
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
|
|
5
|
-
|
|
4
|
+
import validator from 'validator';
|
|
6
5
|
import { ip } from './network.js';
|
|
7
6
|
import { loggerFactory } from './logger.js';
|
|
8
|
-
import
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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 + '
|
|
59
|
+
logger.info(ipUrlTest + ' verify ip', verifyIp);
|
|
71
60
|
if (verifyIp === testIp) {
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
65
|
+
logger.error(error, error.stack);
|
|
66
|
+
logger.error('ip not updated', testIp);
|
|
76
67
|
}
|
|
77
68
|
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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
|
|
96
|
+
export default Dns;
|
package/src/server/downloader.js
CHANGED
|
@@ -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' }) =>
|
package/src/server/logger.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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 };
|