underpost 2.8.56 → 2.8.61
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/.vscode/settings.json +3 -0
- package/bin/index.js +14 -6
- package/bin/vs.js +1 -0
- package/docker-compose.yml +1 -1
- package/manifests/mongodb/kustomization.yaml +2 -2
- package/package.json +1 -1
- package/src/cli/cron.js +1 -1
- package/src/cli/db.js +101 -39
- package/src/cli/deploy.js +27 -6
- package/src/cli/fs.js +27 -12
- package/src/cli/image.js +36 -4
- package/src/cli/repository.js +9 -1
- package/src/client/components/core/CalendarCore.js +12 -1
- package/src/client/components/core/CommonJs.js +52 -1
- package/src/client/components/core/CssCore.js +2 -4
- package/src/client/components/core/Docs.js +1 -2
- package/src/client/components/core/Input.js +4 -2
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +30 -6
- package/src/client/components/core/Panel.js +8 -6
- package/src/client/components/core/PanelForm.js +23 -7
- package/src/client/services/core/core.service.js +15 -10
- 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/index.js +1 -1
- package/src/server/backup.js +2 -2
- package/src/server/client-build.js +32 -23
- package/src/server/conf.js +1 -1
- package/src/server/runtime.js +16 -1
- package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
- package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
package/.vscode/settings.json
CHANGED
package/bin/index.js
CHANGED
|
@@ -6,9 +6,6 @@ import Underpost from '../src/index.js';
|
|
|
6
6
|
import { getUnderpostRootPath, loadConf } from '../src/server/conf.js';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
8
|
import { commitData } from '../src/client/components/core/CommonJs.js';
|
|
9
|
-
import UnderpostScript from '../src/cli/script.js';
|
|
10
|
-
import UnderpostDB from '../src/cli/db.js';
|
|
11
|
-
import UnderpostCron from '../src/cli/cron.js';
|
|
12
9
|
|
|
13
10
|
const underpostRootPath = getUnderpostRootPath();
|
|
14
11
|
fs.existsSync(`${underpostRootPath}/.env`)
|
|
@@ -106,7 +103,9 @@ program
|
|
|
106
103
|
.option('--info-router', 'Display router structure')
|
|
107
104
|
.option('--expose', 'Expose service match deploy-list')
|
|
108
105
|
.option('--info-util', 'Display kubectl util management commands')
|
|
106
|
+
.option('--cert', 'Reset tls/ssl certificate secrets')
|
|
109
107
|
.option('--build-manifest', 'Build kind yaml manifests: deployments, services, proxy and secrets')
|
|
108
|
+
.option('--version', 'Set custom version')
|
|
110
109
|
.description('Manage deployment, for default deploy development pods')
|
|
111
110
|
.action(Underpost.deploy.callback);
|
|
112
111
|
|
|
@@ -130,6 +129,7 @@ program
|
|
|
130
129
|
.argument('<deploy-id>', 'Deploy configuration id')
|
|
131
130
|
.argument('[env]', 'Optional environment, for default is development')
|
|
132
131
|
.option('--run', 'Run custom entry point script')
|
|
132
|
+
.option('--build', 'Build custom image container scripts')
|
|
133
133
|
.description('Dockerfile custom node build script')
|
|
134
134
|
.action(Underpost.image.dockerfile.script);
|
|
135
135
|
|
|
@@ -140,6 +140,8 @@ program
|
|
|
140
140
|
.argument('[path]', 'Absolute or relative directory, for default is current')
|
|
141
141
|
.option('--image-archive', 'Only load tar image from ./images')
|
|
142
142
|
.option('--podman-save', 'Save image from podman to ./images')
|
|
143
|
+
.option('--image-name <image-name>', 'Set custom image name')
|
|
144
|
+
.option('--image-version <image-version>', 'Set custom image version')
|
|
143
145
|
.description('Build image from Dockerfile')
|
|
144
146
|
.action(Underpost.image.dockerfile.build);
|
|
145
147
|
|
|
@@ -161,13 +163,18 @@ program
|
|
|
161
163
|
.option('--import', 'Import container backups from repositories')
|
|
162
164
|
.option('--export', 'Export container backups to repositories')
|
|
163
165
|
.option('--pod-name <pod-name>', 'Optional pod context')
|
|
166
|
+
.option('--collection <collection>', 'Collection')
|
|
167
|
+
.option('--out-path <out-path>', 'Custom out path backup')
|
|
168
|
+
.option('--drop', 'Drop databases')
|
|
169
|
+
.option('--preserveUUID', 'Preserve Ids')
|
|
170
|
+
.option('--git', 'Upload to github')
|
|
164
171
|
.option('--ns <ns-name>', 'Optional name space context')
|
|
165
172
|
.description('Manage databases')
|
|
166
|
-
.action(
|
|
173
|
+
.action(Underpost.db.callback);
|
|
167
174
|
|
|
168
175
|
program
|
|
169
176
|
.command('script')
|
|
170
|
-
.argument('operator', `Options: ${Object.keys(
|
|
177
|
+
.argument('operator', `Options: ${Object.keys(Underpost.script)}`)
|
|
171
178
|
.argument('<script-name>', 'Script name')
|
|
172
179
|
.argument('[script-value]', 'Literal command, or path')
|
|
173
180
|
.option('--itc', 'Inside container execution context')
|
|
@@ -182,9 +189,10 @@ program
|
|
|
182
189
|
program
|
|
183
190
|
.command('cron')
|
|
184
191
|
.argument('[deploy-list]', 'Deploy id list, e.g. default-a,default-b')
|
|
185
|
-
.argument('[job-list]', `Deploy id list, e.g. ${Object.keys(
|
|
192
|
+
.argument('[job-list]', `Deploy id list, e.g. ${Object.keys(Underpost.cron)}, for default all available jobs`)
|
|
186
193
|
.option('--itc', 'Inside container execution context')
|
|
187
194
|
.option('--init', 'Init cron jobs for cron job default deploy id')
|
|
195
|
+
.option('--git', 'Upload to github')
|
|
188
196
|
.description('Cron jobs management')
|
|
189
197
|
.action(Underpost.cron.callback);
|
|
190
198
|
|
package/bin/vs.js
CHANGED
|
@@ -20,6 +20,7 @@ switch (process.argv[2]) {
|
|
|
20
20
|
logger.info('Open new vs windows', 'Ctrl Shift N');
|
|
21
21
|
logger.info('Close current vs windows', 'Ctrl Shift W');
|
|
22
22
|
logger.info('Preview md', 'Ctrl shift V');
|
|
23
|
+
logger.info('Open git changes', 'Ctrl G + G');
|
|
23
24
|
logger.warn('Terminal shortcut configure with command pallette', 'Ctl shift T');
|
|
24
25
|
break;
|
|
25
26
|
}
|
package/docker-compose.yml
CHANGED
package/package.json
CHANGED
package/src/cli/cron.js
CHANGED
|
@@ -46,7 +46,7 @@ class UnderpostCron {
|
|
|
46
46
|
callback: async function (
|
|
47
47
|
deployList = 'default',
|
|
48
48
|
jobList = Object.keys(UnderpostCron.JOB),
|
|
49
|
-
options = { itc: false, init: false },
|
|
49
|
+
options = { itc: false, init: false, git: false },
|
|
50
50
|
) {
|
|
51
51
|
if (options.init === true) {
|
|
52
52
|
await Underpost.test.setUpInfo();
|
package/src/cli/db.js
CHANGED
|
@@ -2,12 +2,26 @@ import { mergeFile, splitFileFactory } from '../server/conf.js';
|
|
|
2
2
|
import { loggerFactory } from '../server/logger.js';
|
|
3
3
|
import { shellExec } from '../server/process.js';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
|
+
import UnderpostDeploy from './deploy.js';
|
|
5
6
|
|
|
6
7
|
const logger = loggerFactory(import.meta);
|
|
7
8
|
|
|
8
9
|
class UnderpostDB {
|
|
9
10
|
static API = {
|
|
10
|
-
async callback(
|
|
11
|
+
async callback(
|
|
12
|
+
deployList = 'default',
|
|
13
|
+
options = {
|
|
14
|
+
import: false,
|
|
15
|
+
export: false,
|
|
16
|
+
podName: false,
|
|
17
|
+
ns: false,
|
|
18
|
+
collection: '',
|
|
19
|
+
outPath: '',
|
|
20
|
+
drop: false,
|
|
21
|
+
preserveUUID: false,
|
|
22
|
+
git: false,
|
|
23
|
+
},
|
|
24
|
+
) {
|
|
11
25
|
const newBackupTimestamp = new Date().getTime();
|
|
12
26
|
const nameSpace = options.ns && typeof options.ns === 'string' ? options.ns : 'default';
|
|
13
27
|
for (const _deployId of deployList.split(',')) {
|
|
@@ -43,10 +57,12 @@ class UnderpostDB {
|
|
|
43
57
|
logger.info('', { hostFolder, provider, dbName });
|
|
44
58
|
|
|
45
59
|
const backUpPath = `../${repoName}/${hostFolder}`;
|
|
60
|
+
if (!fs.existsSync(backUpPath)) fs.mkdirSync(backUpPath, { recursive: true });
|
|
61
|
+
shellExec(`cd ${backUpPath} && find . -type d -empty -delete`); // delete empty folders
|
|
46
62
|
const times = await fs.readdir(backUpPath);
|
|
47
|
-
const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)));
|
|
63
|
+
const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)).filter((t) => !isNaN(t)));
|
|
48
64
|
dbs[provider][dbName].currentBackupTimestamp = currentBackupTimestamp;
|
|
49
|
-
const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)));
|
|
65
|
+
const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)).filter((t) => !isNaN(t)));
|
|
50
66
|
|
|
51
67
|
const sqlContainerPath = `/home/${dbName}.sql`;
|
|
52
68
|
const _fromPartsParts = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}-parths.json`;
|
|
@@ -68,59 +84,105 @@ class UnderpostDB {
|
|
|
68
84
|
}
|
|
69
85
|
|
|
70
86
|
if (options.export === true && times.length >= 5) {
|
|
87
|
+
logger.info('remove', `../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
|
|
71
88
|
fs.removeSync(`../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
|
|
89
|
+
logger.info('create', `../${repoName}/${hostFolder}/${newBackupTimestamp}`);
|
|
72
90
|
fs.mkdirSync(`../${repoName}/${hostFolder}/${newBackupTimestamp}`, { recursive: true });
|
|
73
91
|
}
|
|
74
92
|
|
|
75
93
|
switch (provider) {
|
|
76
94
|
case 'mariadb': {
|
|
77
|
-
const
|
|
78
|
-
options.podName && typeof options.podName === 'string'
|
|
95
|
+
const podNames =
|
|
96
|
+
options.podName && typeof options.podName === 'string'
|
|
97
|
+
? options.podName.split(',')
|
|
98
|
+
: UnderpostDeploy.API.get('mariadb'); // `mariadb-statefulset-0`;
|
|
79
99
|
const serviceName = 'mariadb';
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`kubectl
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
for (const podNameData of [podNames[0]]) {
|
|
101
|
+
const podName = podNameData.NAME;
|
|
102
|
+
if (options.import === true) {
|
|
103
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}.sql"`);
|
|
104
|
+
shellExec(`sudo kubectl cp ${_toSqlPath} ${nameSpace}/${podName}:/${dbName}.sql`);
|
|
105
|
+
const cmd = `mariadb -u ${user} -p${password} ${dbName} < /${dbName}.sql`;
|
|
106
|
+
shellExec(
|
|
107
|
+
`kubectl exec -i ${podName} -- ${serviceName} -p${password} -e 'CREATE DATABASE ${dbName};'`,
|
|
108
|
+
);
|
|
109
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
|
|
110
|
+
}
|
|
111
|
+
if (options.export === true) {
|
|
112
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${sqlContainerPath}"`);
|
|
113
|
+
const cmd = `mariadb-dump --user=${user} --password=${password} --lock-tables ${dbName} > ${sqlContainerPath}`;
|
|
114
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
|
|
115
|
+
shellExec(
|
|
116
|
+
`sudo kubectl cp ${nameSpace}/${podName}:${sqlContainerPath} ${
|
|
117
|
+
options.outPath ? options.outPath : _toNewSqlPath
|
|
118
|
+
}`,
|
|
119
|
+
);
|
|
120
|
+
await splitFileFactory(dbName, options.outPath ? options.outPath : _toNewSqlPath);
|
|
121
|
+
}
|
|
93
122
|
}
|
|
94
123
|
break;
|
|
95
124
|
}
|
|
96
125
|
|
|
97
126
|
case 'mongoose': {
|
|
98
127
|
if (options.import === true) {
|
|
99
|
-
const
|
|
100
|
-
options.podName && typeof options.podName === 'string'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
128
|
+
const podNames =
|
|
129
|
+
options.podName && typeof options.podName === 'string'
|
|
130
|
+
? options.podName.split(',')
|
|
131
|
+
: UnderpostDeploy.API.get('mongo');
|
|
132
|
+
// `mongodb-0`;
|
|
133
|
+
for (const podNameData of [podNames[0]]) {
|
|
134
|
+
const podName = podNameData.NAME;
|
|
135
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}"`);
|
|
136
|
+
shellExec(
|
|
137
|
+
`sudo kubectl cp ${
|
|
138
|
+
options.outPath ? options.outPath : _toBsonPath
|
|
139
|
+
} ${nameSpace}/${podName}:/${dbName}`,
|
|
140
|
+
);
|
|
141
|
+
const cmd = `mongorestore -d ${dbName} /${dbName}${options.drop ? ' --drop' : ''}${
|
|
142
|
+
options.preserveUUID ? ' --preserveUUID' : ''
|
|
143
|
+
}`;
|
|
144
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
|
|
145
|
+
}
|
|
104
146
|
}
|
|
105
147
|
if (options.export === true) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
} else {
|
|
148
|
+
const podNames =
|
|
149
|
+
options.podName && typeof options.podName === 'string'
|
|
150
|
+
? options.podName.split(',')
|
|
151
|
+
: UnderpostDeploy.API.get('mongo'); // `backup-access`;
|
|
152
|
+
for (const podNameData of [podNames[0]]) {
|
|
153
|
+
const podName = podNameData.NAME;
|
|
154
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}"`);
|
|
155
|
+
if (options.collections)
|
|
156
|
+
for (const collection of options.collections)
|
|
157
|
+
shellExec(
|
|
158
|
+
`sudo kubectl exec -i ${podName} -- sh -c "mongodump -d ${dbName} --collection ${collection} -o /${dbName}"`,
|
|
159
|
+
);
|
|
160
|
+
else shellExec(`sudo kubectl exec -i ${podName} -- sh -c "mongodump -d ${dbName} -o /${dbName}"`);
|
|
120
161
|
shellExec(
|
|
121
|
-
`sudo kubectl cp ${nameSpace}/${podName}
|
|
162
|
+
`sudo kubectl cp ${nameSpace}/${podName}:/${dbName} ${
|
|
163
|
+
options.outPath ? options.outPath : _toNewBsonPath
|
|
164
|
+
}`,
|
|
122
165
|
);
|
|
123
166
|
}
|
|
167
|
+
if (false) {
|
|
168
|
+
const containerBaseBackupPath = '/backup';
|
|
169
|
+
let timeFolder = shellExec(
|
|
170
|
+
`sudo kubectl exec -i ${podName} -- sh -c "cd ${containerBaseBackupPath} && ls -a"`,
|
|
171
|
+
{
|
|
172
|
+
stdout: true,
|
|
173
|
+
disableLog: false,
|
|
174
|
+
silent: true,
|
|
175
|
+
},
|
|
176
|
+
).split(`\n`);
|
|
177
|
+
timeFolder = timeFolder[timeFolder.length - 2];
|
|
178
|
+
if (timeFolder === '..') {
|
|
179
|
+
logger.warn(`Cannot backup available`, { timeFolder });
|
|
180
|
+
} else {
|
|
181
|
+
shellExec(
|
|
182
|
+
`sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
124
186
|
}
|
|
125
187
|
break;
|
|
126
188
|
}
|
|
@@ -131,7 +193,7 @@ class UnderpostDB {
|
|
|
131
193
|
}
|
|
132
194
|
}
|
|
133
195
|
}
|
|
134
|
-
if (options.export === true) {
|
|
196
|
+
if (options.export === true && options.git === true) {
|
|
135
197
|
shellExec(`cd ../${repoName} && git add .`);
|
|
136
198
|
shellExec(
|
|
137
199
|
`underpost cmt ../${repoName} backup '' '${new Date(newBackupTimestamp).toLocaleDateString()} ${new Date(
|
package/src/cli/deploy.js
CHANGED
|
@@ -32,7 +32,7 @@ class UnderpostDeploy {
|
|
|
32
32
|
await Config.build(undefined, 'proxy', deployList);
|
|
33
33
|
return buildPortProxyRouter(env === 'development' ? 80 : 443, buildProxyRouter());
|
|
34
34
|
},
|
|
35
|
-
async buildManifest(deployList, env) {
|
|
35
|
+
async buildManifest(deployList, env, version) {
|
|
36
36
|
for (const _deployId of deployList.split(',')) {
|
|
37
37
|
const deployId = _deployId.trim();
|
|
38
38
|
if (!deployId) continue;
|
|
@@ -69,7 +69,18 @@ spec:
|
|
|
69
69
|
spec:
|
|
70
70
|
containers:
|
|
71
71
|
- name: ${deployId}-${env}
|
|
72
|
-
image: localhost
|
|
72
|
+
image: localhost/underpost-engine:${version && typeof version === 'string' ? version : Underpost.version}
|
|
73
|
+
lifecycle:
|
|
74
|
+
postStart:
|
|
75
|
+
exec:
|
|
76
|
+
command:
|
|
77
|
+
- /bin/sh
|
|
78
|
+
- -c
|
|
79
|
+
- >
|
|
80
|
+
sleep 60 &&
|
|
81
|
+
underpost config set deploy-id ${deployId} &&
|
|
82
|
+
underpost config set deploy-env ${env}
|
|
83
|
+
# image: localhost/${deployId}-${env}:${version && typeof version === 'string' ? version : Underpost.version}
|
|
73
84
|
---
|
|
74
85
|
apiVersion: v1
|
|
75
86
|
kind: Service
|
|
@@ -180,7 +191,16 @@ spec:
|
|
|
180
191
|
async callback(
|
|
181
192
|
deployList = 'default',
|
|
182
193
|
env = 'development',
|
|
183
|
-
options = {
|
|
194
|
+
options = {
|
|
195
|
+
remove: false,
|
|
196
|
+
infoRouter: false,
|
|
197
|
+
sync: false,
|
|
198
|
+
buildManifest: false,
|
|
199
|
+
infoUtil: false,
|
|
200
|
+
expose: false,
|
|
201
|
+
cert: false,
|
|
202
|
+
version: '',
|
|
203
|
+
},
|
|
184
204
|
) {
|
|
185
205
|
if (options.infoUtil === true)
|
|
186
206
|
return logger.info(`
|
|
@@ -191,7 +211,7 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
191
211
|
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
192
212
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
193
213
|
if (options.sync) UnderpostDeploy.API.sync(deployList);
|
|
194
|
-
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env);
|
|
214
|
+
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env, options.version);
|
|
195
215
|
if (options.infoRouter === true)
|
|
196
216
|
return logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
|
|
197
217
|
const etcHost = (
|
|
@@ -219,7 +239,7 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
219
239
|
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
220
240
|
for (const host of Object.keys(confServer)) {
|
|
221
241
|
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
222
|
-
if (env === 'production') shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
242
|
+
if (env === 'production' && options.cert === true) shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
223
243
|
if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
|
|
224
244
|
}
|
|
225
245
|
|
|
@@ -231,7 +251,8 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
231
251
|
if (!options.remove === true) {
|
|
232
252
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
|
|
233
253
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml`);
|
|
234
|
-
if (env === 'production'
|
|
254
|
+
if (env === 'production' && options.cert === true)
|
|
255
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
|
|
235
256
|
}
|
|
236
257
|
}
|
|
237
258
|
let renderHosts;
|
package/src/cli/fs.js
CHANGED
|
@@ -38,23 +38,36 @@ class UnderpostFileStorage {
|
|
|
38
38
|
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false },
|
|
39
39
|
) {
|
|
40
40
|
const { storage, storageConf } = UnderpostFileStorage.API.getStorageConf(options);
|
|
41
|
+
const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
|
|
42
|
+
for (const relativePath of deleteFiles) {
|
|
43
|
+
const _path = path + '/' + relativePath;
|
|
44
|
+
if (_path in storage) {
|
|
45
|
+
await UnderpostFileStorage.API.delete(_path);
|
|
46
|
+
delete storage[_path];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
41
49
|
const files =
|
|
42
50
|
options.git === true
|
|
43
51
|
? UnderpostRepository.API.getChangedFiles(path)
|
|
44
52
|
: await fs.readdir(path, { recursive: true });
|
|
45
|
-
|
|
46
|
-
const _path
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
if (options.pull === true) {
|
|
54
|
+
for (const _path of Object.keys(storage)) {
|
|
55
|
+
if (!fs.existsSync(_path) || options.force === true) {
|
|
56
|
+
if (options.force === true && fs.existsSync(_path)) fs.removeSync(_path);
|
|
57
|
+
await UnderpostFileStorage.API.pull(_path, options);
|
|
58
|
+
} else logger.warn(`Pull path already exists`, _path);
|
|
59
|
+
}
|
|
60
|
+
} else
|
|
61
|
+
for (const relativePath of files) {
|
|
62
|
+
const _path = path + '/' + relativePath;
|
|
63
|
+
if (fs.statSync(_path).isDirectory()) {
|
|
64
|
+
if (options.pull === true && !fs.existsSync(_path)) fs.mkdirSync(_path, { recursive: true });
|
|
65
|
+
continue;
|
|
66
|
+
} else if (!(_path in storage) || options.force === true) {
|
|
67
|
+
await UnderpostFileStorage.API.upload(_path, options);
|
|
68
|
+
if (storage) storage[_path] = {};
|
|
69
|
+
} else logger.warn('File already exists', _path);
|
|
50
70
|
}
|
|
51
|
-
if (options.pull === true) {
|
|
52
|
-
await UnderpostFileStorage.API.pull(_path, options);
|
|
53
|
-
} else if (!(_path in storage) || options.force === true) {
|
|
54
|
-
await UnderpostFileStorage.API.upload(_path, options);
|
|
55
|
-
if (storage) storage[_path] = {};
|
|
56
|
-
} else logger.warn('File already exists', _path);
|
|
57
|
-
}
|
|
58
71
|
UnderpostFileStorage.API.writeStorageConf(storage, storageConf);
|
|
59
72
|
if (options.git === true) {
|
|
60
73
|
shellExec(`cd ${path} && git add .`);
|
|
@@ -91,6 +104,8 @@ class UnderpostFileStorage {
|
|
|
91
104
|
},
|
|
92
105
|
async pull(path) {
|
|
93
106
|
UnderpostFileStorage.API.cloudinaryConfig();
|
|
107
|
+
const folder = dir.dirname(path);
|
|
108
|
+
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
94
109
|
const downloadResult = await cloudinary.utils.download_archive_url({
|
|
95
110
|
public_ids: [path],
|
|
96
111
|
resource_type: 'raw',
|
package/src/cli/image.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import Underpost from '../index.js';
|
|
3
|
-
import { shellExec } from '../server/process.js';
|
|
3
|
+
import { shellCd, shellExec } from '../server/process.js';
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
5
|
import { getNpmRootPath } from '../server/conf.js';
|
|
6
6
|
import { timer } from '../client/components/core/CommonJs.js';
|
|
7
|
+
import UnderpostRootEnv from './env.js';
|
|
7
8
|
|
|
8
9
|
dotenv.config();
|
|
9
10
|
|
|
@@ -17,9 +18,13 @@ class UnderpostImage {
|
|
|
17
18
|
deployId = 'default',
|
|
18
19
|
env = 'development',
|
|
19
20
|
path = '.',
|
|
20
|
-
options = { imageArchive: false, podmanSave: false },
|
|
21
|
+
options = { imageArchive: false, podmanSave: false, imageName: '', imageVersion: '' },
|
|
21
22
|
) {
|
|
22
|
-
const imgName = `${
|
|
23
|
+
const imgName = `${
|
|
24
|
+
options.imageName && typeof options.imageName === 'string' ? options.imageName : `${deployId}-${env}`
|
|
25
|
+
}:${
|
|
26
|
+
options.imageVersion && typeof options.imageVersions === 'string' ? options.imageVersion : Underpost.version
|
|
27
|
+
}`;
|
|
23
28
|
const podManImg = `localhost/${imgName}`;
|
|
24
29
|
const imagesStoragePath = `/images`;
|
|
25
30
|
if (!fs.existsSync(`${path}${imagesStoragePath}`))
|
|
@@ -48,7 +53,34 @@ class UnderpostImage {
|
|
|
48
53
|
shellExec(`cd ${path} && podman save -o ${tarFile} ${podManImg}`);
|
|
49
54
|
shellExec(`cd ${path} && sudo kind load image-archive ${tarFile}`);
|
|
50
55
|
},
|
|
51
|
-
async script(deployId = 'default', env = 'development', options = { run: false }) {
|
|
56
|
+
async script(deployId = 'default', env = 'development', options = { run: false, build: false }) {
|
|
57
|
+
if (deployId === 'deploy') {
|
|
58
|
+
const _deployId = UnderpostRootEnv.API.get('deploy-id');
|
|
59
|
+
const _env = UnderpostRootEnv.API.get('deploy-env');
|
|
60
|
+
const _path = UnderpostRootEnv.API.get('deploy-path');
|
|
61
|
+
if (_deployId) {
|
|
62
|
+
deployId = _deployId;
|
|
63
|
+
if (_env) env = _env;
|
|
64
|
+
if (_path) path = _path;
|
|
65
|
+
} else {
|
|
66
|
+
await timer(30 * 1000);
|
|
67
|
+
return await UnderpostImage.API.script(deployId, env, path, options);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (options.build === true) {
|
|
71
|
+
const buildBasePath = `/home/dd`;
|
|
72
|
+
const repoName = `engine-${deployId.split('-')[1]}`;
|
|
73
|
+
fs.mkdirSync(buildBasePath, { recursive: true });
|
|
74
|
+
shellExec(`cd ${buildBasePath} && underpost clone underpostnet/${repoName}`);
|
|
75
|
+
shellExec(`cd ${buildBasePath} && sudo mv ./${repoName} ./engine`);
|
|
76
|
+
shellExec(`cd ${buildBasePath}/engine && underpost clone underpostnet/${repoName}-private`);
|
|
77
|
+
shellExec(`cd ${buildBasePath}/engine && sudo mv ./${repoName}-private ./engine-private`);
|
|
78
|
+
shellCd(`${buildBasePath}/engine`);
|
|
79
|
+
shellExec(`npm install`);
|
|
80
|
+
const itcScripts = fs.readdir('./engine-private/itc-scripts');
|
|
81
|
+
for (const itcScript of itcScripts)
|
|
82
|
+
if (itcScript.match(deployId)) shellExec(`node ./engine-private/itc-scripts/${itcScript}`);
|
|
83
|
+
}
|
|
52
84
|
switch (deployId) {
|
|
53
85
|
case 'dd-lampp':
|
|
54
86
|
{
|
package/src/cli/repository.js
CHANGED
|
@@ -99,17 +99,25 @@ class UnderpostRepository {
|
|
|
99
99
|
});
|
|
100
100
|
},
|
|
101
101
|
|
|
102
|
+
getDeleteFiles(path = '.') {
|
|
103
|
+
const commandUntrack = `cd ${path} && git ls-files --deleted`;
|
|
104
|
+
const diffUntrackOutput = shellExec(commandUntrack, { stdout: true, silent: true });
|
|
105
|
+
return diffUntrackOutput.toString().split('\n').filter(Boolean);
|
|
106
|
+
},
|
|
107
|
+
|
|
102
108
|
getChangedFiles(path = '.', extension = '', head = false) {
|
|
103
109
|
const extensionFilter = extension ? `-- '***.${extension}'` : '';
|
|
104
110
|
const command = `cd ${path} && git diff ${head ? 'HEAD^ HEAD ' : ''}--name-only ${extensionFilter}`;
|
|
105
111
|
const commandUntrack = `cd ${path} && git ls-files --others --exclude-standard`;
|
|
106
112
|
const diffOutput = shellExec(command, { stdout: true, silent: true });
|
|
107
113
|
const diffUntrackOutput = shellExec(commandUntrack, { stdout: true, silent: true });
|
|
114
|
+
const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
|
|
108
115
|
return diffOutput
|
|
109
116
|
.toString()
|
|
110
117
|
.split('\n')
|
|
111
118
|
.filter(Boolean)
|
|
112
|
-
.concat(diffUntrackOutput.toString().split('\n').filter(Boolean))
|
|
119
|
+
.concat(diffUntrackOutput.toString().split('\n').filter(Boolean))
|
|
120
|
+
.filter((f) => !deleteFiles.includes(f));
|
|
113
121
|
},
|
|
114
122
|
};
|
|
115
123
|
}
|
|
@@ -404,7 +404,15 @@ const CalendarCore = {
|
|
|
404
404
|
<div class="in" style="margin-bottom: 100px"></div>`;
|
|
405
405
|
};
|
|
406
406
|
|
|
407
|
+
let delayBlock = false;
|
|
407
408
|
this.Data[options.idModal].updatePanel = async () => {
|
|
409
|
+
if (delayBlock) return;
|
|
410
|
+
else {
|
|
411
|
+
delayBlock = true;
|
|
412
|
+
setTimeout(() => {
|
|
413
|
+
delayBlock = false;
|
|
414
|
+
}, 500);
|
|
415
|
+
}
|
|
408
416
|
const cid = getQueryParams().cid ? getQueryParams().cid : '';
|
|
409
417
|
if (options.route === 'home') Modal.homeCid = newInstance(cid);
|
|
410
418
|
if (s(`.main-body-calendar-${options.idModal}`)) {
|
|
@@ -426,7 +434,10 @@ const CalendarCore = {
|
|
|
426
434
|
},
|
|
427
435
|
});
|
|
428
436
|
|
|
429
|
-
if (options.route === 'home')
|
|
437
|
+
// if (options.route === 'home')
|
|
438
|
+
setTimeout(() => {
|
|
439
|
+
CalendarCore.Data[options.idModal].updatePanel();
|
|
440
|
+
});
|
|
430
441
|
|
|
431
442
|
return html`
|
|
432
443
|
<style>
|
|
@@ -890,8 +890,58 @@ const commitData = {
|
|
|
890
890
|
},
|
|
891
891
|
};
|
|
892
892
|
|
|
893
|
-
const
|
|
893
|
+
const emotionsData = [
|
|
894
|
+
{
|
|
895
|
+
name: 'like',
|
|
896
|
+
ad_display: {
|
|
897
|
+
es: 'Me gusta',
|
|
898
|
+
en: 'Like',
|
|
899
|
+
},
|
|
900
|
+
emoji: '👍',
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
name: 'love',
|
|
904
|
+
ad_display: {
|
|
905
|
+
es: 'Me encanta',
|
|
906
|
+
en: 'Love',
|
|
907
|
+
},
|
|
908
|
+
emoji: '❤️',
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: 'haha',
|
|
912
|
+
ad_display: {
|
|
913
|
+
es: 'Me divierte',
|
|
914
|
+
en: 'Haha',
|
|
915
|
+
},
|
|
916
|
+
emoji: '😂',
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
name: 'wow',
|
|
920
|
+
ad_display: {
|
|
921
|
+
es: 'Me asombra',
|
|
922
|
+
en: 'Wow',
|
|
923
|
+
},
|
|
924
|
+
emoji: '😮',
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
name: 'sad',
|
|
928
|
+
ad_display: {
|
|
929
|
+
es: 'Me entristece',
|
|
930
|
+
en: 'Sad',
|
|
931
|
+
},
|
|
932
|
+
emoji: '😢',
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
name: 'angry',
|
|
936
|
+
ad_display: {
|
|
937
|
+
es: 'Me enoja',
|
|
938
|
+
en: 'Angry',
|
|
939
|
+
},
|
|
940
|
+
emoji: '😠',
|
|
941
|
+
},
|
|
942
|
+
];
|
|
894
943
|
|
|
944
|
+
const userRoleEnum = ['admin', 'moderator', 'user', 'guest'];
|
|
895
945
|
const commonAdminGuard = (role) => userRoleEnum.indexOf(role) === userRoleEnum.indexOf('admin');
|
|
896
946
|
const commonModeratorGuard = (role) => userRoleEnum.indexOf(role) <= userRoleEnum.indexOf('moderator');
|
|
897
947
|
|
|
@@ -954,4 +1004,5 @@ export {
|
|
|
954
1004
|
getCurrentTrace,
|
|
955
1005
|
userRoleEnum,
|
|
956
1006
|
commitData,
|
|
1007
|
+
emotionsData,
|
|
957
1008
|
};
|
|
@@ -396,8 +396,7 @@ const CssCoreDark = {
|
|
|
396
396
|
text-align: center;
|
|
397
397
|
background: #1a1a1a;
|
|
398
398
|
font-size: 17px;
|
|
399
|
-
|
|
400
|
-
padding-bottom: 6px;
|
|
399
|
+
height: 35px;
|
|
401
400
|
}
|
|
402
401
|
::placeholder {
|
|
403
402
|
color: #c6c4c4;
|
|
@@ -701,8 +700,7 @@ const CssCoreLight = {
|
|
|
701
700
|
text-align: center;
|
|
702
701
|
background: #eaeaea;
|
|
703
702
|
font-size: 17px;
|
|
704
|
-
|
|
705
|
-
padding-bottom: 6px;
|
|
703
|
+
height: 35px;
|
|
706
704
|
}
|
|
707
705
|
::placeholder {
|
|
708
706
|
color: #333;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _VERSION, CoreService } from '../../services/core/core.service.js';
|
|
2
1
|
import { Badge } from './Badge.js';
|
|
3
2
|
import { BtnIcon } from './BtnIcon.js';
|
|
4
3
|
import { rgbToHex } from './CommonJs.js';
|
|
@@ -80,7 +79,7 @@ const Docs = {
|
|
|
80
79
|
icon: html`<i class="fa-brands fa-osi"></i>`,
|
|
81
80
|
text: 'Source Docs',
|
|
82
81
|
url: function () {
|
|
83
|
-
return `${getProxyPath()}docs/engine/${
|
|
82
|
+
return `${getProxyPath()}docs/engine/${window.renderPayload.version}`;
|
|
84
83
|
},
|
|
85
84
|
},
|
|
86
85
|
{
|
|
@@ -88,8 +88,10 @@ const Input = {
|
|
|
88
88
|
<div class="fl input-row-${id}">
|
|
89
89
|
<div class="in fll" style="width: 80%;">${inputElement}</div>
|
|
90
90
|
<div class="in fll btn-eye-password btn-eye-${id}" style="width: 20%;">
|
|
91
|
-
<
|
|
92
|
-
|
|
91
|
+
<div class="abs center">
|
|
92
|
+
<i class="fas fa-eye fa-eye-${id} eye-password"></i>
|
|
93
|
+
<i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
|
|
94
|
+
</div>
|
|
93
95
|
</div>
|
|
94
96
|
</div>
|
|
95
97
|
`
|
|
@@ -75,12 +75,17 @@ const LoadingAnimation = {
|
|
|
75
75
|
const style = {
|
|
76
76
|
'text-align': 'center',
|
|
77
77
|
};
|
|
78
|
-
|
|
79
78
|
if (s(container).classList) {
|
|
80
79
|
const classes = Array.from(s(container).classList);
|
|
81
80
|
if (classes.find((e) => e.match('management-table-btn-mini'))) {
|
|
82
81
|
style.top = '-2px';
|
|
83
82
|
style.left = '-2px';
|
|
83
|
+
} else if (classes.find((e) => e.match('-btn-tool'))) {
|
|
84
|
+
style.top = '-26px';
|
|
85
|
+
style.left = '-10px';
|
|
86
|
+
} else if (classes.find((e) => e.match('main-btn-')) && !classes.find((e) => e.match('main-btn-square-menu'))) {
|
|
87
|
+
style.top = '-8px';
|
|
88
|
+
style.left = '-10px';
|
|
84
89
|
} else if (classes.find((e) => e.match('action-bar-box'))) {
|
|
85
90
|
style.top = '-30px';
|
|
86
91
|
style.left = '-12px';
|
|
@@ -145,6 +150,8 @@ const LoadingAnimation = {
|
|
|
145
150
|
s(backgroundContainer).style.opacity = 0;
|
|
146
151
|
setTimeout(async () => {
|
|
147
152
|
s(backgroundContainer).style.display = 'none';
|
|
153
|
+
if (s(`.modal-menu`)) s(`.modal-menu`).classList.remove('hide');
|
|
154
|
+
if (s(`.main-body-btn-container`)) s(`.main-body-btn-container`).classList.remove('hide');
|
|
148
155
|
if (callBack) callBack();
|
|
149
156
|
}, 300);
|
|
150
157
|
});
|
|
@@ -49,6 +49,7 @@ const Modal = {
|
|
|
49
49
|
mode: '' /* slide-menu */,
|
|
50
50
|
RouterInstance: {},
|
|
51
51
|
disableTools: [],
|
|
52
|
+
observer: false,
|
|
52
53
|
},
|
|
53
54
|
) {
|
|
54
55
|
if (options.heightBottomBar === undefined) options.heightBottomBar = 50;
|
|
@@ -76,6 +77,8 @@ const Modal = {
|
|
|
76
77
|
options,
|
|
77
78
|
onCloseListener: {},
|
|
78
79
|
onMenuListener: {},
|
|
80
|
+
onCollapseMenuListener: {},
|
|
81
|
+
onExtendMenuListener: {},
|
|
79
82
|
onDragEndListener: {},
|
|
80
83
|
onObserverListener: {},
|
|
81
84
|
onClickListener: {},
|
|
@@ -156,7 +159,8 @@ const Modal = {
|
|
|
156
159
|
};
|
|
157
160
|
options.mode === 'slide-menu-right' ? (options.style.right = '0px') : (options.style.left = '0px');
|
|
158
161
|
const contentIconClass = 'abs center';
|
|
159
|
-
|
|
162
|
+
if (options.class) options.class += ' hide';
|
|
163
|
+
else options.class = 'hide';
|
|
160
164
|
options.dragDisabled = true;
|
|
161
165
|
options.titleClass = 'hide';
|
|
162
166
|
top = '0px';
|
|
@@ -238,7 +242,7 @@ const Modal = {
|
|
|
238
242
|
'body',
|
|
239
243
|
html`
|
|
240
244
|
<div
|
|
241
|
-
class="abs main-body-btn-container"
|
|
245
|
+
class="abs main-body-btn-container hide"
|
|
242
246
|
style="top: ${options.heightTopBar + 50}px; z-index: 9; ${true ||
|
|
243
247
|
(options.mode && options.mode.match('right'))
|
|
244
248
|
? 'right'
|
|
@@ -1383,6 +1387,9 @@ const Modal = {
|
|
|
1383
1387
|
if (options.onCollapseMenu) options.onCollapseMenu();
|
|
1384
1388
|
s(`.sub-menu-title-container-${'modal-menu'}`).classList.add('hide');
|
|
1385
1389
|
s(`.nav-path-container-${'modal-menu'}`).classList.add('hide');
|
|
1390
|
+
Object.keys(this.Data[idModal].onCollapseMenuListener).map((keyListener) =>
|
|
1391
|
+
this.Data[idModal].onCollapseMenuListener[keyListener](),
|
|
1392
|
+
);
|
|
1386
1393
|
} else {
|
|
1387
1394
|
slideMenuWidth = originSlideMenuWidth;
|
|
1388
1395
|
setTimeout(() => {
|
|
@@ -1403,6 +1410,9 @@ const Modal = {
|
|
|
1403
1410
|
if (options.onExtendMenu) options.onExtendMenu();
|
|
1404
1411
|
s(`.sub-menu-title-container-${'modal-menu'}`).classList.remove('hide');
|
|
1405
1412
|
s(`.nav-path-container-${'modal-menu'}`).classList.remove('hide');
|
|
1413
|
+
Object.keys(this.Data[idModal].onExtendMenuListener).map((keyListener) =>
|
|
1414
|
+
this.Data[idModal].onExtendMenuListener[keyListener](),
|
|
1415
|
+
);
|
|
1406
1416
|
}
|
|
1407
1417
|
// btn-bar-center-icon-menu
|
|
1408
1418
|
this.actionBtnCenter();
|
|
@@ -1781,20 +1791,34 @@ const renderMenuLabel = ({ img, text, icon }) => {
|
|
|
1781
1791
|
<div class="abs center main-btn-menu-text">${text}</div>`;
|
|
1782
1792
|
};
|
|
1783
1793
|
|
|
1784
|
-
const renderViewTitle = (
|
|
1785
|
-
|
|
1794
|
+
const renderViewTitle = (
|
|
1795
|
+
options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top, topText: '' },
|
|
1796
|
+
) => {
|
|
1797
|
+
if (options.dim === undefined) options.dim = 30;
|
|
1786
1798
|
const { img, text, icon, dim, top } = options;
|
|
1787
1799
|
if (!img && !options['ui-icon']) return html`<span class="view-title-icon">${icon}</span> ${text}`;
|
|
1788
1800
|
return html`<img
|
|
1789
1801
|
class="abs img-btn-square-view-title"
|
|
1790
1802
|
style="${renderCssAttr({
|
|
1791
|
-
style: {
|
|
1803
|
+
style: {
|
|
1804
|
+
width: `${dim}px`,
|
|
1805
|
+
height: `${dim}px`,
|
|
1806
|
+
top: top !== undefined ? `${top}px !important` : undefined,
|
|
1807
|
+
},
|
|
1792
1808
|
})}"
|
|
1793
1809
|
src="${options['ui-icon']
|
|
1794
1810
|
? `${getProxyPath()}assets/${options.assetFolder ? options.assetFolder : 'ui-icons'}/${options['ui-icon']}`
|
|
1795
1811
|
: img}"
|
|
1796
1812
|
/>
|
|
1797
|
-
<div
|
|
1813
|
+
<div
|
|
1814
|
+
class="in text-btn-square-view-title"
|
|
1815
|
+
style="${renderCssAttr({
|
|
1816
|
+
style: {
|
|
1817
|
+
// 'padding-left': `${20 + dim}px`,
|
|
1818
|
+
...(options.topText !== undefined ? { top: options.topText + 'px !important' } : {}),
|
|
1819
|
+
},
|
|
1820
|
+
})}"
|
|
1821
|
+
>
|
|
1798
1822
|
${text}
|
|
1799
1823
|
</div>`;
|
|
1800
1824
|
};
|
|
@@ -26,6 +26,7 @@ const Panel = {
|
|
|
26
26
|
idPanel: '',
|
|
27
27
|
parentIdModal: '',
|
|
28
28
|
scrollClassContainer: '',
|
|
29
|
+
htmlFormHeader: async () => '',
|
|
29
30
|
formData: [],
|
|
30
31
|
data: [],
|
|
31
32
|
originData: () => [],
|
|
@@ -244,12 +245,13 @@ const Panel = {
|
|
|
244
245
|
|
|
245
246
|
let render = '';
|
|
246
247
|
let renderForm = html` <div class="in modal stq" style="top: 0px; z-index: 1; padding-bottom: 5px">
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
${await BtnIcon.Render({
|
|
249
|
+
class: `section-mp btn-custom btn-${idPanel}-close`,
|
|
250
|
+
label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
|
|
251
|
+
type: 'button',
|
|
252
|
+
})}
|
|
253
|
+
</div>
|
|
254
|
+
${options?.htmlFormHeader ? await options.htmlFormHeader() : ''}`;
|
|
253
255
|
|
|
254
256
|
for (const modelData of formData) {
|
|
255
257
|
if (modelData.disableRender) continue;
|
|
@@ -29,6 +29,8 @@ const PanelForm = {
|
|
|
29
29
|
Elements: {},
|
|
30
30
|
parentIdModal: undefined,
|
|
31
31
|
route: 'home',
|
|
32
|
+
htmlFormHeader: async () => '',
|
|
33
|
+
firsUpdateEvent: async () => {},
|
|
32
34
|
},
|
|
33
35
|
) {
|
|
34
36
|
const { idPanel, heightTopBar, heightBottomBar, defaultUrlImage, Elements } = options;
|
|
@@ -99,6 +101,7 @@ const PanelForm = {
|
|
|
99
101
|
heightTopBar,
|
|
100
102
|
heightBottomBar,
|
|
101
103
|
data,
|
|
104
|
+
htmlFormHeader: options.htmlFormHeader,
|
|
102
105
|
parentIdModal: options.parentIdModal,
|
|
103
106
|
originData: () => PanelForm.Data[idPanel].originData,
|
|
104
107
|
filesData: () => PanelForm.Data[idPanel].filesData,
|
|
@@ -421,8 +424,16 @@ const PanelForm = {
|
|
|
421
424
|
ssr: true,
|
|
422
425
|
})),
|
|
423
426
|
});
|
|
424
|
-
|
|
427
|
+
let delayBlock = false;
|
|
428
|
+
let firsUpdateEvent = false;
|
|
425
429
|
this.Data[idPanel].updatePanel = async () => {
|
|
430
|
+
if (delayBlock) return;
|
|
431
|
+
else {
|
|
432
|
+
delayBlock = true;
|
|
433
|
+
setTimeout(() => {
|
|
434
|
+
delayBlock = false;
|
|
435
|
+
}, 500);
|
|
436
|
+
}
|
|
426
437
|
const cid = getQueryParams().cid ? getQueryParams().cid : '';
|
|
427
438
|
if (options.route === 'home') Modal.homeCid = newInstance(cid);
|
|
428
439
|
htmls(`.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`, await renderSrrPanelData());
|
|
@@ -431,23 +442,28 @@ const PanelForm = {
|
|
|
431
442
|
`.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`,
|
|
432
443
|
await panelRender({ data: this.Data[idPanel].data }),
|
|
433
444
|
);
|
|
445
|
+
if (!firsUpdateEvent && options.firsUpdateEvent) {
|
|
446
|
+
firsUpdateEvent = true;
|
|
447
|
+
await options.firsUpdateEvent();
|
|
448
|
+
}
|
|
434
449
|
};
|
|
435
450
|
if (options.route)
|
|
436
451
|
listenQueryPathInstance({
|
|
437
452
|
id: options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body',
|
|
438
453
|
routeId: options.route,
|
|
439
454
|
event: async (path) => {
|
|
440
|
-
if (!PanelForm.Data[idPanel].sessionIn)
|
|
455
|
+
// if (!PanelForm.Data[idPanel].sessionIn)
|
|
456
|
+
await this.Data[idPanel].updatePanel();
|
|
441
457
|
},
|
|
442
458
|
});
|
|
443
459
|
|
|
444
460
|
// if (options.route === 'home') setTimeout(this.Data[idPanel].updatePanel);
|
|
445
461
|
setTimeout(() => {
|
|
446
|
-
if (
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
)
|
|
450
|
-
|
|
462
|
+
// if (
|
|
463
|
+
// options.route !== 'home' &&
|
|
464
|
+
// (!PanelForm.Data[idPanel].originData || PanelForm.Data[idPanel].originData.length === 0)
|
|
465
|
+
// )
|
|
466
|
+
this.Data[idPanel].updatePanel();
|
|
451
467
|
});
|
|
452
468
|
|
|
453
469
|
if (options.parentIdModal) {
|
|
@@ -4,13 +4,24 @@ import { getProxyPath } from '../../components/core/VanillaJs.js';
|
|
|
4
4
|
|
|
5
5
|
const logger = loggerFactory(import.meta);
|
|
6
6
|
|
|
7
|
+
logger.info('Load service');
|
|
8
|
+
|
|
9
|
+
const endpoint = 'core';
|
|
10
|
+
|
|
7
11
|
// https://developer.mozilla.org/en-US/docs/Web/API/AbortController
|
|
8
|
-
const getBaseHost = () => location.host;
|
|
12
|
+
const getBaseHost = () => (window.renderPayload?.apiBaseHost ? window.renderPayload.apiBaseHost : location.host);
|
|
9
13
|
|
|
10
|
-
const getApiBasePath = () =>
|
|
14
|
+
const getApiBasePath = (options) =>
|
|
15
|
+
`${
|
|
16
|
+
options?.proxyPath
|
|
17
|
+
? `/${options.proxyPath}/`
|
|
18
|
+
: window.renderPayload?.apiBaseProxyPath
|
|
19
|
+
? window.renderPayload.apiBaseProxyPath
|
|
20
|
+
: getProxyPath()
|
|
21
|
+
}${window.renderPayload?.apiBasePath ? window.renderPayload.apiBasePath : 'api'}/`;
|
|
11
22
|
|
|
12
|
-
const getApiBaseUrl = (options = { id: '', endpoint: '' }) =>
|
|
13
|
-
`${location.protocol}//${getBaseHost()}${getApiBasePath()}${options?.endpoint ? options.endpoint : ''}${
|
|
23
|
+
const getApiBaseUrl = (options = { id: '', endpoint: '', proxyPath: '' }) =>
|
|
24
|
+
`${location.protocol}//${getBaseHost()}${getApiBasePath(options)}${options?.endpoint ? options.endpoint : ''}${
|
|
14
25
|
options?.id ? `/${options.id}` : ''
|
|
15
26
|
}`;
|
|
16
27
|
|
|
@@ -38,11 +49,6 @@ const payloadFactory = (body) => {
|
|
|
38
49
|
return JSON.stringify(body);
|
|
39
50
|
};
|
|
40
51
|
|
|
41
|
-
logger.info('Load service');
|
|
42
|
-
|
|
43
|
-
const endpoint = 'core';
|
|
44
|
-
const _VERSION = window._VERSION;
|
|
45
|
-
|
|
46
52
|
const CoreService = {
|
|
47
53
|
getRaw: (options = { url: '' }) =>
|
|
48
54
|
new Promise((resolve, reject) =>
|
|
@@ -159,7 +165,6 @@ const CoreService = {
|
|
|
159
165
|
const ApiBase = getApiBaseUrl;
|
|
160
166
|
|
|
161
167
|
export {
|
|
162
|
-
_VERSION,
|
|
163
168
|
CoreService,
|
|
164
169
|
headersFactory,
|
|
165
170
|
payloadFactory,
|
package/src/client/ssr/Render.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents }) => html`
|
|
1
|
+
SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents, renderPayload, renderApi }) => html`
|
|
2
2
|
<!DOCTYPE html>
|
|
3
3
|
<html dir="ltr" lang="en">
|
|
4
4
|
<head>
|
|
@@ -6,6 +6,9 @@ SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents
|
|
|
6
6
|
<link rel="icon" type="image/x-icon" href="${ssrPath}favicon.ico" />
|
|
7
7
|
<meta charset="UTF-8" />
|
|
8
8
|
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
|
9
|
+
<script>
|
|
10
|
+
window.renderPayload = ${renderApi.JSONweb(renderPayload)};
|
|
11
|
+
</script>
|
|
9
12
|
${ssrHeadComponents}
|
|
10
13
|
</head>
|
|
11
14
|
<body>
|
|
@@ -70,7 +70,7 @@ const CacheControl = function ({ ttiLoadTimeLimit }) {
|
|
|
70
70
|
setTimeout(window.cacheControlCallBack, ttiLoadTimeLimit); // 70s limit);
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
SrrComponent = ({ ttiLoadTimeLimit }) => {
|
|
73
|
+
SrrComponent = ({ ttiLoadTimeLimit, version }) => {
|
|
74
74
|
const borderChar = (px, color, selectors) => {
|
|
75
75
|
if (selectors) {
|
|
76
76
|
return selectors
|
|
@@ -106,10 +106,9 @@ SrrComponent = ({ ttiLoadTimeLimit }) => {
|
|
|
106
106
|
</style>
|
|
107
107
|
${borderChar(1, 'black', ['.clean-cache-container'])}
|
|
108
108
|
<script>
|
|
109
|
-
window._VERSION = '${npm_package_version}';
|
|
110
109
|
const CacheControl = ${CacheControl};
|
|
111
110
|
CacheControl({ ttiLoadTimeLimit: ${ttiLoadTimeLimit ? ttiLoadTimeLimit : 1000 * 70 * 1} });
|
|
112
111
|
</script>
|
|
113
|
-
<div class="clean-cache-container">${
|
|
112
|
+
<div class="clean-cache-container">${version}</div>
|
|
114
113
|
`;
|
|
115
114
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const PRE_CACHED_RESOURCES = [];
|
|
2
|
-
const CACHE_NAME = 'app-cache';
|
|
3
|
-
const PROXY_PATH = '/';
|
|
1
|
+
const PRE_CACHED_RESOURCES = self.renderPayload?.PRE_CACHED_RESOURCES ? self.renderPayload.PRE_CACHED_RESOURCES : [];
|
|
2
|
+
const CACHE_NAME = self.renderPayload?.CACHE_NAME ? self.renderPayload.CACHE_NAME : 'app-cache';
|
|
3
|
+
const PROXY_PATH = self.renderPayload?.PROXY_PATH ? self.renderPayload.PROXY_PATH : '/';
|
|
4
4
|
self.addEventListener('install', (event) => {
|
|
5
5
|
// Activate right away
|
|
6
6
|
self.skipWaiting();
|
package/src/index.js
CHANGED
package/src/server/backup.js
CHANGED
|
@@ -9,7 +9,7 @@ dotenv.config();
|
|
|
9
9
|
const logger = loggerFactory(import.meta);
|
|
10
10
|
|
|
11
11
|
class BackUp {
|
|
12
|
-
static callback = async function (deployList, options = { itc: false }) {
|
|
12
|
+
static callback = async function (deployList, options = { itc: false, git: false }) {
|
|
13
13
|
if ((!deployList || deployList === 'dd') && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
14
14
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
15
15
|
|
|
@@ -26,7 +26,7 @@ class BackUp {
|
|
|
26
26
|
if (!deployId) continue;
|
|
27
27
|
|
|
28
28
|
if (!(options.itc === true)) {
|
|
29
|
-
shellExec(`
|
|
29
|
+
shellExec(`node bin db ${options.git ? '--git ' : ''}--export ${deployId}`);
|
|
30
30
|
continue;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -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
|
|
|
@@ -250,20 +251,6 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
250
251
|
'services',
|
|
251
252
|
baseHost,
|
|
252
253
|
);
|
|
253
|
-
if (module === 'core' && (process.env.NODE_ENV === 'production' || process.argv.includes('static'))) {
|
|
254
|
-
if (apiBaseHost)
|
|
255
|
-
jsSrc = jsSrc.replace(
|
|
256
|
-
'const getBaseHost = () => location.host;',
|
|
257
|
-
`const getBaseHost = () => '${apiBaseHost}';`,
|
|
258
|
-
);
|
|
259
|
-
if (apiBaseProxyPath) {
|
|
260
|
-
jsSrc = jsSrc.replace('${getProxyPath()}api/', `${apiBaseProxyPath}${process.env.BASE_API}/`);
|
|
261
|
-
jsSrc = jsSrc.replace(
|
|
262
|
-
"const getWsBasePath = () => (getProxyPath() !== '/' ? `${getProxyPath()}socket.io/` : undefined);",
|
|
263
|
-
`const getWsBasePath = () => '${apiBaseProxyPath}socket.io/';`,
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
254
|
fs.writeFileSync(
|
|
268
255
|
jsPublicPath,
|
|
269
256
|
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
@@ -487,7 +474,13 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
487
474
|
}
|
|
488
475
|
|
|
489
476
|
default:
|
|
490
|
-
ssrBodyComponents += SrrComponent({
|
|
477
|
+
ssrBodyComponents += SrrComponent({
|
|
478
|
+
ssrPath,
|
|
479
|
+
host,
|
|
480
|
+
path,
|
|
481
|
+
ttiLoadTimeLimit,
|
|
482
|
+
version: Underpost.version,
|
|
483
|
+
});
|
|
491
484
|
break;
|
|
492
485
|
}
|
|
493
486
|
}
|
|
@@ -507,6 +500,15 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
507
500
|
ssrPath,
|
|
508
501
|
ssrHeadComponents,
|
|
509
502
|
ssrBodyComponents,
|
|
503
|
+
renderPayload: {
|
|
504
|
+
apiBaseProxyPath,
|
|
505
|
+
apiBaseHost,
|
|
506
|
+
apiBasePath: process.env.BASE_API,
|
|
507
|
+
version: Underpost.version,
|
|
508
|
+
},
|
|
509
|
+
renderApi: {
|
|
510
|
+
JSONweb,
|
|
511
|
+
},
|
|
510
512
|
});
|
|
511
513
|
|
|
512
514
|
fs.writeFileSync(
|
|
@@ -707,6 +709,15 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
707
709
|
ssrPath,
|
|
708
710
|
ssrHeadComponents: '',
|
|
709
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
|
+
},
|
|
710
721
|
});
|
|
711
722
|
|
|
712
723
|
const buildPath = `${
|
|
@@ -739,16 +750,14 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
739
750
|
}
|
|
740
751
|
|
|
741
752
|
{
|
|
742
|
-
const
|
|
743
|
-
|
|
753
|
+
const renderPayload = {
|
|
754
|
+
PRE_CACHED_RESOURCES: uniqueArray(PRE_CACHED_RESOURCES),
|
|
755
|
+
PROXY_PATH: path,
|
|
756
|
+
};
|
|
744
757
|
fs.writeFileSync(
|
|
745
758
|
`${rootClientPath}/sw.js`,
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
.replaceAll(`PRE_CACHED_RESOURCES = []`, PRE_CACHED_JSON)
|
|
749
|
-
.replaceAll(`PRE_CACHED_RESOURCES=[]`, PRE_CACHED_JSON)
|
|
750
|
-
.replaceAll(`PROXY_PATH = '/'`, PROXY_PATH)
|
|
751
|
-
.replaceAll(`PROXY_PATH='/'`, PROXY_PATH),
|
|
759
|
+
`self.renderPayload = ${JSONweb(renderPayload)};
|
|
760
|
+
${fs.readFileSync(`${rootClientPath}/sw.js`, 'utf8')}`,
|
|
752
761
|
'utf8',
|
|
753
762
|
);
|
|
754
763
|
}
|
package/src/server/conf.js
CHANGED
|
@@ -996,7 +996,7 @@ const Cmd = {
|
|
|
996
996
|
cron: (deployList, jobList, name, expression, options) =>
|
|
997
997
|
`pm2 start ./bin/index.js --no-autorestart --instances 1 --cron "${expression}" --name ${name} -- cron ${
|
|
998
998
|
options?.itc ? `--itc ` : ''
|
|
999
|
-
}${deployList} ${jobList}`,
|
|
999
|
+
}${options?.git ? `--git ` : ''}${deployList} ${jobList}`,
|
|
1000
1000
|
};
|
|
1001
1001
|
|
|
1002
1002
|
const fixDependencies = async () => {
|
package/src/server/runtime.js
CHANGED
|
@@ -19,7 +19,8 @@ import { DataBaseProvider } from '../db/DataBaseProvider.js';
|
|
|
19
19
|
import { createPeerServer } from './peer.js';
|
|
20
20
|
import { Lampp } from '../runtime/lampp/Lampp.js';
|
|
21
21
|
import { getDeployId } from './conf.js';
|
|
22
|
-
import { ssrFactory } from './client-formatted.js';
|
|
22
|
+
import { JSONweb, ssrFactory } from './client-formatted.js';
|
|
23
|
+
import Underpost from '../index.js';
|
|
23
24
|
|
|
24
25
|
dotenv.config();
|
|
25
26
|
|
|
@@ -384,6 +385,13 @@ const buildRuntime = async () => {
|
|
|
384
385
|
ssrPath,
|
|
385
386
|
ssrHeadComponents: '',
|
|
386
387
|
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/404.js`))(),
|
|
388
|
+
renderPayload: {
|
|
389
|
+
apiBasePath: process.env.BASE_API,
|
|
390
|
+
version: Underpost.version,
|
|
391
|
+
},
|
|
392
|
+
renderApi: {
|
|
393
|
+
JSONweb,
|
|
394
|
+
},
|
|
387
395
|
});
|
|
388
396
|
const path404 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/404/index.html`;
|
|
389
397
|
const page404 = fs.existsSync(path404) ? `${path === '/' ? '' : path}/404` : undefined;
|
|
@@ -400,6 +408,13 @@ const buildRuntime = async () => {
|
|
|
400
408
|
ssrPath,
|
|
401
409
|
ssrHeadComponents: '',
|
|
402
410
|
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/body/500.js`))(),
|
|
411
|
+
renderPayload: {
|
|
412
|
+
apiBasePath: process.env.BASE_API,
|
|
413
|
+
version: Underpost.version,
|
|
414
|
+
},
|
|
415
|
+
renderApi: {
|
|
416
|
+
JSONweb,
|
|
417
|
+
},
|
|
403
418
|
});
|
|
404
419
|
const path500 = `${directory ? directory : `${getRootDirectory()}${rootHostPath}`}/500/index.html`;
|
|
405
420
|
const page500 = fs.existsSync(path500) ? `${path === '/' ? '' : path}/500` : undefined;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
apiVersion: v1
|
|
3
|
-
kind: Service
|
|
4
|
-
metadata:
|
|
5
|
-
name: service-valkey
|
|
6
|
-
namespace: default
|
|
7
|
-
spec:
|
|
8
|
-
ports:
|
|
9
|
-
- port: 6379
|
|
10
|
-
targetPort: 6379
|
|
11
|
-
selector:
|
|
12
|
-
app: service-valkey
|
|
13
|
-
ipFamilyPolicy: PreferDualStack
|
|
14
|
-
ipFamilies:
|
|
15
|
-
- IPv4
|
|
16
|
-
# - IPv6
|
|
17
|
-
type: ClusterIP
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
apiVersion: apps/v1
|
|
3
|
-
kind: StatefulSet
|
|
4
|
-
metadata:
|
|
5
|
-
name: service-valkey
|
|
6
|
-
namespace: default
|
|
7
|
-
spec:
|
|
8
|
-
serviceName: service-valkey
|
|
9
|
-
replicas: 1
|
|
10
|
-
selector:
|
|
11
|
-
matchLabels:
|
|
12
|
-
app: service-valkey
|
|
13
|
-
template:
|
|
14
|
-
metadata:
|
|
15
|
-
labels:
|
|
16
|
-
app: service-valkey
|
|
17
|
-
spec:
|
|
18
|
-
containers:
|
|
19
|
-
- name: service-valkey
|
|
20
|
-
image: docker.io/valkey/valkey:latest
|
|
21
|
-
env:
|
|
22
|
-
- name: TZ
|
|
23
|
-
value: Europe/Zurich
|
|
24
|
-
ports:
|
|
25
|
-
- containerPort: 6379
|
|
26
|
-
startupProbe:
|
|
27
|
-
tcpSocket:
|
|
28
|
-
port: 6379
|
|
29
|
-
failureThreshold: 30
|
|
30
|
-
periodSeconds: 5
|
|
31
|
-
timeoutSeconds: 5
|
|
32
|
-
livenessProbe:
|
|
33
|
-
tcpSocket:
|
|
34
|
-
port: 6379
|
|
35
|
-
failureThreshold: 2
|
|
36
|
-
periodSeconds: 30
|
|
37
|
-
timeoutSeconds: 5
|
|
38
|
-
restartPolicy: Always
|
|
39
|
-
automountServiceAccountToken: false
|