underpost 2.8.47 → 2.8.48
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/Dockerfile +1 -1
- package/bin/build.js +26 -191
- package/bin/index.js +3 -0
- package/docker-compose.yml +1 -1
- package/package.json +1 -1
- package/src/cli/deploy.js +183 -1
- package/src/cli/repository.js +4 -2
- package/src/client/components/core/CommonJs.js +9 -0
- package/src/client/components/core/Modal.js +0 -1
- package/src/client/components/core/VanillaJs.js +0 -9
- package/src/client/components/core/Worker.js +34 -31
- package/src/index.js +1 -1
- package/src/server/conf.js +25 -15
- package/src/server/network.js +7 -4
package/Dockerfile
CHANGED
package/bin/build.js
CHANGED
|
@@ -3,7 +3,7 @@ import { loggerFactory } from '../src/server/logger.js';
|
|
|
3
3
|
import { shellExec } from '../src/server/process.js';
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
5
|
import { getCapVariableName } from '../src/client/components/core/CommonJs.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getPathsSSR } from '../src/server/conf.js';
|
|
7
7
|
|
|
8
8
|
const baseConfPath = './engine-private/conf/dd-cron/.env.production';
|
|
9
9
|
if (fs.existsSync(baseConfPath)) dotenv.config({ path: baseConfPath, override: true });
|
|
@@ -20,21 +20,13 @@ const logger = loggerFactory(import.meta);
|
|
|
20
20
|
const confName = process.argv[2];
|
|
21
21
|
const basePath = '../pwa-microservices-template';
|
|
22
22
|
const repoName = `engine-${confName.split('dd-')[1]}`;
|
|
23
|
-
const privateRepoName = `${repoName}-private`;
|
|
24
|
-
const privateRepoNameBackUp = `${repoName}-cron-backups`;
|
|
25
|
-
const gitPrivateUrl = `https://${process.env.GITHUB_TOKEN}@github.com/underpostnet/${privateRepoName}.git`;
|
|
26
|
-
const gitPrivateBackUpUrl = `https://${process.env.GITHUB_TOKEN}@github.com/underpostnet/${privateRepoNameBackUp}.git`;
|
|
27
23
|
|
|
28
24
|
logger.info('', {
|
|
29
25
|
confName,
|
|
30
26
|
repoName,
|
|
31
|
-
privateRepoName,
|
|
32
|
-
privateRepoNameBackUp,
|
|
33
27
|
basePath,
|
|
34
28
|
});
|
|
35
29
|
|
|
36
|
-
if (process.argv.includes('info')) process.exit(0);
|
|
37
|
-
|
|
38
30
|
if (process.argv.includes('clean')) {
|
|
39
31
|
if (fs.existsSync(`${basePath}/images`)) fs.copySync(`${basePath}/images`, `./images`);
|
|
40
32
|
shellExec(`cd ${basePath} && git checkout .`);
|
|
@@ -42,173 +34,34 @@ if (process.argv.includes('clean')) {
|
|
|
42
34
|
process.exit(0);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
if (process.argv.includes('proxy')) {
|
|
46
|
-
const env = process.argv.includes('development') ? 'development' : 'production';
|
|
47
|
-
process.env.NODE_ENV = env;
|
|
48
|
-
process.env.PORT = process.env.NODE_ENV === 'development' ? 4000 : 3000;
|
|
49
|
-
process.argv[2] = 'proxy';
|
|
50
|
-
process.argv[3] = fs.readFileSync('./engine-private/deploy/dd-router', 'utf8').trim();
|
|
51
|
-
|
|
52
|
-
await Config.build();
|
|
53
|
-
process.env.NODE_ENV = 'production';
|
|
54
|
-
const router = buildPortProxyRouter(443, buildProxyRouter());
|
|
55
|
-
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.server.json`, 'utf8'));
|
|
56
|
-
const confHosts = Object.keys(confServer);
|
|
57
|
-
|
|
58
|
-
for (const host of Object.keys(router)) {
|
|
59
|
-
if (!confHosts.find((_host) => host.match(_host))) {
|
|
60
|
-
delete router[host];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const ports = Object.values(router).map((p) => p.split(':')[2]);
|
|
65
|
-
|
|
66
|
-
const fromPort = ports[0];
|
|
67
|
-
const toPort = ports[ports.length - 1];
|
|
68
|
-
|
|
69
|
-
logger.info('port range', { fromPort, toPort, router });
|
|
70
|
-
|
|
71
|
-
const deploymentYamlFilePath = `./engine-private/conf/${confName}/build/${env}/deployment.yaml`;
|
|
72
|
-
|
|
73
|
-
const deploymentYamlParts = fs.readFileSync(deploymentYamlFilePath, 'utf8').split('ports:');
|
|
74
|
-
deploymentYamlParts[1] =
|
|
75
|
-
buildKindPorts(fromPort, toPort) +
|
|
76
|
-
` type: LoadBalancer
|
|
77
|
-
`;
|
|
78
|
-
|
|
79
|
-
fs.writeFileSync(
|
|
80
|
-
deploymentYamlFilePath,
|
|
81
|
-
deploymentYamlParts.join(`ports:
|
|
82
|
-
`),
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
let proxyYaml = '';
|
|
86
|
-
let secretYaml = '';
|
|
87
|
-
|
|
88
|
-
for (const host of Object.keys(confServer)) {
|
|
89
|
-
if (env === 'production')
|
|
90
|
-
secretYaml += `
|
|
91
|
-
---
|
|
92
|
-
apiVersion: cert-manager.io/v1
|
|
93
|
-
kind: Certificate
|
|
94
|
-
metadata:
|
|
95
|
-
name: ${host}
|
|
96
|
-
spec:
|
|
97
|
-
commonName: ${host}
|
|
98
|
-
dnsNames:
|
|
99
|
-
- ${host}
|
|
100
|
-
issuerRef:
|
|
101
|
-
name: letsencrypt-prod
|
|
102
|
-
kind: ClusterIssuer
|
|
103
|
-
secretName: ${host}`;
|
|
104
|
-
|
|
105
|
-
const pathPortConditions = [];
|
|
106
|
-
for (const path of Object.keys(confServer[host])) {
|
|
107
|
-
const { peer } = confServer[host][path];
|
|
108
|
-
const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
|
|
109
|
-
// logger.info('', { host, port, path });
|
|
110
|
-
pathPortConditions.push({
|
|
111
|
-
port,
|
|
112
|
-
path,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
if (peer) {
|
|
116
|
-
// logger.info('', { host, port: port + 1, path: '/peer' });
|
|
117
|
-
pathPortConditions.push({
|
|
118
|
-
port: port + 1,
|
|
119
|
-
path: '/peer',
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
// logger.info('', { host, pathPortConditions });
|
|
124
|
-
proxyYaml += `
|
|
125
|
-
---
|
|
126
|
-
apiVersion: projectcontour.io/v1
|
|
127
|
-
kind: HTTPProxy
|
|
128
|
-
metadata:
|
|
129
|
-
name: ${host}
|
|
130
|
-
spec:
|
|
131
|
-
virtualhost:
|
|
132
|
-
fqdn: ${host}${
|
|
133
|
-
env === 'development'
|
|
134
|
-
? ''
|
|
135
|
-
: `
|
|
136
|
-
tls:
|
|
137
|
-
secretName: ${host}`
|
|
138
|
-
}
|
|
139
|
-
routes:`;
|
|
140
|
-
for (const conditionObj of pathPortConditions) {
|
|
141
|
-
const { path, port } = conditionObj;
|
|
142
|
-
proxyYaml += `
|
|
143
|
-
- conditions:
|
|
144
|
-
- prefix: ${path}
|
|
145
|
-
enableWebsockets: true
|
|
146
|
-
services:
|
|
147
|
-
- name: ${confName}-${env}-service
|
|
148
|
-
port: ${port}`;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
const yamlPath = `./engine-private/conf/${confName}/build/${env}/proxy.yaml`;
|
|
152
|
-
fs.writeFileSync(yamlPath, proxyYaml, 'utf8');
|
|
153
|
-
if (env === 'production') {
|
|
154
|
-
const yamlPath = `./engine-private/conf/${confName}/build/${env}/secret.yaml`;
|
|
155
|
-
fs.writeFileSync(yamlPath, secretYaml, 'utf8');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
process.exit(0);
|
|
159
|
-
}
|
|
160
37
|
if (process.argv.includes('conf')) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
` &&
|
|
173
|
-
` && git commit -m "ci(engine-core-conf): ⚙️ Update ${confName} conf"` +
|
|
174
|
-
` && git push`,
|
|
175
|
-
);
|
|
176
|
-
process.exit(0);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (process.argv.includes('cron-backups')) {
|
|
180
|
-
if (!fs.existsSync(`../${privateRepoNameBackUp}`)) {
|
|
181
|
-
shellExec(`cd .. && git clone ${gitPrivateBackUpUrl}`, { silent: true });
|
|
182
|
-
} else {
|
|
183
|
-
shellExec(`cd ../${privateRepoNameBackUp} && git pull`);
|
|
184
|
-
}
|
|
185
|
-
const serverConf = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.server.json`, 'utf8'));
|
|
186
|
-
for (const host of Object.keys(serverConf)) {
|
|
187
|
-
for (let path of Object.keys(serverConf[host])) {
|
|
188
|
-
path = path.replaceAll('/', '-');
|
|
189
|
-
const toPath = `../${privateRepoNameBackUp}/${host}${path}`;
|
|
190
|
-
const fromPath = `./engine-private/cron-backups/${host}${path}`;
|
|
191
|
-
if (fs.existsSync(fromPath)) {
|
|
192
|
-
if (fs.existsSync(toPath)) fs.removeSync(toPath);
|
|
193
|
-
logger.info('Build', { fromPath, toPath });
|
|
194
|
-
fs.copySync(fromPath, toPath);
|
|
195
|
-
}
|
|
38
|
+
for (const _confName of (confName === 'dd'
|
|
39
|
+
? fs.readFileSync(`./engine-private/deploy/dd-router`, 'utf8')
|
|
40
|
+
: confName
|
|
41
|
+
).split(',')) {
|
|
42
|
+
const _repoName = `engine-${_confName.split('dd-')[1]}`;
|
|
43
|
+
const privateRepoName = `${_repoName}-private`;
|
|
44
|
+
const privateGitUri = `${process.env.GITHUB_USERNAME}/${privateRepoName}`;
|
|
45
|
+
|
|
46
|
+
if (!fs.existsSync(`../${privateRepoName}`)) {
|
|
47
|
+
shellExec(`cd .. && underpost clone ${privateGitUri}`, { silent: true });
|
|
48
|
+
} else {
|
|
49
|
+
shellExec(`cd ../${privateRepoName} && underpost pull . ${privateGitUri}`);
|
|
196
50
|
}
|
|
51
|
+
const toPath = `../${privateRepoName}/conf/${_confName}`;
|
|
52
|
+
fs.removeSync(toPath);
|
|
53
|
+
fs.mkdirSync(toPath, { recursive: true });
|
|
54
|
+
fs.copySync(`./engine-private/conf/${_confName}`, toPath);
|
|
55
|
+
shellExec(
|
|
56
|
+
`cd ../${privateRepoName}` +
|
|
57
|
+
` && git add .` +
|
|
58
|
+
` && underpost cmt . ci engine-core-conf 'Update ${_confName} conf'` +
|
|
59
|
+
` && underpost push . ${privateGitUri}`,
|
|
60
|
+
);
|
|
197
61
|
}
|
|
198
|
-
shellExec(
|
|
199
|
-
`cd ../${privateRepoNameBackUp}` +
|
|
200
|
-
` && git add .` +
|
|
201
|
-
` && git commit -m "ci(engine-core-cron-backups): ⚙️ Update ${confName} cron backups"` +
|
|
202
|
-
` && git push`,
|
|
203
|
-
);
|
|
204
62
|
process.exit(0);
|
|
205
63
|
}
|
|
206
64
|
|
|
207
|
-
if (process.argv.includes('test')) {
|
|
208
|
-
fs.mkdirSync(`${basePath}/engine-private/conf`, { recursive: true });
|
|
209
|
-
fs.copySync(`./engine-private/conf/${confName}`, `${basePath}/engine-private/conf/${confName}`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
65
|
const { DefaultConf } = await import(`../conf.${confName}.js`);
|
|
213
66
|
|
|
214
67
|
{
|
|
@@ -294,27 +147,9 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
|
|
|
294
147
|
const env = process.argv.includes('development') ? 'development' : 'production';
|
|
295
148
|
const deploymentsFiles = ['Dockerfile', 'proxy.yaml', 'deployment.yaml', 'secret.yaml'];
|
|
296
149
|
// remove engine-private of .dockerignore for local testing
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (!fs.existsSync(`./manifests/deployment/${confName}-${env}`))
|
|
302
|
-
fs.mkdirSync(`./manifests/deployment/${confName}-${env}`);
|
|
303
|
-
|
|
304
|
-
for (const file of deploymentsFiles) {
|
|
305
|
-
if (fs.existsSync(`./engine-private/conf/${confName}/build/${env}/${file}`)) {
|
|
306
|
-
fs.copyFileSync(`./engine-private/conf/${confName}/build/${env}/${file}`, `${basePath}/${file}`);
|
|
307
|
-
fs.copyFileSync(
|
|
308
|
-
`./engine-private/conf/${confName}/build/${env}/${file}`,
|
|
309
|
-
`./manifests/deployment/${confName}-${env}/${file}`,
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
for (const file of deploymentsFiles) {
|
|
315
|
-
if (fs.existsSync(`./manifests/deployment/${confName}-${env}/${file}`)) {
|
|
316
|
-
fs.copyFileSync(`./manifests/deployment/${confName}-${env}/${file}`, `${basePath}/${file}`);
|
|
317
|
-
}
|
|
150
|
+
for (const file of deploymentsFiles) {
|
|
151
|
+
if (fs.existsSync(`./manifests/deployment/${confName}-${env}/${file}`)) {
|
|
152
|
+
fs.copyFileSync(`./manifests/deployment/${confName}-${env}/${file}`, `${basePath}/${file}`);
|
|
318
153
|
}
|
|
319
154
|
}
|
|
320
155
|
}
|
package/bin/index.js
CHANGED
|
@@ -102,6 +102,9 @@ program
|
|
|
102
102
|
.argument('<deploy-list>', 'Deploy id list, e.g. default-a, default-b')
|
|
103
103
|
.argument('[env]', 'Optional environment, for default is development')
|
|
104
104
|
.option('--remove', 'Delete deployments and services')
|
|
105
|
+
.option('--sync', 'Sync deployments env, ports, and replicas')
|
|
106
|
+
.option('--info-router', 'Display router structure')
|
|
107
|
+
.option('--build-manifest', 'Build kind yaml manifests: deployments, services, proxy and secrets')
|
|
105
108
|
.description('Manage deployment, for default deploy development pods')
|
|
106
109
|
.action(Underpost.deploy.callback);
|
|
107
110
|
|
package/docker-compose.yml
CHANGED
package/package.json
CHANGED
package/src/cli/deploy.js
CHANGED
|
@@ -1,12 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildKindPorts,
|
|
3
|
+
buildPortProxyRouter,
|
|
4
|
+
buildProxyRouter,
|
|
5
|
+
Config,
|
|
6
|
+
getDataDeploy,
|
|
7
|
+
loadReplicas,
|
|
8
|
+
} from '../server/conf.js';
|
|
1
9
|
import { loggerFactory } from '../server/logger.js';
|
|
2
10
|
import { shellExec } from '../server/process.js';
|
|
3
11
|
import fs from 'fs-extra';
|
|
12
|
+
import dotenv from 'dotenv';
|
|
13
|
+
import Underpost from '../index.js';
|
|
4
14
|
|
|
5
15
|
const logger = loggerFactory(import.meta);
|
|
6
16
|
|
|
7
17
|
class UnderpostDeploy {
|
|
8
18
|
static API = {
|
|
9
|
-
|
|
19
|
+
sync(deployList) {
|
|
20
|
+
const deployGroupId = '_dd';
|
|
21
|
+
fs.writeFileSync(`./engine-private/deploy/${deployGroupId}.json`, JSON.stringify(deployList.split(',')), 'utf8');
|
|
22
|
+
return getDataDeploy({
|
|
23
|
+
buildSingleReplica: true,
|
|
24
|
+
deployGroupId,
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
async routerFactory(deployList, env) {
|
|
28
|
+
const initEnvPath = `./engine-private/conf/${deployList.split(',')[0]}/.env.${env}`;
|
|
29
|
+
const initEnvObj = dotenv.parse(fs.readFileSync(initEnvPath, 'utf8'));
|
|
30
|
+
process.env.PORT = initEnvObj.PORT;
|
|
31
|
+
process.env.NODE_ENV = env;
|
|
32
|
+
await Config.build(undefined, 'proxy', deployList);
|
|
33
|
+
return buildPortProxyRouter(env === 'development' ? 80 : 443, buildProxyRouter());
|
|
34
|
+
},
|
|
35
|
+
async buildManifest(deployList, env) {
|
|
36
|
+
for (const _deployId of deployList.split(',')) {
|
|
37
|
+
const deployId = _deployId.trim();
|
|
38
|
+
if (!deployId) continue;
|
|
39
|
+
|
|
40
|
+
const router = await UnderpostDeploy.API.routerFactory(deployId, env);
|
|
41
|
+
const ports = Object.values(router).map((p) => parseInt(p.split(':')[2]));
|
|
42
|
+
const fromPort = Math.min(...ports);
|
|
43
|
+
const toPort = Math.max(...ports);
|
|
44
|
+
const confServer = loadReplicas(
|
|
45
|
+
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
46
|
+
'proxy',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
fs.mkdirSync(`./engine-private/conf/${deployId}/build/${env}`, { recursive: true });
|
|
50
|
+
if (env === 'development') fs.mkdirSync(`./manifests/deployment/${deployId}-${env}`, { recursive: true });
|
|
51
|
+
|
|
52
|
+
logger.info('port range', { deployId, fromPort, toPort });
|
|
53
|
+
|
|
54
|
+
const deploymentYamlParts = `apiVersion: apps/v1
|
|
55
|
+
kind: Deployment
|
|
56
|
+
metadata:
|
|
57
|
+
name: ${deployId}-${env}
|
|
58
|
+
labels:
|
|
59
|
+
app: ${deployId}-${env}
|
|
60
|
+
spec:
|
|
61
|
+
replicas: 2
|
|
62
|
+
selector:
|
|
63
|
+
matchLabels:
|
|
64
|
+
app: ${deployId}-${env}
|
|
65
|
+
template:
|
|
66
|
+
metadata:
|
|
67
|
+
labels:
|
|
68
|
+
app: ${deployId}-${env}
|
|
69
|
+
spec:
|
|
70
|
+
containers:
|
|
71
|
+
- name: ${deployId}-${env}
|
|
72
|
+
image: localhost/${deployId}-${env}:${Underpost.version}
|
|
73
|
+
---
|
|
74
|
+
apiVersion: v1
|
|
75
|
+
kind: Service
|
|
76
|
+
metadata:
|
|
77
|
+
name: ${deployId}-${env}-service
|
|
78
|
+
spec:
|
|
79
|
+
selector:
|
|
80
|
+
app: ${deployId}-${env}
|
|
81
|
+
ports:
|
|
82
|
+
type: LoadBalancer`.split('ports:');
|
|
83
|
+
deploymentYamlParts[1] =
|
|
84
|
+
buildKindPorts(fromPort, toPort) +
|
|
85
|
+
` type: LoadBalancer
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
fs.writeFileSync(
|
|
89
|
+
`./engine-private/conf/${deployId}/build/${env}/deployment.yaml`,
|
|
90
|
+
deploymentYamlParts.join(`ports:
|
|
91
|
+
`),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
let proxyYaml = '';
|
|
95
|
+
let secretYaml = '';
|
|
96
|
+
|
|
97
|
+
for (const host of Object.keys(confServer)) {
|
|
98
|
+
if (env === 'production')
|
|
99
|
+
secretYaml += `
|
|
100
|
+
---
|
|
101
|
+
apiVersion: cert-manager.io/v1
|
|
102
|
+
kind: Certificate
|
|
103
|
+
metadata:
|
|
104
|
+
name: ${host}
|
|
105
|
+
spec:
|
|
106
|
+
commonName: ${host}
|
|
107
|
+
dnsNames:
|
|
108
|
+
- ${host}
|
|
109
|
+
issuerRef:
|
|
110
|
+
name: letsencrypt-prod
|
|
111
|
+
kind: ClusterIssuer
|
|
112
|
+
secretName: ${host}`;
|
|
113
|
+
|
|
114
|
+
const pathPortConditions = [];
|
|
115
|
+
for (const path of Object.keys(confServer[host])) {
|
|
116
|
+
const { peer } = confServer[host][path];
|
|
117
|
+
if (!router[`${host}${path === '/' ? '' : path}`]) continue;
|
|
118
|
+
const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
|
|
119
|
+
// logger.info('', { host, port, path });
|
|
120
|
+
pathPortConditions.push({
|
|
121
|
+
port,
|
|
122
|
+
path,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (peer) {
|
|
126
|
+
// logger.info('', { host, port: port + 1, path: '/peer' });
|
|
127
|
+
pathPortConditions.push({
|
|
128
|
+
port: port + 1,
|
|
129
|
+
path: '/peer',
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// logger.info('', { host, pathPortConditions });
|
|
135
|
+
proxyYaml += `
|
|
136
|
+
---
|
|
137
|
+
apiVersion: projectcontour.io/v1
|
|
138
|
+
kind: HTTPProxy
|
|
139
|
+
metadata:
|
|
140
|
+
name: ${host}
|
|
141
|
+
spec:
|
|
142
|
+
virtualhost:
|
|
143
|
+
fqdn: ${host}${
|
|
144
|
+
env === 'development'
|
|
145
|
+
? ''
|
|
146
|
+
: `
|
|
147
|
+
tls:
|
|
148
|
+
secretName: ${host}`
|
|
149
|
+
}
|
|
150
|
+
routes:`;
|
|
151
|
+
for (const conditionObj of pathPortConditions) {
|
|
152
|
+
const { path, port } = conditionObj;
|
|
153
|
+
proxyYaml += `
|
|
154
|
+
- conditions:
|
|
155
|
+
- prefix: ${path}
|
|
156
|
+
enableWebsockets: true
|
|
157
|
+
services:
|
|
158
|
+
- name: ${deployId}-${env}-service
|
|
159
|
+
port: ${port}`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/proxy.yaml`;
|
|
163
|
+
fs.writeFileSync(yamlPath, proxyYaml, 'utf8');
|
|
164
|
+
if (env === 'production') {
|
|
165
|
+
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/secret.yaml`;
|
|
166
|
+
fs.writeFileSync(yamlPath, secretYaml, 'utf8');
|
|
167
|
+
} else {
|
|
168
|
+
const deploymentsFiles = ['Dockerfile', 'proxy.yaml', 'deployment.yaml'];
|
|
169
|
+
for (const file of deploymentsFiles) {
|
|
170
|
+
if (fs.existsSync(`./engine-private/conf/${deployId}/build/${env}/${file}`)) {
|
|
171
|
+
fs.copyFileSync(
|
|
172
|
+
`./engine-private/conf/${deployId}/build/${env}/${file}`,
|
|
173
|
+
`./manifests/deployment/${deployId}-${env}/${file}`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
async callback(
|
|
181
|
+
deployList = 'default',
|
|
182
|
+
env = 'development',
|
|
183
|
+
options = { remove: false, infoRouter: false, sync: false, buildManifest: false },
|
|
184
|
+
) {
|
|
185
|
+
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd-router`))
|
|
186
|
+
deployList = fs.readFileSync(`./engine-private/deploy/dd-router`, 'utf8');
|
|
187
|
+
if (options.sync) UnderpostDeploy.API.sync(deployList);
|
|
188
|
+
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env);
|
|
189
|
+
if (options.infoRouter === true)
|
|
190
|
+
return logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
|
|
191
|
+
|
|
10
192
|
for (const _deployId of deployList.split(',')) {
|
|
11
193
|
const deployId = _deployId.trim();
|
|
12
194
|
if (!deployId) continue;
|
package/src/cli/repository.js
CHANGED
|
@@ -4,6 +4,7 @@ import { pbcopy, shellExec } from '../server/process.js';
|
|
|
4
4
|
import { actionInitLog, loggerFactory } from '../server/logger.js';
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
6
|
import { getNpmRootPath } from '../server/conf.js';
|
|
7
|
+
import { listenPortController, listenServerFactory } from '../server/network.js';
|
|
7
8
|
|
|
8
9
|
dotenv.config();
|
|
9
10
|
|
|
@@ -86,9 +87,10 @@ class UnderpostRepository {
|
|
|
86
87
|
new(repositoryName) {
|
|
87
88
|
return new Promise(async (resolve, reject) => {
|
|
88
89
|
try {
|
|
89
|
-
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
90
|
-
actionInitLog();
|
|
91
90
|
await logger.setUpInfo();
|
|
91
|
+
if (repositoryName === 'service') return resolve(await listenPortController(listenServerFactory(), ':'));
|
|
92
|
+
else actionInitLog();
|
|
93
|
+
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
92
94
|
const destFolder = `./${repositoryName}`;
|
|
93
95
|
logger.info('Note: This process may take several minutes to complete');
|
|
94
96
|
logger.info('build app', { destFolder });
|
|
@@ -573,6 +573,14 @@ const isValidFormat = (value, format) => {
|
|
|
573
573
|
}
|
|
574
574
|
};
|
|
575
575
|
|
|
576
|
+
const getCurrentTrace = () => {
|
|
577
|
+
try {
|
|
578
|
+
_stack;
|
|
579
|
+
} catch (error) {
|
|
580
|
+
return error.stack.split('is not defined')[1];
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
576
584
|
/**
|
|
577
585
|
* Returns the time difference between UTC time and local time, in minutes.
|
|
578
586
|
* @memberof CommonJS
|
|
@@ -943,6 +951,7 @@ export {
|
|
|
943
951
|
commonAdminGuard,
|
|
944
952
|
commonModeratorGuard,
|
|
945
953
|
isChileanIdentityDocument,
|
|
954
|
+
getCurrentTrace,
|
|
946
955
|
userRoleEnum,
|
|
947
956
|
commitData,
|
|
948
957
|
};
|
|
@@ -419,14 +419,6 @@ const isActiveTab = () => document.hasFocus();
|
|
|
419
419
|
const isActiveElement = (classSearch = '') =>
|
|
420
420
|
document.activeElement?.classList?.value?.match(classSearch) ? true : false;
|
|
421
421
|
|
|
422
|
-
const getCurrentTrace = () => {
|
|
423
|
-
try {
|
|
424
|
-
_stack;
|
|
425
|
-
} catch (error) {
|
|
426
|
-
return error.stack.split('is not defined')[1];
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
|
|
430
422
|
const isDevInstance = () => location.origin.match('localhost') && location.port;
|
|
431
423
|
|
|
432
424
|
const getDataFromInputFile = async (file) => Array.from(new Uint8Array(await file.arrayBuffer()));
|
|
@@ -460,7 +452,6 @@ export {
|
|
|
460
452
|
isNavigator,
|
|
461
453
|
getTimeZone,
|
|
462
454
|
getAllChildNodes,
|
|
463
|
-
getCurrentTrace,
|
|
464
455
|
isActiveTab,
|
|
465
456
|
isActiveElement,
|
|
466
457
|
isDevInstance,
|
|
@@ -22,41 +22,44 @@ const Worker = {
|
|
|
22
22
|
setTimeout(() => {
|
|
23
23
|
if ('onLine' in navigator && navigator.onLine) window.ononline();
|
|
24
24
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
if ('serviceWorker' in navigator) {
|
|
26
|
+
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
|
27
|
+
logger.info('The controller of current browsing context has changed.');
|
|
28
|
+
});
|
|
29
|
+
navigator.serviceWorker.ready.then((worker) => {
|
|
30
|
+
logger.info('Ready', worker);
|
|
31
|
+
// event message
|
|
32
|
+
navigator.serviceWorker.addEventListener('message', (event) => {
|
|
33
|
+
logger.info('Received event message', event.data);
|
|
34
|
+
const { status } = event.data;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
switch (status) {
|
|
37
|
+
case 'loader':
|
|
38
|
+
{
|
|
39
|
+
LoadingAnimation.RenderCurrentSrcLoad(event);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
default:
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
// if (navigator.serviceWorker.controller)
|
|
49
|
+
// navigator.serviceWorker.controller.postMessage({
|
|
50
|
+
// title: 'Hello from Client event message',
|
|
51
|
+
// });
|
|
52
|
+
|
|
53
|
+
// broadcast message
|
|
54
|
+
// const channel = new BroadcastChannel('sw-messages');
|
|
55
|
+
// channel.addEventListener('message', (event) => {
|
|
56
|
+
// logger.info('Received broadcast message', event.data);
|
|
57
|
+
// });
|
|
58
|
+
// channel.postMessage({ title: 'Hello from Client broadcast message' });
|
|
59
|
+
// channel.close();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
51
62
|
|
|
52
|
-
// broadcast message
|
|
53
|
-
// const channel = new BroadcastChannel('sw-messages');
|
|
54
|
-
// channel.addEventListener('message', (event) => {
|
|
55
|
-
// logger.info('Received broadcast message', event.data);
|
|
56
|
-
// });
|
|
57
|
-
// channel.postMessage({ title: 'Hello from Client broadcast message' });
|
|
58
|
-
// channel.close();
|
|
59
|
-
});
|
|
60
63
|
this.RouterInstance = router();
|
|
61
64
|
const isInstall = await this.status();
|
|
62
65
|
if (!isInstall) await this.install();
|
package/src/index.js
CHANGED
package/src/server/conf.js
CHANGED
|
@@ -40,21 +40,26 @@ const logger = loggerFactory(import.meta);
|
|
|
40
40
|
|
|
41
41
|
const Config = {
|
|
42
42
|
default: DefaultConf,
|
|
43
|
-
build: async function (options = { folder: '' }) {
|
|
43
|
+
build: async function (options = { folder: '' }, deployContext, deployList, subConf) {
|
|
44
|
+
if (!deployContext) deployContext = process.argv[2];
|
|
44
45
|
if (!fs.existsSync(`./tmp`)) fs.mkdirSync(`./tmp`, { recursive: true });
|
|
45
46
|
fs.writeFileSync(`./tmp/await-deploy`, '', 'utf8');
|
|
46
|
-
if (fs.existsSync(`./engine-private/conf/${
|
|
47
|
-
|
|
47
|
+
if (fs.existsSync(`./engine-private/conf/${deployContext}`))
|
|
48
|
+
return loadConf(deployContext, process.env.NODE_ENV, subConf);
|
|
49
|
+
if (fs.existsSync(`./engine-private/replica/${deployContext}`))
|
|
50
|
+
return loadConf(deployContext, process.env.NODE_ENV, subConf);
|
|
48
51
|
|
|
49
|
-
if (
|
|
52
|
+
if (deployContext === 'deploy') return;
|
|
50
53
|
|
|
51
|
-
if (
|
|
54
|
+
if (deployContext === 'proxy') {
|
|
55
|
+
if (!deployList) deployList = process.argv[3];
|
|
56
|
+
if (!subConf) subConf = process.argv[4];
|
|
52
57
|
this.default.server = {};
|
|
53
|
-
for (const deployId of
|
|
58
|
+
for (const deployId of deployList.split(',')) {
|
|
54
59
|
let confPath = `./engine-private/conf/${deployId}/conf.server.json`;
|
|
55
60
|
const privateConfDevPath = fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
|
|
56
61
|
? `./engine-private/replica/${deployId}/conf.server.json`
|
|
57
|
-
: `./engine-private/conf/${deployId}/conf.server.dev.${
|
|
62
|
+
: `./engine-private/conf/${deployId}/conf.server.dev.${subConf}.json`;
|
|
58
63
|
const confDevPath = fs.existsSync(privateConfDevPath)
|
|
59
64
|
? privateConfDevPath
|
|
60
65
|
: `./engine-private/conf/${deployId}/conf.server.dev.json`;
|
|
@@ -62,7 +67,7 @@ const Config = {
|
|
|
62
67
|
if (process.env.NODE_ENV === 'development' && fs.existsSync(confDevPath)) confPath = confDevPath;
|
|
63
68
|
const serverConf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
|
|
64
69
|
|
|
65
|
-
for (const host of Object.keys(loadReplicas(serverConf))) {
|
|
70
|
+
for (const host of Object.keys(loadReplicas(serverConf, deployContext, subConf))) {
|
|
66
71
|
if (serverConf[host]['/'])
|
|
67
72
|
this.default.server[host] = {
|
|
68
73
|
...this.default.server[host],
|
|
@@ -92,7 +97,7 @@ const Config = {
|
|
|
92
97
|
},
|
|
93
98
|
};
|
|
94
99
|
|
|
95
|
-
const loadConf = (deployId, envInput) => {
|
|
100
|
+
const loadConf = (deployId, envInput, subConf) => {
|
|
96
101
|
const folder = fs.existsSync(`./engine-private/replica/${deployId}`)
|
|
97
102
|
? `./engine-private/replica/${deployId}`
|
|
98
103
|
: `./engine-private/conf/${deployId}`;
|
|
@@ -109,7 +114,8 @@ const loadConf = (deployId, envInput) => {
|
|
|
109
114
|
? fs.readFileSync(`${folder}/conf.${typeConf}.json`, 'utf8')
|
|
110
115
|
: JSON.stringify(Config.default[typeConf]);
|
|
111
116
|
if (process.env.NODE_ENV === 'development' && typeConf === 'server') {
|
|
112
|
-
|
|
117
|
+
if (!subConf) subConf = process.argv[3];
|
|
118
|
+
const devConfPath = `${folder}/conf.${typeConf}.dev${subConf ? `.${subConf}` : ''}.json`;
|
|
113
119
|
if (fs.existsSync(devConfPath)) srcConf = fs.readFileSync(devConfPath, 'utf8');
|
|
114
120
|
}
|
|
115
121
|
if (typeConf === 'server') srcConf = JSON.stringify(loadReplicas(JSON.parse(srcConf)), null, 4);
|
|
@@ -135,15 +141,17 @@ const loadConf = (deployId, envInput) => {
|
|
|
135
141
|
return { folder, deployId };
|
|
136
142
|
};
|
|
137
143
|
|
|
138
|
-
const loadReplicas = (confServer) => {
|
|
144
|
+
const loadReplicas = (confServer, deployContext, subConf) => {
|
|
145
|
+
if (!deployContext) deployContext = process.argv[2];
|
|
146
|
+
if (!subConf) subConf = process.argv[3];
|
|
139
147
|
for (const host of Object.keys(confServer)) {
|
|
140
148
|
for (const path of Object.keys(confServer[host])) {
|
|
141
149
|
const { replicas, singleReplica } = confServer[host][path];
|
|
142
150
|
if (
|
|
143
151
|
replicas &&
|
|
144
|
-
(
|
|
152
|
+
(deployContext === 'proxy' ||
|
|
145
153
|
!singleReplica ||
|
|
146
|
-
(singleReplica && process.env.NODE_ENV === 'development' && !
|
|
154
|
+
(singleReplica && process.env.NODE_ENV === 'development' && !subConf))
|
|
147
155
|
)
|
|
148
156
|
for (const replicaPath of replicas) {
|
|
149
157
|
confServer[host][replicaPath] = newInstance(confServer[host][path]);
|
|
@@ -513,14 +521,16 @@ const buildPortProxyRouter = (port, proxyRouter) => {
|
|
|
513
521
|
// build router
|
|
514
522
|
Object.keys(hosts).map((hostKey) => {
|
|
515
523
|
let { host, path, target, proxy, peer } = hosts[hostKey];
|
|
516
|
-
if (process.env.NODE_ENV === 'development') host = `localhost`;
|
|
524
|
+
if (process.argv.includes('localhost') && process.env.NODE_ENV === 'development') host = `localhost`;
|
|
517
525
|
|
|
518
526
|
if (!proxy.includes(port)) return;
|
|
519
527
|
const absoluteHost = [80, 443].includes(port)
|
|
520
528
|
? `${host}${path === '/' ? '' : path}`
|
|
521
529
|
: `${host}:${port}${path === '/' ? '' : path}`;
|
|
522
530
|
|
|
523
|
-
if (
|
|
531
|
+
if (process.argv.includes('localhost')) {
|
|
532
|
+
if (!(absoluteHost in router)) router[absoluteHost] = target;
|
|
533
|
+
} else router[absoluteHost] = target;
|
|
524
534
|
}); // order router
|
|
525
535
|
|
|
526
536
|
if (Object.keys(router).length === 0) return router;
|
package/src/server/network.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
|
|
3
3
|
import { publicIp, publicIpv4, publicIpv6 } from 'public-ip';
|
|
4
|
-
import { loggerFactory } from './logger.js';
|
|
4
|
+
import { actionInitLog, loggerFactory } from './logger.js';
|
|
5
5
|
import { DataBaseProvider } from '../db/DataBaseProvider.js';
|
|
6
6
|
import { getDeployId } from './conf.js';
|
|
7
7
|
|
|
@@ -77,7 +77,7 @@ const saveRuntimeRouter = async () => {
|
|
|
77
77
|
|
|
78
78
|
if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
|
|
79
79
|
} catch (error) {
|
|
80
|
-
logger.error(error);
|
|
80
|
+
logger.error(error, error.stack);
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -114,7 +114,7 @@ const saveRuntimeCron = async () => {
|
|
|
114
114
|
|
|
115
115
|
if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
|
|
116
116
|
} catch (error) {
|
|
117
|
-
logger.error(error);
|
|
117
|
+
logger.error(error, error.stack);
|
|
118
118
|
}
|
|
119
119
|
};
|
|
120
120
|
|
|
@@ -134,7 +134,10 @@ const listenServerFactory = (logic = async () => {}) => {
|
|
|
134
134
|
const listenPortController = async (server, port, metadata) =>
|
|
135
135
|
new Promise((resolve) => {
|
|
136
136
|
try {
|
|
137
|
-
if (
|
|
137
|
+
if (port === ':') {
|
|
138
|
+
server.listen(port, actionInitLog);
|
|
139
|
+
return resolve(true);
|
|
140
|
+
}
|
|
138
141
|
|
|
139
142
|
const { host, path, client, runtime, meta } = metadata;
|
|
140
143
|
const error = [];
|