underpost 2.8.0 → 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 +20 -4
- 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 +168 -157
- package/bin/file.js +59 -16
- package/bin/hwt.js +0 -10
- package/bin/index.js +201 -61
- package/bin/ssl.js +19 -11
- package/bin/util.js +24 -101
- package/bin/vs.js +26 -2
- package/conf.js +30 -132
- 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 -134
- 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/Account.js +4 -2
- package/src/client/components/core/Auth.js +24 -6
- 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 +2 -1
- package/src/client/components/core/CssCore.js +8 -4
- package/src/client/components/core/Docs.js +1 -1
- package/src/client/components/core/DropDown.js +5 -1
- package/src/client/components/core/Input.js +22 -6
- package/src/client/components/core/JoyStick.js +8 -5
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +47 -18
- package/src/client/components/core/Panel.js +93 -31
- package/src/client/components/core/PanelForm.js +27 -19
- package/src/client/components/core/Scroll.js +1 -0
- package/src/client/components/core/SignUp.js +4 -1
- package/src/client/components/core/Translate.js +61 -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/public/default/plantuml/client-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-schema.svg +1 -1
- package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
- package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
- package/src/client/services/core/core.service.js +15 -8
- 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 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +3 -3
- package/src/client/ssr/offline/Maintenance.js +63 -0
- package/src/client/sw/default.sw.js +26 -6
- package/src/db/mongo/MongooseDB.js +29 -1
- package/src/index.js +91 -17
- 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 +41 -50
- package/src/server/client-formatted.js +6 -3
- package/src/server/client-icons.js +1 -1
- package/src/server/conf.js +207 -57
- package/src/server/dns.js +30 -55
- package/src/server/downloader.js +0 -8
- package/src/server/logger.js +22 -15
- 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 +3 -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
|
@@ -21,6 +21,7 @@ import swaggerAutoGen from 'swagger-autogen';
|
|
|
21
21
|
import { SitemapStream, streamToPromise } from 'sitemap';
|
|
22
22
|
import { Readable } from 'stream';
|
|
23
23
|
import { buildIcons, buildTextImg, getBufferPngText } from './client-icons.js';
|
|
24
|
+
import Underpost from '../index.js';
|
|
24
25
|
|
|
25
26
|
dotenv.config();
|
|
26
27
|
|
|
@@ -50,10 +51,10 @@ const fullBuild = async ({
|
|
|
50
51
|
buildAcmeChallengePath(acmeChallengeFullPath);
|
|
51
52
|
|
|
52
53
|
if (publicClientId && publicClientId.startsWith('html-website-templates')) {
|
|
53
|
-
if (!fs.existsSync(`/dd/html-website-templates/`))
|
|
54
|
-
shellExec(`cd /dd && git clone https://github.com/designmodo/html-website-templates.git`);
|
|
54
|
+
if (!fs.existsSync(`/home/dd/html-website-templates/`))
|
|
55
|
+
shellExec(`cd /home/dd && git clone https://github.com/designmodo/html-website-templates.git`);
|
|
55
56
|
if (!fs.existsSync(`${rootClientPath}/index.php`)) {
|
|
56
|
-
fs.copySync(`/dd/html-website-templates/${publicClientId.split('-publicClientId-')[1]}`, rootClientPath);
|
|
57
|
+
fs.copySync(`/home/dd/html-website-templates/${publicClientId.split('-publicClientId-')[1]}`, rootClientPath);
|
|
57
58
|
shellExec(`cd ${rootClientPath} && git init && git add . && git commit -m "Base template implementation"`);
|
|
58
59
|
// git remote add origin git@github.com:<username>/<repo>.git
|
|
59
60
|
fs.writeFileSync(`${rootClientPath}/.git/.htaccess`, `Deny from all`, 'utf8');
|
|
@@ -191,8 +192,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
191
192
|
|
|
192
193
|
if (redirect || disabledRebuild) continue;
|
|
193
194
|
|
|
194
|
-
if (fullBuildEnabled)
|
|
195
|
-
// !(confServer[host]['/'] && confServer[host]['/'].liteBuild)
|
|
195
|
+
if (fullBuildEnabled)
|
|
196
196
|
await fullBuild({
|
|
197
197
|
path,
|
|
198
198
|
logger,
|
|
@@ -205,14 +205,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
205
205
|
iconsBuild,
|
|
206
206
|
metadata,
|
|
207
207
|
});
|
|
208
|
-
if (apis && false)
|
|
209
|
-
for (const apiBuildScript of apis) {
|
|
210
|
-
const scriptPath = `src/api/${apiBuildScript}/${apiBuildScript}.build.js`;
|
|
211
|
-
if (fs.existsSync(`./${scriptPath}`)) {
|
|
212
|
-
shellExec(`node ${scriptPath}`);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
208
|
|
|
217
209
|
if (components)
|
|
218
210
|
for (const module of Object.keys(components)) {
|
|
@@ -259,20 +251,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
259
251
|
'services',
|
|
260
252
|
baseHost,
|
|
261
253
|
);
|
|
262
|
-
if (module === 'core' && (process.env.NODE_ENV === 'production' || process.argv.includes('static'))) {
|
|
263
|
-
if (apiBaseHost)
|
|
264
|
-
jsSrc = jsSrc.replace(
|
|
265
|
-
'const getBaseHost = () => location.host;',
|
|
266
|
-
`const getBaseHost = () => '${apiBaseHost}';`,
|
|
267
|
-
);
|
|
268
|
-
if (apiBaseProxyPath) {
|
|
269
|
-
jsSrc = jsSrc.replace('${getProxyPath()}api/', `${apiBaseProxyPath}${process.env.BASE_API}/`);
|
|
270
|
-
jsSrc = jsSrc.replace(
|
|
271
|
-
"const getWsBasePath = () => (getProxyPath() !== '/' ? `${getProxyPath()}socket.io/` : undefined);",
|
|
272
|
-
`const getWsBasePath = () => '${apiBaseProxyPath}socket.io/';`,
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
254
|
fs.writeFileSync(
|
|
277
255
|
jsPublicPath,
|
|
278
256
|
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
@@ -465,10 +443,11 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
465
443
|
case 'DefaultSplashScreen':
|
|
466
444
|
if (backgroundImage) {
|
|
467
445
|
ssrHeadComponents += SrrComponent({
|
|
468
|
-
|
|
469
|
-
.readFileSync(backgroundImage)
|
|
470
|
-
.toString('base64')}`,
|
|
446
|
+
backgroundImage: (path === '/' ? path : `${path}/`) + backgroundImage,
|
|
471
447
|
});
|
|
448
|
+
// `data:image/${backgroundImage.split('.').pop()};base64,${fs
|
|
449
|
+
// .readFileSync()
|
|
450
|
+
// .toString('base64')}`,
|
|
472
451
|
break;
|
|
473
452
|
} else {
|
|
474
453
|
ssrHeadComponents += SrrComponent({ metadata });
|
|
@@ -480,7 +459,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
480
459
|
bgColor: metadata?.themeColor ? metadata.themeColor : '#ececec',
|
|
481
460
|
});
|
|
482
461
|
ssrHeadComponents += SrrComponent({
|
|
483
|
-
|
|
462
|
+
backgroundImage: `data:image/png;base64,${bufferBackgroundImage.toString('base64')}`,
|
|
484
463
|
});
|
|
485
464
|
}
|
|
486
465
|
|
|
@@ -495,7 +474,13 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
495
474
|
}
|
|
496
475
|
|
|
497
476
|
default:
|
|
498
|
-
ssrBodyComponents += SrrComponent({
|
|
477
|
+
ssrBodyComponents += SrrComponent({
|
|
478
|
+
ssrPath,
|
|
479
|
+
host,
|
|
480
|
+
path,
|
|
481
|
+
ttiLoadTimeLimit,
|
|
482
|
+
version: Underpost.version,
|
|
483
|
+
});
|
|
499
484
|
break;
|
|
500
485
|
}
|
|
501
486
|
}
|
|
@@ -515,6 +500,15 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
515
500
|
ssrPath,
|
|
516
501
|
ssrHeadComponents,
|
|
517
502
|
ssrBodyComponents,
|
|
503
|
+
renderPayload: {
|
|
504
|
+
apiBaseProxyPath,
|
|
505
|
+
apiBaseHost,
|
|
506
|
+
apiBasePath: process.env.BASE_API,
|
|
507
|
+
version: Underpost.version,
|
|
508
|
+
},
|
|
509
|
+
renderApi: {
|
|
510
|
+
JSONweb,
|
|
511
|
+
},
|
|
518
512
|
});
|
|
519
513
|
|
|
520
514
|
fs.writeFileSync(
|
|
@@ -544,17 +538,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
544
538
|
let siteMapSrc = await new Promise((resolve) =>
|
|
545
539
|
streamToPromise(Readable.from(siteMapLinks).pipe(siteMapStream)).then((data) => resolve(data.toString())),
|
|
546
540
|
);
|
|
547
|
-
switch (publicClientId) {
|
|
548
|
-
case 'underpost':
|
|
549
|
-
siteMapSrc = siteMapSrc.replaceAll(
|
|
550
|
-
`</urlset>`,
|
|
551
|
-
`${fs.readFileSync(`./src/client/public/underpost/sitemap-template.txt`, 'utf8')} </urlset>`,
|
|
552
|
-
);
|
|
553
|
-
break;
|
|
554
541
|
|
|
555
|
-
default:
|
|
556
|
-
break;
|
|
557
|
-
}
|
|
558
542
|
// Return a promise that resolves with your XML string
|
|
559
543
|
fs.writeFileSync(`${rootClientPath}/sitemap.xml`, siteMapSrc, 'utf8');
|
|
560
544
|
if (xslUrl)
|
|
@@ -725,6 +709,15 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
725
709
|
ssrPath,
|
|
726
710
|
ssrHeadComponents: '',
|
|
727
711
|
ssrBodyComponents: SsrComponent(),
|
|
712
|
+
renderPayload: {
|
|
713
|
+
apiBaseProxyPath,
|
|
714
|
+
apiBaseHost,
|
|
715
|
+
apiBasePath: process.env.BASE_API,
|
|
716
|
+
version: Underpost.version,
|
|
717
|
+
},
|
|
718
|
+
renderApi: {
|
|
719
|
+
JSONweb,
|
|
720
|
+
},
|
|
728
721
|
});
|
|
729
722
|
|
|
730
723
|
const buildPath = `${
|
|
@@ -757,16 +750,14 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
757
750
|
}
|
|
758
751
|
|
|
759
752
|
{
|
|
760
|
-
const
|
|
761
|
-
|
|
753
|
+
const renderPayload = {
|
|
754
|
+
PRE_CACHED_RESOURCES: uniqueArray(PRE_CACHED_RESOURCES),
|
|
755
|
+
PROXY_PATH: path,
|
|
756
|
+
};
|
|
762
757
|
fs.writeFileSync(
|
|
763
758
|
`${rootClientPath}/sw.js`,
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
.replaceAll(`PRE_CACHED_RESOURCES = []`, PRE_CACHED_JSON)
|
|
767
|
-
.replaceAll(`PRE_CACHED_RESOURCES=[]`, PRE_CACHED_JSON)
|
|
768
|
-
.replaceAll(`PROXY_PATH = '/'`, PROXY_PATH)
|
|
769
|
-
.replaceAll(`PROXY_PATH='/'`, PROXY_PATH),
|
|
759
|
+
`self.renderPayload = ${JSONweb(renderPayload)};
|
|
760
|
+
${fs.readFileSync(`${rootClientPath}/sw.js`, 'utf8')}`,
|
|
770
761
|
'utf8',
|
|
771
762
|
);
|
|
772
763
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
|
+
import vm from 'node:vm';
|
|
5
|
+
import Underpost from '../index.js';
|
|
4
6
|
|
|
5
7
|
const srcFormatted = (src) =>
|
|
6
8
|
src
|
|
@@ -48,9 +50,10 @@ const viewFormatted = (src, dists, proxyPath, baseHost = '') => {
|
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
const ssrFactory = async (componentPath = `./src/client/ssr/Render.js`) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const context = { SrrComponent: () => {}, npm_package_version: Underpost.version };
|
|
54
|
+
vm.createContext(context);
|
|
55
|
+
vm.runInContext(await srcFormatted(fs.readFileSync(componentPath, 'utf8')), context);
|
|
56
|
+
return context.SrrComponent;
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
export { srcFormatted, JSONweb, componentFormatted, viewFormatted, ssrFactory };
|
|
@@ -141,7 +141,7 @@ const buildIcons = async ({
|
|
|
141
141
|
for (const file of response.files)
|
|
142
142
|
fs.writeFileSync(`./src/client/public/${publicClientId}/${file.name}`, file.contents, 'utf8');
|
|
143
143
|
|
|
144
|
-
const ssrPath = `./src/client/ssr/
|
|
144
|
+
const ssrPath = `./src/client/ssr/head/Pwa${getCapVariableName(publicClientId)}.js`;
|
|
145
145
|
if (!fs.existsSync(ssrPath))
|
|
146
146
|
fs.writeFileSync(ssrPath, 'SrrComponent = () => html`' + response.html.join(`\n`) + '`;', 'utf8');
|
|
147
147
|
} catch (error) {
|
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]);
|
|
@@ -253,8 +272,8 @@ const buildClientSrc = async (
|
|
|
253
272
|
}
|
|
254
273
|
|
|
255
274
|
fs.writeFileSync(
|
|
256
|
-
`./src/client/ssr/
|
|
257
|
-
formattedSrc(fs.readFileSync(`./src/client/ssr/
|
|
275
|
+
`./src/client/ssr/head/${toClientVariableName}Scripts.js`,
|
|
276
|
+
formattedSrc(fs.readFileSync(`./src/client/ssr/head/${fromClientVariableName}Scripts.js`, 'utf8')),
|
|
258
277
|
'utf8',
|
|
259
278
|
);
|
|
260
279
|
|
|
@@ -473,13 +492,55 @@ const buildProxyRouter = () => {
|
|
|
473
492
|
title: 'Site in maintenance',
|
|
474
493
|
ssrPath: '/',
|
|
475
494
|
ssrHeadComponents: '',
|
|
476
|
-
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/
|
|
495
|
+
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/offline/Maintenance.js`))(),
|
|
477
496
|
});
|
|
478
497
|
})();
|
|
479
498
|
|
|
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
|
};
|