underpost 2.8.62 → 2.8.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/Dockerfile +9 -10
  2. package/bin/build.js +2 -2
  3. package/bin/deploy.js +1 -1
  4. package/bin/index.js +21 -7
  5. package/docker-compose.yml +1 -1
  6. package/package.json +1 -1
  7. package/src/api/default/default.service.js +1 -1
  8. package/src/api/user/user.service.js +1 -1
  9. package/src/cli/cron.js +39 -8
  10. package/src/cli/deploy.js +83 -42
  11. package/src/cli/fs.js +7 -6
  12. package/src/cli/image.js +81 -75
  13. package/src/cli/monitor.js +92 -0
  14. package/src/client/components/core/Account.js +25 -21
  15. package/src/client/components/core/Blockchain.js +1 -1
  16. package/src/client/components/core/CalendarCore.js +14 -83
  17. package/src/client/components/core/CommonJs.js +2 -1
  18. package/src/client/components/core/CssCore.js +8 -2
  19. package/src/client/components/core/Docs.js +1 -1
  20. package/src/client/components/core/EventsUI.js +2 -2
  21. package/src/client/components/core/FileExplorer.js +86 -78
  22. package/src/client/components/core/LoadingAnimation.js +1 -17
  23. package/src/client/components/core/LogIn.js +3 -3
  24. package/src/client/components/core/LogOut.js +1 -1
  25. package/src/client/components/core/Modal.js +12 -7
  26. package/src/client/components/core/Panel.js +19 -61
  27. package/src/client/components/core/PanelForm.js +13 -22
  28. package/src/client/components/core/Recover.js +3 -3
  29. package/src/client/components/core/Router.js +3 -1
  30. package/src/client/components/core/SignUp.js +2 -2
  31. package/src/client/components/default/RoutesDefault.js +3 -2
  32. package/src/client/services/default/default.management.js +45 -38
  33. package/src/client/ssr/Render.js +2 -0
  34. package/src/index.js +17 -2
  35. package/src/runtime/lampp/Dockerfile +65 -0
  36. package/src/server/conf.js +45 -1
  37. package/src/server/dns.js +9 -1
  38. package/src/server/network.js +7 -122
  39. package/src/server/runtime.js +1 -3
@@ -80,36 +80,40 @@ const DefaultManagement = {
80
80
  class: `in fll section-mp management-table-btn-mini management-table-btn-remove-${id}-${cellRenderId}`,
81
81
  })}`;
82
82
  setTimeout(() => {
83
- EventsUI.onClick(`.management-table-btn-remove-${id}-${cellRenderId}`, async () => {
84
- const confirmResult = await Modal.RenderConfirm({
85
- html: async () => {
86
- return html`
87
- <div class="in section-mp" style="text-align: center">
88
- ${Translate.Render('confirm-delete-item')}
89
- ${Object.keys(params.data).length > 0
90
- ? html`<br />
91
- "${options.defaultColKeyFocus
92
- ? getValueFromJoinString(params.data, options.defaultColKeyFocus)
93
- : params.data[Object.keys(params.data)[0]]}"`
94
- : ''}
95
- </div>
96
- `;
97
- },
98
- id: `delete-${params.data._id}`,
99
- });
100
- if (confirmResult.status !== 'confirm') return;
101
- let result;
102
- if (params.data._id) result = await ServiceProvider.delete({ id: params.data._id });
103
- else result = { status: 'success' };
83
+ EventsUI.onClick(
84
+ `.management-table-btn-remove-${id}-${cellRenderId}`,
85
+ async () => {
86
+ const confirmResult = await Modal.RenderConfirm({
87
+ html: async () => {
88
+ return html`
89
+ <div class="in section-mp" style="text-align: center">
90
+ ${Translate.Render('confirm-delete-item')}
91
+ ${Object.keys(params.data).length > 0
92
+ ? html`<br />
93
+ "${options.defaultColKeyFocus
94
+ ? getValueFromJoinString(params.data, options.defaultColKeyFocus)
95
+ : params.data[Object.keys(params.data)[0]]}"`
96
+ : ''}
97
+ </div>
98
+ `;
99
+ },
100
+ id: `delete-${params.data._id}`,
101
+ });
102
+ if (confirmResult.status !== 'confirm') return;
103
+ let result;
104
+ if (params.data._id) result = await ServiceProvider.delete({ id: params.data._id });
105
+ else result = { status: 'success' };
104
106
 
105
- NotificationManager.Push({
106
- html: result.status === 'error' ? result.message : Translate.Render('item-success-delete'),
107
- status: result.status,
108
- });
109
- if (result.status === 'success') {
110
- AgGrid.grids[gridId].applyTransaction({ remove: [params.data] });
111
- }
112
- });
107
+ NotificationManager.Push({
108
+ html: result.status === 'error' ? result.message : Translate.Render('item-success-delete'),
109
+ status: result.status,
110
+ });
111
+ if (result.status === 'success') {
112
+ AgGrid.grids[gridId].applyTransaction({ remove: [params.data] });
113
+ }
114
+ },
115
+ { context: 'modal' },
116
+ );
113
117
  });
114
118
  }
115
119
 
@@ -220,16 +224,19 @@ const DefaultManagement = {
220
224
  });
221
225
  });
222
226
  EventsUI.onClick(`.management-table-btn-clean-${id}`, async () => {
223
- const confirmResult = await Modal.RenderConfirm({
224
- html: async () => {
225
- return html`
226
- <div class="in section-mp" style="text-align: center;">
227
- <strong>${Translate.Render('confirm-delete-all-data')}</strong>
228
- </div>
229
- `;
227
+ const confirmResult = await Modal.RenderConfirm(
228
+ {
229
+ html: async () => {
230
+ return html`
231
+ <div class="in section-mp" style="text-align: center;">
232
+ <strong>${Translate.Render('confirm-delete-all-data')}</strong>
233
+ </div>
234
+ `;
235
+ },
236
+ id: `clean-table-${id}`,
230
237
  },
231
- id: `clean-table-${id}`,
232
- });
238
+ { context: 'modal' },
239
+ );
233
240
  if (confirmResult.status === 'cancelled') return;
234
241
  const result = await ServiceProvider.delete();
235
242
  NotificationManager.Push({
@@ -133,6 +133,8 @@ SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents,
133
133
  border: none;
134
134
  padding-block: 0;
135
135
  padding-inline: 0;
136
+ height: 30px;
137
+ line-height: 30px;
136
138
  }
137
139
  input::file-selector-button {
138
140
  outline: none !important;
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ import UnderpostDeploy from './cli/deploy.js';
11
11
  import UnderpostRootEnv from './cli/env.js';
12
12
  import UnderpostFileStorage from './cli/fs.js';
13
13
  import UnderpostImage from './cli/image.js';
14
+ import UnderpostMonitor from './cli/monitor.js';
14
15
  import UnderpostRepository from './cli/repository.js';
15
16
  import UnderpostScript from './cli/script.js';
16
17
  import UnderpostSecret from './cli/secrets.js';
@@ -28,7 +29,7 @@ class Underpost {
28
29
  * @type {String}
29
30
  * @memberof Underpost
30
31
  */
31
- static version = 'v2.8.62';
32
+ static version = 'v2.8.64';
32
33
  /**
33
34
  * Repository cli API
34
35
  * @static
@@ -92,6 +93,13 @@ class Underpost {
92
93
  * @memberof Underpost
93
94
  */
94
95
  static deploy = UnderpostDeploy.API;
96
+ /**
97
+ * Deployment cli NETWORK
98
+ * @static
99
+ * @type {UnderpostDeploy.NETWORK}
100
+ * @memberof Underpost
101
+ */
102
+ static deployNetwork = UnderpostDeploy.NETWORK;
95
103
  /**
96
104
  * Cron cli API
97
105
  * @static
@@ -103,9 +111,16 @@ class Underpost {
103
111
  * File Storage cli API
104
112
  * @static
105
113
  * @type {UnderpostFileStorage.API}
106
- * @memberof UnderpostFileStorage
114
+ * @memberof Underpost
107
115
  */
108
116
  static fs = UnderpostFileStorage.API;
117
+ /**
118
+ * Monitor cli API
119
+ * @static
120
+ * @type {UnderpostMonitor.API}
121
+ * @memberof Underpost
122
+ */
123
+ static monitor = UnderpostMonitor.API;
109
124
  }
110
125
 
111
126
  const up = Underpost;
@@ -0,0 +1,65 @@
1
+ ARG BASE_DEBIAN=buster
2
+
3
+ USER root
4
+
5
+ FROM debian:${BASE_DEBIAN}
6
+
7
+ ENV DEBIAN_FRONTEND=noninteractive
8
+
9
+ # Set root password to root, format is 'user:password'.
10
+ RUN echo 'root:root' | chpasswd
11
+
12
+ RUN apt-get update --fix-missing
13
+ RUN apt-get upgrade -y
14
+ # install sudo
15
+ RUN apt-get -y install sudo
16
+ # net-tools provides netstat commands
17
+ RUN apt-get -y install curl net-tools
18
+ RUN apt-get -yq install openssh-server supervisor
19
+ # Few handy utilities which are nice to have
20
+ RUN apt-get -y install nano vim less --no-install-recommends
21
+ RUN apt-get clean
22
+
23
+ # install ssh
24
+ RUN mkdir -p /var/run/sshd
25
+ # Allow root login via password
26
+ RUN sed -ri 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
27
+
28
+ # install open ssl git and others tools
29
+ RUN apt-get install -yq --no-install-recommends libssl-dev curl wget git gnupg
30
+
31
+ # install lampp
32
+ RUN curl -Lo xampp-linux-installer.run https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run?from_af=true
33
+ RUN chmod +x xampp-linux-installer.run
34
+ RUN bash -c './xampp-linux-installer.run'
35
+ RUN ln -sf /opt/lampp/lampp /usr/bin/lampp
36
+ # Enable XAMPP web interface(remove security checks)
37
+ RUN sed -i.bak s'/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf
38
+ # Enable error display in php
39
+ RUN sed -i.bak s'/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
40
+ # Enable includes of several configuration files
41
+ RUN mkdir /opt/lampp/apache2/conf.d
42
+ RUN echo "IncludeOptional /opt/lampp/apache2/conf.d/*.conf" >>/opt/lampp/etc/httpd.conf
43
+ # Create a /www folder and a symbolic link to it in /opt/lampp/htdocs. It'll be accessible via http://localhost:[port]/www/
44
+ # This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools in /opt/lampp/htdocs
45
+ # /opt/lampp/etc/httpd.conf
46
+ RUN mkdir /www
47
+ RUN ln -s /www /opt/lampp/htdocs
48
+
49
+ # install nodejs https://github.com/nodesource/distributions/blob/master/README.md#deb
50
+ RUN curl -fsSL https://deb.nodesource.com/setup_23.x | bash -
51
+ RUN apt-get install -y nodejs build-essential
52
+ RUN node --version
53
+ RUN npm --version
54
+
55
+ WORKDIR /home/dd
56
+
57
+ EXPOSE 22
58
+
59
+ EXPOSE 80
60
+
61
+ EXPOSE 443
62
+
63
+ EXPOSE 3000-3100
64
+
65
+ EXPOSE 4000-4100
@@ -499,6 +499,40 @@ const buildProxyRouter = () => {
499
499
  return proxyRouter;
500
500
  };
501
501
 
502
+ const pathPortAssignmentFactory = (router, confServer) => {
503
+ const pathPortAssignmentData = {};
504
+ for (const host of Object.keys(confServer)) {
505
+ const pathPortAssignment = [];
506
+ for (const path of Object.keys(confServer[host])) {
507
+ const { peer } = confServer[host][path];
508
+ if (!router[`${host}${path === '/' ? '' : path}`]) continue;
509
+ const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
510
+ // logger.info('', { host, port, path });
511
+ pathPortAssignment.push({
512
+ port,
513
+ path,
514
+ });
515
+
516
+ if (peer) {
517
+ // logger.info('', { host, port: port + 1, path: '/peer' });
518
+ pathPortAssignment.push({
519
+ port: port + 1,
520
+ path: '/peer',
521
+ });
522
+ }
523
+ }
524
+ pathPortAssignmentData[host] = pathPortAssignment;
525
+ }
526
+ return pathPortAssignmentData;
527
+ };
528
+
529
+ const deployRangePortFactory = (router) => {
530
+ const ports = Object.values(router).map((p) => parseInt(p.split(':')[2]));
531
+ const fromPort = Math.min(...ports);
532
+ const toPort = Math.max(...ports);
533
+ return { ports, fromPort, toPort };
534
+ };
535
+
502
536
  const buildKindPorts = (from, to) =>
503
537
  range(parseInt(from), parseInt(to))
504
538
  .map(
@@ -729,7 +763,7 @@ const validateTemplatePath = (absolutePath = '') => {
729
763
  return true;
730
764
  };
731
765
 
732
- const deployTest = async (dataDeploy) => {
766
+ const deployTest = async (dataDeploy = [{ deployId: 'default' }]) => {
733
767
  const failed = [];
734
768
  for (const deploy of dataDeploy) {
735
769
  const deployServerConfPath = fs.existsSync(`./engine-private/replica/${deploy.deployId}/conf.server.json`)
@@ -773,6 +807,12 @@ const deployTest = async (dataDeploy) => {
773
807
  return { failed };
774
808
  };
775
809
 
810
+ const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
811
+ if (init) fs.writeFileSync(`./tmp/await-deploy`, '', 'utf8');
812
+ await timer(deltaMs);
813
+ if (fs.existsSync(`./tmp/await-deploy`)) return await awaitDeployMonitor();
814
+ };
815
+
776
816
  const getDeployGroupId = () => {
777
817
  const deployGroupIndexArg = process.argv.findIndex((a) => a.match(`deploy-group:`));
778
818
  if (deployGroupIndexArg > -1) return process.argv[deployGroupIndexArg].split(':')[1].trim();
@@ -1122,4 +1162,8 @@ export {
1122
1162
  getNpmRootPath,
1123
1163
  getUnderpostRootPath,
1124
1164
  writeEnv,
1165
+ deployTest,
1166
+ pathPortAssignmentFactory,
1167
+ deployRangePortFactory,
1168
+ awaitDeployMonitor,
1125
1169
  };
package/src/server/dns.js CHANGED
@@ -2,7 +2,7 @@ import axios from 'axios';
2
2
  import dotenv from 'dotenv';
3
3
  import fs from 'fs';
4
4
  import validator from 'validator';
5
- import { ip } from './network.js';
5
+ import { publicIp, publicIpv4, publicIpv6 } from 'public-ip';
6
6
  import { loggerFactory } from './logger.js';
7
7
  import UnderpostRootEnv from '../cli/env.js';
8
8
 
@@ -10,6 +10,14 @@ dotenv.config();
10
10
 
11
11
  const logger = loggerFactory(import.meta);
12
12
 
13
+ const ip = {
14
+ public: {
15
+ get: async () => await publicIp(), // => 'fe80::200:f8ff:fe21:67cf'
16
+ ipv4: async () => await publicIpv4(), // => '46.5.21.123'
17
+ ipv6: async () => await publicIpv6(), // => 'fe80::200:f8ff:fe21:67cf'
18
+ },
19
+ };
20
+
13
21
  class Dns {
14
22
  static callback = async function (deployList) {
15
23
  // Network topology configuration:
@@ -1,123 +1,18 @@
1
- import fs from 'fs-extra';
2
-
3
- import { publicIp, publicIpv4, publicIpv6 } from 'public-ip';
1
+ import Underpost from '../index.js';
4
2
  import { actionInitLog, loggerFactory } from './logger.js';
5
- import { DataBaseProvider } from '../db/DataBaseProvider.js';
6
- import { getDeployId } from './conf.js';
7
-
8
- // Network Address Translation Management
9
-
10
- // import dotenv from 'dotenv';
11
- // dotenv.config();
12
3
 
13
4
  const logger = loggerFactory(import.meta);
14
5
 
15
- const ip = {
16
- public: {
17
- get: async () => await publicIp(), // => 'fe80::200:f8ff:fe21:67cf'
18
- ipv4: async () => await publicIpv4(), // => '46.5.21.123'
19
- ipv6: async () => await publicIpv6(), // => 'fe80::200:f8ff:fe21:67cf'
20
- },
21
- };
22
-
23
- let ipInstance = '';
24
- const networkRouter = {};
25
-
26
6
  const logRuntimeRouter = () => {
27
7
  const displayLog = {};
28
8
 
29
- for (const host of Object.keys(networkRouter))
30
- for (const path of Object.keys(networkRouter[host]))
31
- displayLog[networkRouter[host][path].publicHost] = networkRouter[host][path].local;
9
+ for (const host of Object.keys(Underpost.deployNetwork))
10
+ for (const path of Object.keys(Underpost.deployNetwork[host]))
11
+ displayLog[Underpost.deployNetwork[host][path].publicHost] = Underpost.deployNetwork[host][path].local;
32
12
 
33
13
  logger.info('Runtime network', displayLog);
34
14
  };
35
15
 
36
- const saveRuntimeRouter = async () => {
37
- try {
38
- const deployId = process.env.DEFAULT_DEPLOY_ID;
39
- const host = process.env.DEFAULT_DEPLOY_HOST;
40
- const path = process.env.DEFAULT_DEPLOY_PATH;
41
- const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
42
- if (!deployId || !host || !path || !fs.existsSync(confServerPath)) {
43
- // logger.warn('default deploy instance not found');
44
- return;
45
- }
46
- const confServer = JSON.parse(fs.readFileSync(confServerPath, 'utf8'));
47
- const { db } = confServer[host][path];
48
-
49
- let closeConn;
50
- if (!DataBaseProvider.instance[`${host}${path}`]) {
51
- await DataBaseProvider.load({ apis: ['instance'], host, path, db });
52
- closeConn = true;
53
- }
54
-
55
- /** @type {import('../api/instance/instance.model.js').InstanceModel} */
56
- const Instance = DataBaseProvider.instance[`${host}${path}`].mongoose.models.Instance;
57
-
58
- for (const _host of Object.keys(networkRouter)) {
59
- for (const _path of Object.keys(networkRouter[_host])) {
60
- const body = {
61
- host: _host,
62
- path: _path,
63
- deployId: getDeployId(),
64
- client: networkRouter[_host][_path].client,
65
- runtime: networkRouter[_host][_path].runtime,
66
- port: networkRouter[_host][_path].port,
67
- apis: networkRouter[_host][_path].apis,
68
- };
69
- const instance = await Instance.findOne({ deployId: body.deployId, host: _host, path: _path });
70
- if (instance) {
71
- await Instance.findByIdAndUpdate(instance._id, body);
72
- } else {
73
- await new Instance(body).save();
74
- }
75
- }
76
- }
77
-
78
- if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
79
- } catch (error) {
80
- logger.error(error, error.stack);
81
- }
82
- };
83
-
84
- const netWorkCron = [];
85
-
86
- const saveRuntimeCron = async () => {
87
- try {
88
- const deployId = process.env.DEFAULT_DEPLOY_ID;
89
- const host = process.env.DEFAULT_DEPLOY_HOST;
90
- const path = process.env.DEFAULT_DEPLOY_PATH;
91
- const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
92
- const confServer = JSON.parse(fs.readFileSync(confServerPath, 'utf8'));
93
- const { db } = confServer[host][path];
94
-
95
- let closeConn;
96
- if (!DataBaseProvider.instance[`${host}${path}`]) {
97
- await DataBaseProvider.load({ apis: ['cron'], host, path, db });
98
- closeConn = true;
99
- }
100
-
101
- /** @type {import('../api/cron/cron.model.js').CronModel} */
102
- const Cron = DataBaseProvider.instance[`${host}${path}`].mongoose.models.Cron;
103
-
104
- // await Cron.insertMany(netWorkCron);
105
-
106
- for (const cronInstance of netWorkCron) {
107
- const cron = await Cron.findOne({ deployId: cronInstance.deployId, jobId: cronInstance.jobId });
108
- if (cron) {
109
- await Cron.findByIdAndUpdate(cron._id, cronInstance);
110
- } else {
111
- await new Cron(cronInstance).save();
112
- }
113
- }
114
-
115
- if (closeConn) await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
116
- } catch (error) {
117
- logger.error(error, error.stack);
118
- }
119
- };
120
-
121
16
  const listenServerFactory = (logic = async () => {}) => {
122
17
  return {
123
18
  listen: async (...args) => (
@@ -150,13 +45,12 @@ const listenPortController = async (server, port, metadata) =>
150
45
  if (error.length > 0) throw new Error('Listen port controller requires values: ' + error.join(', '));
151
46
 
152
47
  server.listen(port, () => {
153
- if (!networkRouter[host]) networkRouter[host] = {};
154
- networkRouter[host][path] = {
48
+ if (!Underpost.deployNetwork[host]) Underpost.deployNetwork[host] = {};
49
+ Underpost.deployNetwork[host][path] = {
155
50
  meta,
156
51
  client,
157
52
  runtime,
158
53
  port,
159
- public: `http://${ipInstance}:${port}${path}`,
160
54
  publicHost:
161
55
  port === 80
162
56
  ? `http://${host}${path}`
@@ -175,13 +69,4 @@ const listenPortController = async (server, port, metadata) =>
175
69
  }
176
70
  });
177
71
 
178
- export {
179
- ip,
180
- listenPortController,
181
- networkRouter,
182
- netWorkCron,
183
- saveRuntimeRouter,
184
- logRuntimeRouter,
185
- listenServerFactory,
186
- saveRuntimeCron,
187
- };
72
+ export { listenPortController, logRuntimeRouter, listenServerFactory };
@@ -9,7 +9,7 @@ import compression from 'compression';
9
9
 
10
10
  import { createServer } from 'http';
11
11
  import { getRootDirectory } from './process.js';
12
- import { listenPortController, saveRuntimeRouter, logRuntimeRouter, listenServerFactory } from './network.js';
12
+ import { listenPortController, logRuntimeRouter, listenServerFactory } from './network.js';
13
13
  import { loggerFactory, loggerMiddleware } from './logger.js';
14
14
  import { getCapVariableName, newInstance } from '../client/components/core/CommonJs.js';
15
15
  import { Xampp } from '../runtime/xampp/Xampp.js';
@@ -41,7 +41,6 @@ const buildRuntime = async () => {
41
41
  // logger.info('promCounterOption', promCounterOption);
42
42
 
43
43
  const requestCounter = new promClient.Counter(promCounterOption);
44
- const ipInstance = ''; // await ip.public.ipv4();
45
44
  const initPort = parseInt(process.env.PORT) + 1;
46
45
  let currentPort = initPort;
47
46
  const confServer = JSON.parse(fs.readFileSync(`./conf/conf.server.json`, 'utf8'));
@@ -484,7 +483,6 @@ const buildRuntime = async () => {
484
483
  if (Xampp.enabled() && Xampp.router) Xampp.initService();
485
484
  if (Lampp.enabled() && Lampp.router) Lampp.initService();
486
485
 
487
- saveRuntimeRouter();
488
486
  logRuntimeRouter();
489
487
  };
490
488