underpost 2.8.45 → 2.8.47

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.
@@ -9,47 +9,6 @@ permissions:
9
9
  packages: write
10
10
  id-token: write
11
11
  jobs:
12
- pwa-microservices-template:
13
- if: github.repository == 'underpostnet/engine' && startsWith(github.event.head_commit.message, 'ci(package-pwa-microservices-template)')
14
- name: Update github repo package Jobs
15
- runs-on: ubuntu-latest
16
- permissions:
17
- contents: write
18
- packages: write
19
- id-token: write
20
- steps:
21
- - uses: actions/checkout@v3
22
-
23
- - uses: actions/setup-node@v4
24
- with:
25
- node-version: '22.x'
26
-
27
- - name: Install dependencies
28
- run: |
29
- npm install
30
-
31
- - name: Set git credentials
32
- run: |
33
- git config --global credential.helper ""
34
- git config credential.helper ""
35
- git config --global user.name 'underpostnet'
36
- git config --global user.email 'development@underpost.net'
37
- git config --global credential.interactive always
38
- git config user.name 'underpostnet'
39
- git config user.email 'development@underpost.net'
40
- git config credential.interactive always
41
-
42
- - name: Clone github package repository
43
- run: |
44
- cd .. && git clone https://github.com/underpostnet/pwa-microservices-template.git
45
- cd engine
46
- npm run update-template
47
- cd ../pwa-microservices-template
48
- git remote set-url origin git@github.com:underpostnet/pwa-microservices-template.git
49
- git add .
50
- git commit -m "ci(package-pwa-microservices-template-ghpkg): ⚙️ Update github repo package"
51
- git push https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/pwa-microservices-template.git
52
-
53
12
  pwa-microservices-template-ghpk:
54
13
  if: github.repository == 'underpostnet/pwa-microservices-template' && startsWith(github.event.head_commit.message, 'ci(package-pwa-microservices-template-ghpkg)')
55
14
  name: Update github repo package Jobs
@@ -63,7 +22,7 @@ jobs:
63
22
 
64
23
  - uses: actions/setup-node@v4
65
24
  with:
66
- node-version: '22.x'
25
+ node-version: '23.x'
67
26
 
68
27
  # - name: Get npm root
69
28
  # run: sudo npm root -g
@@ -82,13 +41,15 @@ jobs:
82
41
 
83
42
  - name: Install dependencies and set repo configuration
84
43
  run: |
85
- npm install
44
+ npm install -g underpost
45
+ underpost config set GITHUB_TOKEN ${{ secrets.GIT_AUTH_TOKEN }}
46
+ underpost install
86
47
  node ./bin/deploy rename-package @underpostnet/underpost
87
48
  node ./bin/deploy set-repo underpostnet/pwa-microservices-template-ghpkg
88
49
 
89
50
  - name: Clone github package repository
90
51
  run: |
91
- git clone --bare https://github.com/underpostnet/pwa-microservices-template-ghpkg.git
52
+ underpost clone --bare underpostnet/pwa-microservices-template-ghpkg
92
53
  rm -rf ./.git
93
54
  cp -rf -a ./pwa-microservices-template-ghpkg.git ./.git
94
55
  rm -rf ./pwa-microservices-template-ghpkg.git
@@ -111,8 +72,14 @@ jobs:
111
72
  git status
112
73
  git remote set-url origin git@github.com:underpostnet/pwa-microservices-template-ghpkg.git
113
74
  git add .
114
- git commit -m "ci(package-pwa-microservices-template-ghpkg): ⚙️ Update github repo package"
115
- git push https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/pwa-microservices-template-ghpkg.git
75
+ underpost cmt . ci package-pwa-microservices-template-ghpkg 'Update github repo package'
76
+ underpost push . underpostnet/pwa-microservices-template-ghpkg
77
+
78
+ # git clone --bare https://github.com/underpostnet/engine.git
79
+ # mkdir engine
80
+ # mv ./engine.git ./engine/.git
81
+ # cd engine
82
+ # git init
116
83
 
117
84
  # git push -u origin https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/pwa-microservices-template-ghpkg.git
118
85
  # git push -u origin master
@@ -0,0 +1,67 @@
1
+ name: Update npm repo package
2
+ on:
3
+ push:
4
+ branches: ['master']
5
+ pull_request:
6
+ branches: ['master']
7
+ permissions:
8
+ contents: write
9
+ packages: write
10
+ id-token: write
11
+ jobs:
12
+ pwa-microservices-template:
13
+ if: github.repository == 'underpostnet/engine' && startsWith(github.event.head_commit.message, 'ci(package-pwa-microservices-template)')
14
+ name: Update npm repo package Jobs
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: write
18
+ packages: write
19
+ id-token: write
20
+ steps:
21
+ - uses: actions/checkout@v3
22
+
23
+ - uses: actions/setup-node@v4
24
+ with:
25
+ node-version: '23.x'
26
+
27
+ - name: Install dependencies
28
+ run: |
29
+ npm install -g underpost
30
+ underpost config set GITHUB_TOKEN ${{ secrets.GIT_AUTH_TOKEN }}
31
+ underpost install
32
+
33
+ - name: Set git credentials
34
+ run: |
35
+ git config --global credential.helper ""
36
+ git config credential.helper ""
37
+ git config --global user.name 'underpostnet'
38
+ git config --global user.email 'development@underpost.net'
39
+ git config --global credential.interactive always
40
+ git config user.name 'underpostnet'
41
+ git config user.email 'development@underpost.net'
42
+ git config credential.interactive always
43
+
44
+ - name: Clone github package repository
45
+ run: |
46
+ cd .. && underpost clone underpostnet/pwa-microservices-template
47
+ cd engine
48
+ npm run update-template
49
+ cd ../pwa-microservices-template
50
+ git remote set-url origin git@github.com:underpostnet/pwa-microservices-template.git
51
+ git add .
52
+ underpost cmt . ci package-pwa-microservices-template-ghpkg 'Update npm repo package'
53
+ underpost push . underpostnet/pwa-microservices-template
54
+ # cd ../engine
55
+ # git commit --allow-empty -m "ci(engine-core-repo-build): ⚙️ Update engine core repository"
56
+ # git commit --allow-empty -m "ci(engine-cyberia-repo-build): ⚙️ Update engine cyberia repository"
57
+ # git commit --allow-empty -m "ci(engine-lampp-repo-build): ⚙️ Update engine lampp repository"
58
+ # git push https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/engine.git
59
+
60
+ # git clone --bare https://github.com/underpostnet/engine.git
61
+ # mkdir engine
62
+ # mv ./engine.git ./engine/.git
63
+ # cd engine
64
+ # git init
65
+
66
+ # git push -u origin https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/pwa-microservices-template-ghpkg.git
67
+ # git push -u origin master
@@ -14,7 +14,7 @@ jobs:
14
14
  - uses: actions/checkout@v4
15
15
  - uses: actions/setup-node@v4
16
16
  with:
17
- node-version: '22.x'
17
+ node-version: '23.x'
18
18
  registry-url: 'https://registry.npmjs.org'
19
19
 
20
20
  - name: Install Dependencies
@@ -25,7 +25,7 @@ jobs:
25
25
  # Publish to npm
26
26
  - uses: actions/setup-node@v4
27
27
  with:
28
- node-version: '22.x'
28
+ node-version: '23.x'
29
29
  registry-url: 'https://registry.npmjs.org'
30
30
  # Defaults to the user or organization that owns the workflow file
31
31
  # scope: '@underpostnet'
@@ -45,7 +45,7 @@ jobs:
45
45
  - uses: actions/checkout@v4
46
46
  - uses: actions/setup-node@v4
47
47
  with:
48
- node-version: '22.x'
48
+ node-version: '23.x'
49
49
  registry-url: 'https://registry.npmjs.org'
50
50
 
51
51
  - name: Install Dependencies
@@ -56,7 +56,7 @@ jobs:
56
56
  # Publish to npm git hub package
57
57
  - uses: actions/setup-node@v4
58
58
  with:
59
- node-version: '22.x'
59
+ node-version: '23.x'
60
60
  registry-url: 'https://registry.npmjs.org'
61
61
  # Defaults to the user or organization that owns the workflow file
62
62
  scope: '@underpostnet'
@@ -70,7 +70,7 @@ jobs:
70
70
  - name: Setup node to publish to GitHub Packages
71
71
  uses: actions/setup-node@v4
72
72
  with:
73
- node-version: 22.x
73
+ node-version: 23.x
74
74
  registry-url: 'https://npm.pkg.github.com'
75
75
  # Defaults to the user or organization that owns the workflow file
76
76
  scope: '@underpostnet'
@@ -38,11 +38,12 @@ jobs:
38
38
  # run: git lfs checkout
39
39
  - uses: actions/setup-node@v4
40
40
  with:
41
- node-version: '22.x'
41
+ node-version: '23.x'
42
42
 
43
43
  - name: Build the site
44
44
  run: |
45
- npm install
45
+ npm install -g underpost
46
+ underpost install
46
47
  node bin/deploy update-default-conf ghpkg
47
48
  env-cmd -f .env.production node bin/deploy build-full-client github-pages underpostnet.github.io /pwa-microservices-template-ghpkg
48
49
  # git lfs install
@@ -2,12 +2,12 @@ name: Test
2
2
  on: [push]
3
3
  jobs:
4
4
  test:
5
- if: (github.repository == 'underpostnet/pwa-microservices-template') || (github.repository == 'underpostnet/pwa-microservices-template-ghpkg')
5
+ # if: (github.repository == 'underpostnet/pwa-microservices-template') || (github.repository == 'underpostnet/pwa-microservices-template-ghpkg')
6
6
  name: Node ${{ matrix.node }} on ${{ matrix.os }}
7
7
  runs-on: ${{ matrix.os }}
8
8
  strategy:
9
9
  matrix:
10
- node-version: [21.x]
10
+ node-version: [23.x]
11
11
  os: [ubuntu-latest]
12
12
  # os: [ubuntu-latest, windows-latest]
13
13
 
package/Dockerfile CHANGED
@@ -4,7 +4,7 @@ FROM debian:${BASE_DEBIAN}
4
4
 
5
5
  ENV DEBIAN_FRONTEND=noninteractive
6
6
 
7
- WORKDIR /code
7
+ WORKDIR /home/dd
8
8
 
9
9
  # Set root password to root, format is 'user:password'.
10
10
  RUN echo 'root:root' | chpasswd
@@ -39,10 +39,10 @@ RUN npm --version
39
39
 
40
40
  RUN npm install -g underpost
41
41
 
42
- VOLUME [ "/code/app/logs" ]
42
+ VOLUME [ "/home/dd/engine/logs" ]
43
43
 
44
44
  EXPOSE 22
45
45
 
46
46
  EXPOSE 4000-4004
47
47
 
48
- CMD [ "underpost", "new", "app" ]
48
+ CMD [ "underpost", "new", "engine" ]
package/bin/build.js CHANGED
@@ -292,16 +292,16 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
292
292
  if (!fs.existsSync(`${basePath}/images`)) fs.mkdirSync(`${basePath}/images`);
293
293
 
294
294
  const env = process.argv.includes('development') ? 'development' : 'production';
295
-
295
+ const deploymentsFiles = ['Dockerfile', 'proxy.yaml', 'deployment.yaml', 'secret.yaml'];
296
296
  // remove engine-private of .dockerignore for local testing
297
297
 
298
- {
298
+ if (process.argv.includes('engine')) {
299
299
  fs.removeSync(`${basePath}/manifests/deployment`);
300
300
 
301
301
  if (!fs.existsSync(`./manifests/deployment/${confName}-${env}`))
302
302
  fs.mkdirSync(`./manifests/deployment/${confName}-${env}`);
303
303
 
304
- for (const file of ['Dockerfile', 'proxy.yaml', 'deployment.yaml', 'secret.yaml']) {
304
+ for (const file of deploymentsFiles) {
305
305
  if (fs.existsSync(`./engine-private/conf/${confName}/build/${env}/${file}`)) {
306
306
  fs.copyFileSync(`./engine-private/conf/${confName}/build/${env}/${file}`, `${basePath}/${file}`);
307
307
  fs.copyFileSync(
@@ -310,5 +310,11 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
310
310
  );
311
311
  }
312
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
+ }
318
+ }
313
319
  }
314
320
  }
package/bin/deploy.js CHANGED
@@ -2,7 +2,6 @@ import fs from 'fs-extra';
2
2
  import axios from 'axios';
3
3
 
4
4
  import dotenv from 'dotenv';
5
- import plantuml from 'plantuml';
6
5
 
7
6
  import { pbcopy, shellCd, shellExec } from '../src/server/process.js';
8
7
  import { loggerFactory } from '../src/server/logger.js';
@@ -257,19 +256,6 @@ try {
257
256
 
258
257
  shellExec(Cmd.replica(deployId, host, path));
259
258
  }
260
- if (serverConf[host][path].db) {
261
- switch (serverConf[host][path].db.provider) {
262
- case 'mariadb':
263
- {
264
- shellExec(`node bin/db ${host}${path} create ${deployId}`);
265
- }
266
-
267
- break;
268
-
269
- default:
270
- break;
271
- }
272
- }
273
259
  }
274
260
  }
275
261
  }
@@ -591,6 +577,7 @@ try {
591
577
  }
592
578
  case 'build-uml':
593
579
  {
580
+ const plantuml = await import('plantuml');
594
581
  const folder = process.argv[3] ? process.argv[3] : `./src/client/public/default/plantuml`;
595
582
  const confData = Config.default;
596
583
 
package/bin/file.js CHANGED
@@ -1,7 +1,13 @@
1
1
  import fs from 'fs-extra';
2
2
 
3
3
  import { loggerFactory } from '../src/server/logger.js';
4
- import { cap, getCapVariableName, getDirname, newInstance } from '../src/client/components/core/CommonJs.js';
4
+ import {
5
+ cap,
6
+ getCapVariableName,
7
+ getDirname,
8
+ newInstance,
9
+ uniqueArray,
10
+ } from '../src/client/components/core/CommonJs.js';
5
11
  import { shellCd, shellExec } from '../src/server/process.js';
6
12
  import walk from 'ignore-walk';
7
13
  import { validateTemplatePath } from '../src/server/conf.js';
@@ -80,10 +86,13 @@ try {
80
86
  '.github/workflows/engine.lampp.ci.yml',
81
87
  '.github/workflows/engine.core.ci.yml',
82
88
  '.github/workflows/engine.cyberia.ci.yml',
89
+ './manifests/deployment/dd-lampp-development',
90
+ './manifests/deployment/dd-cyberia-development',
91
+ './manifests/deployment/dd-core-development',
83
92
  'bin/web3.js',
84
93
  'bin/cyberia.js',
85
94
  ]) {
86
- fs.removeSync('../pwa-microservices-template/' + deletePath);
95
+ if (fs.existsSync(deletePath)) fs.removeSync('../pwa-microservices-template/' + deletePath);
87
96
  }
88
97
  const originPackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
89
98
  const templatePackageJson = JSON.parse(fs.readFileSync('../pwa-microservices-template/package.json', 'utf8'));
@@ -101,6 +110,9 @@ try {
101
110
  templatePackageJson.description = description;
102
111
  templatePackageJson.scripts.dev = dev;
103
112
  templatePackageJson.scripts.build = build;
113
+ templatePackageJson.keywords = uniqueArray(
114
+ ['pwa', 'microservices', 'template', 'builder'].concat(templatePackageJson.keywords),
115
+ );
104
116
  delete templatePackageJson.scripts['update-template'];
105
117
  fs.writeFileSync(
106
118
  '../pwa-microservices-template/package.json',
package/bin/index.js CHANGED
@@ -8,6 +8,8 @@ import { getNpmRootPath, loadConf } from '../src/server/conf.js';
8
8
  import fs from 'fs-extra';
9
9
  import { commitData } from '../src/client/components/core/CommonJs.js';
10
10
  import UnderpostScript from '../src/cli/script.js';
11
+ import { shellExec } from '../src/server/process.js';
12
+ import UnderpostDB from '../src/cli/db.js';
11
13
 
12
14
  const npmRoot = getNpmRootPath();
13
15
  const underpostRoot = `${npmRoot}/underpost/.env`;
@@ -28,6 +30,7 @@ program
28
30
  program
29
31
  .command('clone')
30
32
  .argument(`<uri>`, 'e.g. username/repository')
33
+ .option('--bare', 'Clone only .git files')
31
34
  .description('Clone github repository')
32
35
  .action(Underpost.repo.clone);
33
36
 
@@ -94,6 +97,14 @@ program
94
97
  })
95
98
  .description('Manage cluster, for default initialization base kind cluster');
96
99
 
100
+ program
101
+ .command('deploy')
102
+ .argument('<deploy-list>', 'Deploy id list, e.g. default-a, default-b')
103
+ .argument('[env]', 'Optional environment, for default is development')
104
+ .option('--remove', 'Delete deployments and services')
105
+ .description('Manage deployment, for default deploy development pods')
106
+ .action(Underpost.deploy.callback);
107
+
97
108
  program
98
109
  .command('secret')
99
110
  .argument('<platform>', `Options: ${Object.keys(Underpost.secret)}`)
@@ -130,6 +141,21 @@ program
130
141
  .description('Pull underpost dockerfile images requirements')
131
142
  .action(Underpost.image.dockerfile.pullBaseImages);
132
143
 
144
+ program
145
+ .command('install')
146
+ .description('Fast import underpost npm dependencies')
147
+ .action(() => {
148
+ fs.copySync(`${npmRoot}/underpost/node_modules`, './node_modules');
149
+ });
150
+
151
+ program
152
+ .command('db')
153
+ .argument('<deploy-list>', 'Deploy id list, e.g. default-a, default-b')
154
+ .option('--import', 'Import container backups from repositories')
155
+ .option('--export', 'Export container backups to repositories')
156
+ .description('Manage databases')
157
+ .action(UnderpostDB.API.callback);
158
+
133
159
  program
134
160
  .command('script')
135
161
  .argument('operator', `Options: ${Object.keys(UnderpostScript.API)}`)
@@ -140,6 +166,12 @@ program
140
166
  )
141
167
  .action((...args) => Underpost.script[args[0]](args[1], args[2]));
142
168
 
143
- program.command('test').description('Run tests').action(Underpost.test.run);
169
+ program
170
+ .command('test')
171
+ .argument('[deploy-list]', 'Deploy id list, e.g. default-a, default-b')
172
+ .description('Manage Test, for default run current underpost default test')
173
+ .option('--inside-container', 'Inside container execution context')
174
+ .option('--sh', 'Copy to clipboard, container entrypoint shell command')
175
+ .action(Underpost.test.callback);
144
176
 
145
177
  program.parse();
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.8.45'
61
+ engine.version: '2.8.47'
62
62
  networks:
63
63
  - load-balancer
64
64
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.8.45",
5
+ "version": "2.8.47",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -16,6 +16,7 @@
16
16
  "docs": "jsdoc -c jsdoc.json",
17
17
  "install-global": "npm install -g pm2 && npm install -g jsdoc && npm install -g prettier && npm install -g env-cmd && npm install -g yarn && npm install -g auto-changelog",
18
18
  "install-test": "npm install -g mocha && npm install -g c8 && npm install -g nyc && npm install -g coveralls",
19
+ "install-underpost": "cp -a $(npm root -g)/underpost/node_modules ./node_modules && npm install --only=dev --ignore-scripts",
19
20
  "install": "npm run install-global && npm run install-test",
20
21
  "docker:start": "docker-compose up",
21
22
  "prettier": "prettier --write .",
@@ -31,6 +32,10 @@
31
32
  "url": "git+https://github.com/underpostnet/pwa-microservices-template.git"
32
33
  },
33
34
  "keywords": [
35
+ "pwa",
36
+ "microservices",
37
+ "template",
38
+ "builder",
34
39
  "engine",
35
40
  "server",
36
41
  "proxy",
@@ -105,12 +110,17 @@
105
110
  "uglify-js": "^3.17.4",
106
111
  "validator": "^13.11.0",
107
112
  "vanilla-jsoneditor": "^2.3.2",
108
- "winston": "^3.11.0"
113
+ "winston": "^3.11.0",
114
+ "clean-jsdoc-theme": "^4.3.0",
115
+ "easy-json-schema": "^0.0.2-beta",
116
+ "mocha": "^10.8.2",
117
+ "plantuml": "^0.0.2",
118
+ "swagger-autogen": "^2.23.7"
109
119
  },
110
120
  "devDependencies": {
111
121
  "clean-jsdoc-theme": "^4.3.0",
112
122
  "easy-json-schema": "^0.0.2-beta",
113
- "mocha": "^10.4.0",
123
+ "mocha": "^10.8.2",
114
124
  "plantuml": "^0.0.2",
115
125
  "swagger-autogen": "^2.23.7"
116
126
  },
@@ -43,7 +43,7 @@ class UnderpostCluster {
43
43
  return;
44
44
  }
45
45
  const testClusterInit = shellExec(`kubectl get pods --all-namespaces -o wide`, {
46
- disableLogging: true,
46
+ disableLog: true,
47
47
  silent: true,
48
48
  stdout: true,
49
49
  });
@@ -93,7 +93,7 @@ class UnderpostCluster {
93
93
  silent: true,
94
94
  stdout: true,
95
95
  disableLog: true,
96
- }).match(`mongodb-0 1/1 Running`)
96
+ }).match(`mongodb-1 1/1 Running`)
97
97
  )
98
98
  return resolve();
99
99
  return monitor();
@@ -110,7 +110,7 @@ class UnderpostCluster {
110
110
  };
111
111
 
112
112
  shellExec(
113
- `kubectl exec -i mongodb-0 -- mongosh --quiet --json=relaxed \
113
+ `sudo kubectl exec -i mongodb-0 -- mongosh --quiet --json=relaxed \
114
114
  --eval 'use admin' \
115
115
  --eval 'rs.initiate(${JSON.stringify(mongoConfig)})' \
116
116
  --eval 'rs.status()'`,
package/src/cli/db.js ADDED
@@ -0,0 +1,148 @@
1
+ import { mergeFile, splitFileFactory } from '../server/conf.js';
2
+ import { loggerFactory } from '../server/logger.js';
3
+ import { shellExec } from '../server/process.js';
4
+ import fs from 'fs-extra';
5
+
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ class UnderpostDB {
9
+ static API = {
10
+ async callback(deployList = 'default', options = { import: false, export: false }) {
11
+ const newBackupTimestamp = new Date().getTime();
12
+ const nameSpace = 'default';
13
+ for (const _deployId of deployList.split(',')) {
14
+ const deployId = _deployId.trim();
15
+ if (!deployId) continue;
16
+ const dbs = {};
17
+ const repoName = `engine-${deployId.split('dd-')[1]}-cron-backups`;
18
+
19
+ const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
20
+ for (const host of Object.keys(confServer)) {
21
+ for (const path of Object.keys(confServer[host])) {
22
+ const { db } = confServer[host][path];
23
+ if (db) {
24
+ const { provider, name, user, password } = db;
25
+ if (!dbs[provider]) dbs[provider] = {};
26
+
27
+ if (!(name in dbs[provider]))
28
+ dbs[provider][name] = { user, password, hostFolder: host + path.replaceAll('/', '-') };
29
+ }
30
+ }
31
+ }
32
+
33
+ if (!fs.existsSync(`../${repoName}`)) {
34
+ shellExec(`cd .. && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}`);
35
+ } else {
36
+ shellExec(`cd ../${repoName} && underpost pull . ${process.env.GITHUB_USERNAME}/${repoName}`);
37
+ }
38
+
39
+ for (const provider of Object.keys(dbs)) {
40
+ for (const dbName of Object.keys(dbs[provider])) {
41
+ const { hostFolder, user, password } = dbs[provider][dbName];
42
+ if (hostFolder) {
43
+ logger.info('', { hostFolder, provider, dbName });
44
+
45
+ const backUpPath = `../${repoName}/${hostFolder}`;
46
+ const times = await fs.readdir(backUpPath);
47
+ const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)));
48
+ dbs[provider][dbName].currentBackupTimestamp = currentBackupTimestamp;
49
+ const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)));
50
+
51
+ const sqlContainerPath = `/home/${dbName}.sql`;
52
+ const _fromPartsParts = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}-parths.json`;
53
+ const _toSqlPath = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}.sql`;
54
+ const _toNewSqlPath = `../${repoName}/${hostFolder}/${newBackupTimestamp}/${dbName}.sql`;
55
+ const _toBsonPath = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}`;
56
+ const _toNewBsonPath = `../${repoName}/${hostFolder}/${newBackupTimestamp}/${dbName}`;
57
+
58
+ if (options.import === true && fs.existsSync(_fromPartsParts) && !fs.existsSync(_toSqlPath)) {
59
+ const names = JSON.parse(fs.readFileSync(_fromPartsParts, 'utf8')).map((_path) => {
60
+ return `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${_path.split('/').pop()}`;
61
+ });
62
+ logger.info('merge Back Up paths', {
63
+ _fromPartsParts,
64
+ _toSqlPath,
65
+ names,
66
+ });
67
+ await mergeFile(names, _toSqlPath);
68
+ }
69
+
70
+ if (options.export === true && times.length >= 5) {
71
+ fs.removeSync(`../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
72
+ fs.mkdirSync(`../${repoName}/${hostFolder}/${newBackupTimestamp}`, { recursive: true });
73
+ }
74
+
75
+ switch (provider) {
76
+ case 'mariadb': {
77
+ const podName = `mariadb-statefulset-0`;
78
+ const serviceName = 'mariadb';
79
+ if (options.import === true) {
80
+ shellExec(`sudo kubectl cp ${_toSqlPath} ${nameSpace}/${podName}:/${dbName}.sql`);
81
+ const cmd = `mariadb -u ${user} -p${password} ${dbName} < /${dbName}.sql`;
82
+ shellExec(
83
+ `kubectl exec -i ${podName} -- ${serviceName} -p${password} -e 'CREATE DATABASE ${dbName};'`,
84
+ );
85
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
86
+ }
87
+ if (options.export === true) {
88
+ const cmd = `mariadb-dump --user=${user} --password=${password} --lock-tables ${dbName} > ${sqlContainerPath}`;
89
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
90
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${sqlContainerPath} ${_toNewSqlPath}`);
91
+ await splitFileFactory(dbName, _toNewSqlPath);
92
+ }
93
+ break;
94
+ }
95
+
96
+ case 'mongoose': {
97
+ if (options.import === true) {
98
+ const podName = `mongodb-0`;
99
+ shellExec(`sudo kubectl cp ${_toBsonPath} ${nameSpace}/${podName}:/${dbName}`);
100
+ const cmd = `mongorestore -d ${dbName} /${dbName}`;
101
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
102
+ }
103
+ if (options.export === true) {
104
+ const podName = `backup-access`;
105
+ const containerBaseBackupPath = '/backup';
106
+ let timeFolder = shellExec(
107
+ `sudo kubectl exec -i ${podName} -- sh -c "cd ${containerBaseBackupPath} && ls -a"`,
108
+ {
109
+ stdout: true,
110
+ disableLog: false,
111
+ silent: true,
112
+ },
113
+ ).split(`\n`);
114
+ timeFolder = timeFolder[timeFolder.length - 2];
115
+ if (timeFolder === '..') {
116
+ logger.warn(`Cannot backup available`, { timeFolder });
117
+ } else {
118
+ shellExec(
119
+ `sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
120
+ );
121
+ }
122
+ }
123
+ break;
124
+ }
125
+
126
+ default:
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ }
132
+ if (options.export === true) {
133
+ shellExec(`cd ../${repoName} && git add .`);
134
+ shellExec(
135
+ `underpost cmt ../${repoName} backup '' '${new Date(newBackupTimestamp).toLocaleDateString()} ${new Date(
136
+ newBackupTimestamp,
137
+ ).toLocaleTimeString()}'`,
138
+ );
139
+ shellExec(`cd ../${repoName} && underpost push . ${process.env.GITHUB_USERNAME}/${repoName}`, {
140
+ disableLog: true,
141
+ });
142
+ }
143
+ }
144
+ },
145
+ };
146
+ }
147
+
148
+ export default UnderpostDB;
@@ -0,0 +1,95 @@
1
+ import { loggerFactory } from '../server/logger.js';
2
+ import { shellExec } from '../server/process.js';
3
+ import fs from 'fs-extra';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ class UnderpostDeploy {
8
+ static API = {
9
+ callback: (deployList = 'default', env = 'development', options = { remove: false }) => {
10
+ for (const _deployId of deployList.split(',')) {
11
+ const deployId = _deployId.trim();
12
+ if (!deployId) continue;
13
+
14
+ shellExec(`sudo kubectl delete svc ${deployId}-${env}-service`);
15
+ shellExec(`sudo kubectl delete deployment ${deployId}-${env}`);
16
+
17
+ const etcHost = (
18
+ concat,
19
+ ) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
20
+ ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
21
+ let concatHots = '';
22
+
23
+ const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
24
+ for (const host of Object.keys(confServer)) {
25
+ shellExec(`sudo kubectl delete HTTPProxy ${host}`);
26
+ if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
27
+ }
28
+
29
+ if (!options.remove === true) {
30
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/${deployId}-${env}/deployment.yaml`);
31
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/${deployId}-${env}/proxy.yaml`);
32
+ }
33
+
34
+ let renderHosts;
35
+
36
+ switch (process.platform) {
37
+ case 'linux':
38
+ {
39
+ switch (env) {
40
+ case 'development':
41
+ renderHosts = etcHost(concatHots);
42
+ fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
43
+
44
+ break;
45
+
46
+ default:
47
+ break;
48
+ }
49
+ }
50
+ break;
51
+
52
+ default:
53
+ break;
54
+ }
55
+ logger.info(
56
+ `
57
+ ` + renderHosts,
58
+ );
59
+ }
60
+ },
61
+ getPods(deployId) {
62
+ const raw = shellExec(`sudo kubectl get pods --all-namespaces -o wide`, {
63
+ stdout: true,
64
+ disableLog: false,
65
+ silent: true,
66
+ });
67
+
68
+ const heads = raw
69
+ .split(`\n`)[0]
70
+ .split(' ')
71
+ .filter((_r) => _r.trim());
72
+
73
+ const pods = raw
74
+ .split(`\n`)
75
+ .filter((r) => (deployId ? r.match(deployId) : r.trim() && !r.match('NAME')))
76
+ .map((r) => r.split(' ').filter((_r) => _r.trim()));
77
+
78
+ const result = [];
79
+
80
+ for (const row of pods) {
81
+ const pod = {};
82
+ let index = -1;
83
+ for (const head of heads) {
84
+ index++;
85
+ pod[head] = row[index];
86
+ }
87
+ result.push(pod);
88
+ }
89
+
90
+ return result;
91
+ },
92
+ };
93
+ }
94
+
95
+ export default UnderpostDeploy;
package/src/cli/image.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import fs from 'fs-extra';
2
2
  import Underpost from '../index.js';
3
3
  import { shellExec } from '../server/process.js';
4
- import { MariaDB } from '../db/mariadb/MariaDB.js';
5
4
  import dotenv from 'dotenv';
6
5
  import { getNpmRootPath } from '../server/conf.js';
7
6
 
@@ -19,7 +18,7 @@ class UnderpostImage {
19
18
  const imagesStoragePath = `./images`;
20
19
  const tarFile = `${imagesStoragePath}/${imgName.replace(':', '_')}.tar`;
21
20
 
22
- let secrets = '';
21
+ let secrets = ' ';
23
22
  let secretDockerInput = '';
24
23
 
25
24
  const envObj = dotenv.parse(fs.readFileSync(`${getNpmRootPath()}/underpost/.env`, 'utf8'));
@@ -45,17 +44,6 @@ class UnderpostImage {
45
44
  case 'dd-lampp':
46
45
  {
47
46
  const lamppPublicPath = '/xampp/htdocs/online';
48
- if (process.argv.includes('test')) {
49
- const { MARIADB_HOST, MARIADB_USER, MARIADB_PASSWORD, DD_LAMPP_TEST_DB_0 } = process.env;
50
-
51
- await MariaDB.query({
52
- host: MARIADB_HOST,
53
- user: MARIADB_USER,
54
- password: MARIADB_PASSWORD,
55
- query: `SHOW TABLES FROM ${DD_LAMPP_TEST_DB_0}`,
56
- });
57
- process.exit(0);
58
- }
59
47
  shellExec(`sudo mkdir -p ${lamppPublicPath}`);
60
48
 
61
49
  {
@@ -11,11 +11,13 @@ const logger = loggerFactory(import.meta);
11
11
 
12
12
  class UnderpostRepository {
13
13
  static API = {
14
- clone(gitUri = 'underpostnet/pwa-microservices-template') {
14
+ clone(gitUri = 'underpostnet/pwa-microservices-template', options = { bare: false }) {
15
15
  const repoName = gitUri.split('/').pop();
16
16
  if (fs.existsSync(`./${repoName}`)) fs.removeSync(`./${repoName}`);
17
17
  return shellExec(
18
- `git clone https://${process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''}github.com/${gitUri}.git`,
18
+ `git clone ${options?.bare === true ? ` --bare ` : ''}https://${
19
+ process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''
20
+ }github.com/${gitUri}.git`,
19
21
  {
20
22
  disableLog: true,
21
23
  },
@@ -52,6 +54,10 @@ class UnderpostRepository {
52
54
  empty: false,
53
55
  },
54
56
  ) {
57
+ if (commitType === 'reset') {
58
+ shellExec(`cd ${repoPath} && git reset --soft HEAD~${isNaN(parseInt(subModule)) ? 1 : parseInt(subModule)}`);
59
+ return;
60
+ }
55
61
  if (options.info) return logger.info('', commitData);
56
62
  const _message = `${commitType}${subModule ? `(${subModule})` : ''}${process.argv.includes('!') ? '!' : ''}: ${
57
63
  commitData[commitType].emoji
@@ -81,18 +87,16 @@ class UnderpostRepository {
81
87
  return new Promise(async (resolve, reject) => {
82
88
  try {
83
89
  const exeRootPath = `${getNpmRootPath()}/underpost`;
84
- // const exeRootPath = '/home/dd/pwa-microservices-template';
85
90
  actionInitLog();
86
91
  await logger.setUpInfo();
87
- const destFolder = `${process.cwd()}/${repositoryName}`;
92
+ const destFolder = `./${repositoryName}`;
88
93
  logger.info('Note: This process may take several minutes to complete');
89
94
  logger.info('build app', { destFolder });
95
+ if (fs.existsSync(destFolder)) fs.removeSync(destFolder);
90
96
  fs.mkdirSync(destFolder, { recursive: true });
91
97
  fs.copySync(exeRootPath, destFolder);
92
- if (fs.existsSync(`${destFolder}/node_modules`)) fs.removeSync(`${destFolder}/node_modules`);
93
98
  fs.writeFileSync(`${destFolder}/.gitignore`, fs.readFileSync(`${exeRootPath}/.dockerignore`, 'utf8'), 'utf8');
94
99
  shellExec(`cd ${destFolder} && git init && git add . && git commit -m "Base template implementation"`);
95
- shellExec(`cd ${destFolder} && npm install`);
96
100
  shellExec(`cd ${destFolder} && npm run build`);
97
101
  shellExec(`cd ${destFolder} && npm run dev`);
98
102
  return resolve();
package/src/cli/test.js CHANGED
@@ -1,6 +1,8 @@
1
+ import { MariaDB } from '../db/mariadb/MariaDB.js';
1
2
  import { getNpmRootPath } from '../server/conf.js';
2
3
  import { actionInitLog, loggerFactory } from '../server/logger.js';
3
- import { shellExec } from '../server/process.js';
4
+ import { pbcopy, shellExec } from '../server/process.js';
5
+ import UnderpostDeploy from './deploy.js';
4
6
 
5
7
  const logger = loggerFactory(import.meta);
6
8
 
@@ -26,6 +28,52 @@ class UnderpostTest {
26
28
  actionInitLog();
27
29
  shellExec(`cd ${getNpmRootPath()}/underpost && npm run test`);
28
30
  },
31
+ async callback(deployList = '', options = { insideContainer: false, sh: false }) {
32
+ if (options.sh === true) {
33
+ const [pod] = UnderpostDeploy.API.getPods(deployList);
34
+ if (pod) return pbcopy(`sudo kubectl exec -it ${pod.NAME} -- sh`);
35
+ return logger.warn(`Couldn't find pods in deployment`, deployList);
36
+ }
37
+ if (deployList) {
38
+ for (const _deployId of deployList.split(',')) {
39
+ const deployId = _deployId.trim();
40
+ if (!deployId) continue;
41
+ if (options.insideContainer === true)
42
+ switch (deployId) {
43
+ case 'dd-lampp':
44
+ {
45
+ const { MARIADB_HOST, MARIADB_USER, MARIADB_PASSWORD, DD_LAMPP_TEST_DB_0 } = process.env;
46
+
47
+ await MariaDB.query({
48
+ host: MARIADB_HOST,
49
+ user: MARIADB_USER,
50
+ password: MARIADB_PASSWORD,
51
+ query: `SHOW TABLES FROM ${DD_LAMPP_TEST_DB_0}`,
52
+ });
53
+ }
54
+ break;
55
+
56
+ default:
57
+ {
58
+ shellExec('npm run test');
59
+ }
60
+
61
+ break;
62
+ }
63
+ else {
64
+ const pods = UnderpostDeploy.API.getPods(deployId);
65
+ if (pods.length > 0)
66
+ for (const deployData of pods) {
67
+ const { NAME } = deployData;
68
+ shellExec(
69
+ `sudo kubectl exec -i ${NAME} -- sh -c "cd /home/dd/engine && underpost test ${deployId} --inside-container"`,
70
+ );
71
+ }
72
+ else logger.warn(`Couldn't find pods in deployment`, { deployId });
73
+ }
74
+ }
75
+ } else return UnderpostTest.API.run();
76
+ },
29
77
  };
30
78
  }
31
79
 
@@ -3,7 +3,10 @@ import { Account } from './Account.js';
3
3
  import { loggerFactory } from './Logger.js';
4
4
  import { LogIn } from './LogIn.js';
5
5
  import { LogOut } from './LogOut.js';
6
+ import { NotificationManager } from './NotificationManager.js';
6
7
  import { SignUp } from './SignUp.js';
8
+ import { Translate } from './Translate.js';
9
+ import { s } from './VanillaJs.js';
7
10
 
8
11
  const logger = loggerFactory(import.meta);
9
12
 
@@ -65,6 +68,7 @@ const Auth = {
65
68
  const _result = await UserService.get({ id: 'auth' });
66
69
  return {
67
70
  status: _result.status,
71
+ message: _result.message,
68
72
  data: {
69
73
  user: _result.data,
70
74
  },
@@ -77,6 +81,15 @@ const Auth = {
77
81
  await Account.updateForm(data.user);
78
82
  return { user: data.user };
79
83
  }
84
+ if (message && message.match('expired'))
85
+ setTimeout(() => {
86
+ s(`.main-btn-log-in`).click();
87
+ NotificationManager.Push({
88
+ html: Translate.Render(`expired-session`),
89
+ status: 'warning',
90
+ });
91
+ });
92
+ return await Auth.sessionOut();
80
93
  }
81
94
 
82
95
  // anon guest session
@@ -92,20 +105,25 @@ const Auth = {
92
105
 
93
106
  this.setGuestToken(guestToken);
94
107
  let { data, status, message } = await UserService.get({ id: 'auth' });
95
- if (status === 'error') throw new Error(message);
108
+ if (status === 'error') {
109
+ if (message && message.match('expired')) {
110
+ localStorage.removeItem('jwt.g');
111
+ return await Auth.sessionOut();
112
+ } else throw new Error(message);
113
+ }
96
114
  await Account.updateForm(data);
97
115
  return { user: data };
98
116
  } catch (error) {
99
117
  logger.error(error);
100
- localStorage.removeItem('jwt');
101
- localStorage.removeItem('jwt.g');
102
118
  return { user: UserMock.default };
103
119
  }
104
120
  },
105
121
  sessionOut: async function () {
106
122
  this.deleteToken();
107
123
  localStorage.removeItem('jwt');
108
- await LogOut.Trigger(await this.sessionIn());
124
+ const result = await this.sessionIn();
125
+ await LogOut.Trigger(result);
126
+ return result;
109
127
  },
110
128
  };
111
129
 
@@ -508,6 +508,10 @@ const TranslateCore = {
508
508
  en: 'Invalid identity document',
509
509
  es: 'Documento de identidad inválido',
510
510
  };
511
+ Translate.Data['expired-session'] = {
512
+ en: 'Your session has expired. Please log in again.',
513
+ es: 'Su sesión ha expirado. Por favor, inicie sesión de nuevo.',
514
+ };
511
515
  },
512
516
  };
513
517
 
package/src/index.js CHANGED
@@ -5,6 +5,8 @@
5
5
  */
6
6
 
7
7
  import UnderpostCluster from './cli/cluster.js';
8
+ import UnderpostDB from './cli/db.js';
9
+ import UnderpostDeploy from './cli/deploy.js';
8
10
  import UnderpostRootEnv from './cli/env.js';
9
11
  import UnderpostImage from './cli/image.js';
10
12
  import UnderpostRepository from './cli/repository.js';
@@ -24,7 +26,7 @@ class Underpost {
24
26
  * @type {String}
25
27
  * @memberof Underpost
26
28
  */
27
- static version = 'v2.8.45';
29
+ static version = 'v2.8.47';
28
30
  /**
29
31
  * Repository cli API
30
32
  * @static
@@ -74,6 +76,20 @@ class Underpost {
74
76
  * @memberof Underpost
75
77
  */
76
78
  static script = UnderpostScript.API;
79
+ /**
80
+ * Database cli API
81
+ * @static
82
+ * @type {UnderpostDB.API}
83
+ * @memberof Underpost
84
+ */
85
+ static db = UnderpostDB.API;
86
+ /**
87
+ * Deployment cli API
88
+ * @static
89
+ * @type {UnderpostDeploy.API}
90
+ * @memberof Underpost
91
+ */
92
+ static deploy = UnderpostDeploy.API;
77
93
  }
78
94
 
79
95
  const up = Underpost;
@@ -525,9 +525,11 @@ const buildPortProxyRouter = (port, proxyRouter) => {
525
525
 
526
526
  if (Object.keys(router).length === 0) return router;
527
527
 
528
+ const reOrderRouter = {};
528
529
  for (const absoluteHostKey of orderArrayFromAttrInt(Object.keys(router), 'length'))
529
- router[absoluteHostKey] = router[absoluteHostKey];
530
- return router;
530
+ reOrderRouter[absoluteHostKey] = router[absoluteHostKey];
531
+
532
+ return reOrderRouter;
531
533
  };
532
534
 
533
535
  const cliBar = async (time = 5000) => {
@@ -85,6 +85,7 @@ const format = (meta) =>
85
85
  */
86
86
  const setUpInfo = async (logger = new winston.Logger()) => {
87
87
  logger.info('argv', process.argv);
88
+ logger.info('cwd', process.cwd());
88
89
  logger.info('platform', process.platform);
89
90
  logger.info('env', process.env.NODE_ENV);
90
91
  logger.info('--max-old-space-size', {
@@ -39,7 +39,7 @@ const saveRuntimeRouter = async () => {
39
39
  const host = process.env.DEFAULT_DEPLOY_HOST;
40
40
  const path = process.env.DEFAULT_DEPLOY_PATH;
41
41
  const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
42
- if (!deployId || !host || !path) {
42
+ if (!deployId || !host || !path || !fs.existsSync(confServerPath)) {
43
43
  // logger.warn('default deploy instance not found');
44
44
  return;
45
45
  }
@@ -120,7 +120,14 @@ const saveRuntimeCron = async () => {
120
120
 
121
121
  const listenServerFactory = (logic = async () => {}) => {
122
122
  return {
123
- listen: async (...args) => (logic ? await logic(...args) : undefined, args[1]()),
123
+ listen: async (...args) => (
124
+ setTimeout(() => {
125
+ const message = 'Listen server factory timeout';
126
+ logger.error(message);
127
+ throw new Error(message);
128
+ }, 80000000), // ~ 55 days
129
+ (logic ? await logic(...args) : undefined, args[1]())
130
+ ),
124
131
  };
125
132
  };
126
133