underpost 3.2.10 → 3.2.12

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 (54) hide show
  1. package/.vscode/extensions.json +9 -9
  2. package/.vscode/settings.json +12 -1
  3. package/CHANGELOG.md +92 -1
  4. package/CLI-HELP.md +80 -26
  5. package/README.md +6 -10
  6. package/bin/build.js +9 -6
  7. package/bin/build.template.js +187 -0
  8. package/bin/deploy.js +29 -18
  9. package/conf.js +1 -4
  10. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  11. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  12. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  13. package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
  14. package/manifests/lxd/lxd-admin-profile.yaml +12 -3
  15. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  16. package/manifests/mongodb-4.4/kustomization.yaml +3 -1
  17. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  18. package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
  19. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  20. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  21. package/manifests/valkey/statefulset.yaml +1 -1
  22. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  23. package/package.json +3 -3
  24. package/scripts/ipxe-setup.sh +52 -49
  25. package/scripts/k3s-node-setup.sh +84 -68
  26. package/scripts/lxd-vm-setup.sh +193 -8
  27. package/scripts/maas-nat-firewalld.sh +145 -0
  28. package/src/cli/baremetal.js +115 -93
  29. package/src/cli/cluster.js +548 -221
  30. package/src/cli/deploy.js +131 -166
  31. package/src/cli/fs.js +11 -3
  32. package/src/cli/index.js +75 -17
  33. package/src/cli/lxd.js +1034 -240
  34. package/src/cli/monitor.js +9 -3
  35. package/src/cli/release.js +72 -36
  36. package/src/cli/repository.js +10 -16
  37. package/src/cli/run.js +72 -55
  38. package/src/cli/secrets.js +11 -2
  39. package/src/client/components/core/Auth.js +4 -3
  40. package/src/client/components/core/ClientEvents.js +76 -0
  41. package/src/client/components/core/EventBus.js +4 -0
  42. package/src/client/components/core/Modal.js +82 -41
  43. package/src/db/DataBaseProvider.js +9 -9
  44. package/src/db/mariadb/MariaDB.js +2 -1
  45. package/src/db/mongo/MongoBootstrap.js +592 -522
  46. package/src/db/mongo/MongooseDB.js +19 -15
  47. package/src/index.js +1 -1
  48. package/src/server/conf.js +67 -19
  49. package/src/server/proxy.js +9 -2
  50. package/src/server/start.js +8 -4
  51. package/src/server/valkey.js +2 -0
  52. package/bin/file.js +0 -220
  53. package/bin/vs.js +0 -74
  54. package/bin/zed.js +0 -84
@@ -1,5 +1,6 @@
1
1
  import mongoose from 'mongoose';
2
2
  import { getCapVariableName } from '../../client/components/core/CommonJs.js';
3
+ import { loggerFactory } from '../../server/logger.js';
3
4
 
4
5
  /**
5
6
  * Module for connecting to and loading models for a MongoDB database using Mongoose.
@@ -7,14 +8,14 @@ import { getCapVariableName } from '../../client/components/core/CommonJs.js';
7
8
  * @namespace MongooseDBService
8
9
  */
9
10
 
11
+ const logger = loggerFactory(import.meta);
12
+
10
13
  const MONGODB_SERVICE_NAME = 'mongodb-service';
11
14
  const MONGODB_STATEFULSET_NAME = 'mongodb';
12
15
  const MONGODB_DEFAULT_AUTH_SOURCE = 'admin';
13
16
  const MONGODB_DEFAULT_REPLICA_SET = 'rs0';
14
17
  const MONGODB_DEFAULT_REPLICA_COUNT = 3;
15
18
 
16
-
17
-
18
19
  /**
19
20
  * Resolves MongoDB replica hosts from explicit input or StatefulSet defaults.
20
21
  * @param {{hostList?: string, replicaCount?: number}} [options] - Host resolution options.
@@ -66,13 +67,11 @@ class MongooseDBService {
66
67
  * Normalizes connection config from object or legacy host/name signature.
67
68
  * @param {object|string} configOrHost - Connection config object or host string.
68
69
  * @param {string} [name] - Legacy DB name when using host string input.
69
- * @returns {{authSource: string, dbName: string, hosts: Array<string>, password: string, replicaSet: string, user: string}} Normalized config.
70
+ * @returns {{authSource: string, dbName: string, directConnection: boolean, hosts: Array<string>, password: string, replicaSet: string, user: string}} Normalized config.
70
71
  */
71
72
  normalizeConfig(configOrHost, name) {
72
73
  const config =
73
- typeof configOrHost === 'object' && configOrHost !== null
74
- ? { ...configOrHost }
75
- : { host: configOrHost, name };
74
+ typeof configOrHost === 'object' && configOrHost !== null ? { ...configOrHost } : { host: configOrHost, name };
76
75
 
77
76
  const rawHosts = config.host || process.env.DB_HOST;
78
77
  const hosts = this.normalizeHosts(rawHosts);
@@ -87,14 +86,16 @@ class MongooseDBService {
87
86
 
88
87
  const user = config.user || process.env.DB_USER || '';
89
88
  const password = config.password || process.env.DB_PASSWORD || '';
90
- const replicaSet =
91
- config.replicaSet || process.env.DB_REPLICA_SET || (hosts.length > 1 ? MONGODB_DEFAULT_REPLICA_SET : '');
92
- const authSource =
93
- config.authSource || process.env.DB_AUTH_SOURCE || (user ? MONGODB_DEFAULT_AUTH_SOURCE : '');
89
+ const directConnection = hosts.length === 1;
90
+ const replicaSet = directConnection
91
+ ? ''
92
+ : config.replicaSet || process.env.DB_REPLICA_SET || MONGODB_DEFAULT_REPLICA_SET;
93
+ const authSource = config.authSource || process.env.DB_AUTH_SOURCE || (user ? MONGODB_DEFAULT_AUTH_SOURCE : '');
94
94
 
95
95
  return {
96
96
  authSource,
97
97
  dbName,
98
+ directConnection,
98
99
  hosts,
99
100
  password,
100
101
  replicaSet,
@@ -110,12 +111,14 @@ class MongooseDBService {
110
111
  */
111
112
  buildUri(configOrHost, name) {
112
113
  const config = this.normalizeConfig(configOrHost, name);
113
- const credentials = config.user && config.password
114
- ? `${encodeURIComponent(config.user)}:${encodeURIComponent(config.password)}@`
115
- : '';
114
+ const credentials =
115
+ config.user && config.password
116
+ ? `${encodeURIComponent(config.user)}:${encodeURIComponent(config.password)}@`
117
+ : '';
116
118
  const query = new URLSearchParams();
117
119
 
118
- if (config.replicaSet) query.set('replicaSet', config.replicaSet);
120
+ if (config.directConnection) query.set('directConnection', 'true');
121
+ else if (config.replicaSet) query.set('replicaSet', config.replicaSet);
119
122
  if (config.authSource) query.set('authSource', config.authSource);
120
123
 
121
124
  return `mongodb://${credentials}${config.hosts.join(',')}/${config.dbName}${query.size ? `?${query.toString()}` : ''}`;
@@ -138,6 +141,7 @@ class MongooseDBService {
138
141
  */
139
142
  async connect(configOrHost, name) {
140
143
  const uri = this.buildUri(configOrHost, name);
144
+ if (process.env.NODE_ENV === 'development') logger.info(`Connecting to MongoDB with URI`, uri);
141
145
  return await mongoose
142
146
  .createConnection(uri, {
143
147
  autoIndex: process.env.NODE_ENV !== 'production',
@@ -190,5 +194,5 @@ export {
190
194
  MONGODB_DEFAULT_REPLICA_SET,
191
195
  MONGODB_SERVICE_NAME,
192
196
  MONGODB_STATEFULSET_NAME,
193
- resolveMongoReplicaHosts
197
+ resolveMongoReplicaHosts,
194
198
  };
package/src/index.js CHANGED
@@ -44,7 +44,7 @@ class Underpost {
44
44
  * @type {String}
45
45
  * @memberof Underpost
46
46
  */
47
- static version = 'v3.2.10';
47
+ static version = 'v3.2.12';
48
48
 
49
49
  /**
50
50
  * Required Node.js major version
@@ -334,25 +334,29 @@ const Config = {
334
334
 
335
335
  if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
336
336
 
337
- const envTemplate = fs.existsSync('./.env.example')
337
+ const sharedEnvTemplate = fs.existsSync('./.env.example')
338
338
  ? fs.readFileSync('./.env.example', 'utf8')
339
339
  : fs.existsSync('./.env.production')
340
340
  ? fs.readFileSync('./.env.production', 'utf8')
341
341
  : '';
342
342
 
343
- if (envTemplate) {
344
- const prodEnv = envTemplate.replaceAll('dd-default', deployId);
345
- fs.writeFileSync(`${folder}/.env.production`, prodEnv, 'utf8');
346
- fs.writeFileSync(
347
- `${folder}/.env.development`,
348
- prodEnv.replace('NODE_ENV=production', 'NODE_ENV=development').replace('PORT=3000', 'PORT=4000'),
349
- 'utf8',
350
- );
351
- fs.writeFileSync(
352
- `${folder}/.env.test`,
353
- prodEnv.replace('NODE_ENV=production', 'NODE_ENV=test').replace('PORT=3000', 'PORT=5000'),
354
- 'utf8',
355
- );
343
+ const envTemplates = {
344
+ production: fs.existsSync('./.env.production') ? fs.readFileSync('./.env.production', 'utf8') : sharedEnvTemplate,
345
+ development: fs.existsSync('./.env.development')
346
+ ? fs.readFileSync('./.env.development', 'utf8')
347
+ : sharedEnvTemplate
348
+ ? sharedEnvTemplate.replace('NODE_ENV=production', 'NODE_ENV=development').replace('PORT=3000', 'PORT=4000')
349
+ : '',
350
+ test: fs.existsSync('./.env.test')
351
+ ? fs.readFileSync('./.env.test', 'utf8')
352
+ : sharedEnvTemplate
353
+ ? sharedEnvTemplate.replace('NODE_ENV=production', 'NODE_ENV=test').replace('PORT=3000', 'PORT=5000')
354
+ : '',
355
+ };
356
+
357
+ for (const [envName, envTemplate] of Object.entries(envTemplates)) {
358
+ if (!envTemplate) continue;
359
+ fs.writeFileSync(`${folder}/.env.${envName}`, envTemplate.replaceAll('dd-default', deployId), 'utf8');
356
360
  }
357
361
 
358
362
  fs.writeFileSync(
@@ -1222,7 +1226,11 @@ const validateTemplatePath = (absolutePath = '') => {
1222
1226
  const confSsr = DefaultConf.ssr[ssr];
1223
1227
  const clients = DefaultConf.client.default.services;
1224
1228
 
1225
- if (absolutePath.match('src/api') && !absolutePath.match('src/api/types.js') && !confServer.apis.find((p) => absolutePath.match(`src/api/${p}/`))) {
1229
+ if (
1230
+ absolutePath.match('src/api') &&
1231
+ !absolutePath.match('src/api/types.js') &&
1232
+ !confServer.apis.find((p) => absolutePath.match(`src/api/${p}/`))
1233
+ ) {
1226
1234
  return false;
1227
1235
  }
1228
1236
  if (absolutePath.match('conf.dd-') && absolutePath.match('.js')) return false;
@@ -1287,16 +1295,17 @@ const validateTemplatePath = (absolutePath = '') => {
1287
1295
  /**
1288
1296
  * @method awaitDeployMonitor
1289
1297
  * @description Waits for the deploy monitor.
1290
- * @param {boolean} [init=false] - The init flag.
1298
+ * @param {boolean} [isFinal=false] - If true, logs when the final (non-replica) deployment completes.
1291
1299
  * @param {number} [deltaMs=1000] - The delta ms.
1292
1300
  * @returns {Promise<void>} - The await deploy monitor.
1293
1301
  * @memberof ServerConfBuilder
1294
1302
  */
1295
- const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
1296
- if (init) Underpost.env.set('await-deploy', new Date().toISOString());
1303
+ const awaitDeployMonitor = async (isFinal = false, deltaMs = 1000) => {
1304
+ Underpost.env.set('await-deploy', new Date().toISOString());
1305
+ if (isFinal) logger.info('Final deployment running (no replica)');
1297
1306
  await timer(deltaMs);
1298
1307
  if (Underpost.env.get('container-status') === 'error') throw new Error('Container status error');
1299
- if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor();
1308
+ if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor(isFinal, deltaMs);
1300
1309
  };
1301
1310
 
1302
1311
  /**
@@ -1701,6 +1710,44 @@ const loadConfServerJson = (jsonPath, options) => {
1701
1710
  return options && options.resolve === true ? resolveConfSecrets(raw) : raw;
1702
1711
  };
1703
1712
 
1713
+ /**
1714
+ * Creates and writes the /etc/hosts file for a deployment.
1715
+ * @method etcHostFactory
1716
+ * @param {Array<string>} hosts - List of hosts to be added to the hosts file.
1717
+ * @param {object} options - Options for the hosts file creation.
1718
+ * @param {boolean} options.append - Whether to append to the existing hosts file.
1719
+ * @returns {object} - Object containing the rendered hosts file.
1720
+ * @memberof ServerConfBuilder
1721
+ */
1722
+ const etcHostFactory = (hosts = [], options = { append: false }) => {
1723
+ hosts = hosts.map((host) => {
1724
+ try {
1725
+ if (!host.startsWith('http')) host = `http://${host}`;
1726
+ const hostname = new URL(host).hostname;
1727
+ logger.info('Hostname extract valid', { host, hostname });
1728
+ return hostname;
1729
+ } catch (e) {
1730
+ logger.warn('No hostname extract valid', host);
1731
+ return host;
1732
+ }
1733
+ });
1734
+ const renderHosts = `127.0.0.1 ${hosts.join(
1735
+ ' ',
1736
+ )} localhost localhost.localdomain localhost4 localhost4.localdomain4
1737
+ ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
1738
+
1739
+ if (options && options.append && fs.existsSync(`/etc/hosts`)) {
1740
+ fs.writeFileSync(
1741
+ `/etc/hosts`,
1742
+ fs.readFileSync(`/etc/hosts`, 'utf8') +
1743
+ `
1744
+ ${renderHosts}`,
1745
+ 'utf8',
1746
+ );
1747
+ } else fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
1748
+ return { renderHosts };
1749
+ };
1750
+
1704
1751
  export {
1705
1752
  Config,
1706
1753
  loadConf,
@@ -1747,4 +1794,5 @@ export {
1747
1794
  DEFAULT_DEPLOY_ID,
1748
1795
  loadCronDeployEnv,
1749
1796
  cronDeployIdResolve,
1797
+ etcHostFactory,
1750
1798
  };
@@ -9,7 +9,14 @@
9
9
  import express from 'express';
10
10
  import { createProxyMiddleware } from 'http-proxy-middleware';
11
11
  import { loggerFactory, loggerMiddleware } from './logger.js';
12
- import { buildPortProxyRouter, buildProxyRouter, getTlsHosts, isDevProxyContext, isTlsDevProxy } from './conf.js';
12
+ import {
13
+ buildPortProxyRouter,
14
+ buildProxyRouter,
15
+ etcHostFactory,
16
+ getTlsHosts,
17
+ isDevProxyContext,
18
+ isTlsDevProxy,
19
+ } from './conf.js';
13
20
 
14
21
  import { shellExec } from './process.js';
15
22
  import fs from 'fs-extra';
@@ -114,7 +121,7 @@ class ProxyService {
114
121
  logger.info('Proxy running', { port, router: options.router });
115
122
  if (process.env.NODE_ENV === 'development')
116
123
  logger.info(
117
- Underpost.deploy.etcHostFactory(Object.keys(options.router), {
124
+ etcHostFactory(Object.keys(options.router), {
118
125
  append: true,
119
126
  }).renderHosts,
120
127
  );
@@ -52,7 +52,7 @@ class UnderpostStartUp {
52
52
  * @param {Function} logic - The logic to execute when the server is listening.
53
53
  * @returns {Object} An object with a listen method.
54
54
  */
55
- listenServerFactory: (logic = async () => { }) => {
55
+ listenServerFactory: (logic = async () => {}) => {
56
56
  return {
57
57
  listen: async (...args) => {
58
58
  const msDelta = 1000;
@@ -211,15 +211,19 @@ class UnderpostStartUp {
211
211
  shellExec(`node bin env ${replica} ${env}`);
212
212
  const replicaCmd = `npm ${runCmd} ${replica}`;
213
213
  shellExec(replicaCmd, { async: true, callback: makeDeployCallback(replicaCmd) });
214
- await awaitDeployMonitor(true);
214
+ await awaitDeployMonitor();
215
215
  }
216
216
  }
217
217
  shellExec(`node bin env ${deployId} ${env}`);
218
218
  const deployCmd = `npm ${runCmd} ${deployId}`;
219
219
  shellExec(deployCmd, { async: true, callback: makeDeployCallback(deployCmd) });
220
220
  await awaitDeployMonitor(true);
221
- if (env === 'production' && Underpost.env.isInsideContainer()) Underpost.secret.globalSecretClean();
222
- if (Underpost.env.get('container-status') !== 'error') Underpost.env.set('container-status', `${deployId}-${env}-running-deployment`);
221
+ if (Underpost.env.get('container-status') !== 'error') {
222
+ if (env === 'production' && Underpost.env.isInsideContainer()) Underpost.secret.globalSecretClean();
223
+ Underpost.env.set('container-status', `${deployId}-${env}-running-deployment`);
224
+ } else {
225
+ Underpost.env.set('container-status', 'error');
226
+ }
223
227
  },
224
228
  };
225
229
  }
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import Valkey from 'iovalkey';
16
16
  import { loggerFactory } from './logger.js';
17
+ import Underpost from '../index.js';
17
18
 
18
19
  const logger = loggerFactory(import.meta);
19
20
 
@@ -70,6 +71,7 @@ const createValkeyConnection = async (instance = {}, connectionOptions = {}) =>
70
71
  client.on('error', (err) => {
71
72
  ValkeyStatus[key] = 'error';
72
73
  logger.error('Valkey error', { err: err?.message, instance });
74
+ if (Underpost.env.isInsideContainer()) Underpost.env.set('container-status', 'error');
73
75
  });
74
76
  client.on('reconnecting', () => {
75
77
  ValkeyStatus[key] = 'reconnecting';
package/bin/file.js DELETED
@@ -1,220 +0,0 @@
1
- import fs from 'fs-extra';
2
-
3
- import { loggerFactory } from '../src/server/logger.js';
4
- import {
5
- cap,
6
- getCapVariableName,
7
- getDirname,
8
- newInstance,
9
- uniqueArray,
10
- } from '../src/client/components/core/CommonJs.js';
11
- import { shellCd, shellExec } from '../src/server/process.js';
12
- import walk from 'ignore-walk';
13
- import { validateTemplatePath } from '../src/server/conf.js';
14
- import dotenv from 'dotenv';
15
-
16
- const logger = loggerFactory(import.meta);
17
-
18
- if (fs.existsSync('./engine-private/conf/dd-cron/.env.production'))
19
- dotenv.config({
20
- path:
21
- `./engine-private/conf/dd-cron/.env.production`,
22
- override: true
23
- });
24
- else dotenv.config();
25
-
26
- let [exe, dir, type] = process.argv;
27
- let rawPath = process.argv[3].replaceAll(`'`, '');
28
- let toPath = process.argv[4].replaceAll(`'`, '');
29
- let path = `${rawPath}`.split('/');
30
- path.pop();
31
- path = path.join('/');
32
- const file = `${rawPath}`.split('/').pop();
33
- const ext = file.split('.')[1];
34
- let name = getCapVariableName(file.split('.')[0]);
35
- let content = '';
36
-
37
- logger.info('File metadata', { path, file, ext, name });
38
-
39
- try {
40
- switch (type) {
41
- case 'update-template':
42
- case 'copy-src':
43
- console.log({ rawPath, toPath });
44
-
45
- let result = await new Promise((resolve) =>
46
- walk(
47
- {
48
- path: rawPath, // root dir to start in. defaults to process.cwd()
49
- ignoreFiles: [`.gitignore`], // list of filenames. defaults to ['.ignore']
50
- includeEmpty: false, // true to include empty dirs, default false
51
- follow: false, // true to follow symlink dirs, default false
52
- },
53
- (...args) => resolve(args[1]),
54
- ),
55
- );
56
-
57
- result = result.filter((path) => !path.startsWith('.git'));
58
-
59
- console.log('copy paths', result);
60
-
61
- if (type === 'update-template') {
62
- if (!fs.existsSync(toPath))
63
- shellExec(`cd .. && node engine/bin clone ${process.env.GITHUB_USERNAME}/pwa-microservices-template`);
64
- else {
65
- shellExec(`cd ${toPath} && git reset && git checkout . && git clean -f -d`);
66
- shellExec(`node bin pull ${toPath} ${process.env.GITHUB_USERNAME}/pwa-microservices-template`);
67
- shellExec(`sudo rm -rf ${toPath}/engine-private`);
68
- shellExec(`sudo rm -rf ${toPath}/logs`);
69
- }
70
- } else {
71
- fs.removeSync(toPath);
72
- }
73
-
74
- for (const copyPath of result) {
75
- if (copyPath === 'NaN') continue;
76
- const folder = getDirname(`${toPath}/${copyPath}`);
77
- const absolutePath = `${rawPath}/${copyPath}`;
78
-
79
- if (type === 'update-template' && !validateTemplatePath(absolutePath)) continue;
80
-
81
- if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
82
-
83
- logger.info('build', `${toPath}/${copyPath}`);
84
-
85
- fs.copyFileSync(absolutePath, `${toPath}/${copyPath}`);
86
- }
87
-
88
- if (type === 'update-template') {
89
- fs.copySync(`./.vscode`, `../pwa-microservices-template/.vscode`);
90
- // fs.copySync(`./.github`, `../pwa-microservices-template/.github`);
91
- fs.copySync(`./src/client/public/default`, `../pwa-microservices-template/src/client/public/default`);
92
-
93
- for (const checkoutPath of ['README.md', 'package.json'])
94
- shellExec(`cd ../pwa-microservices-template && git checkout ${checkoutPath}`);
95
-
96
- for (const deletePath of [
97
- './.github',
98
- './manifests/deployment/dd-lampp-development',
99
- './manifests/deployment/dd-cyberia-development',
100
- './manifests/deployment/dd-core-development',
101
- './manifests/deployment/dd-template-development',
102
- './src/server/object-layer.js',
103
- './src/server/atlas-sprite-sheet-generator.js',
104
- './src/server/shape-generator.js',
105
- './src/server/semantic-layer-generator.js',
106
- './src/server/semantic-layer-generator-floor.js',
107
- './src/server/semantic-layer-generator-skin.js',
108
- './src/server/semantic-layer-generator-resource.js',
109
- './src/server/besu-genesis-generator.js',
110
- './src/grpc/cyberia',
111
- './src/runtime/cyberia-server',
112
- './src/runtime/cyberia-client',
113
- './test/shape-generator.test.js',
114
- './src/client/public/cyberia-docs',
115
- 'bin/cyberia.js',
116
- ]) {
117
- if (fs.existsSync(deletePath)) fs.removeSync('../pwa-microservices-template/' + deletePath);
118
- }
119
-
120
- fs.mkdirSync(`../pwa-microservices-template/.github/workflows`, {
121
- recursive: true,
122
- });
123
- for (const _path of [
124
- `./.github/workflows/pwa-microservices-template-page.cd.yml`,
125
- `./.github/workflows/pwa-microservices-template-test.ci.yml`,
126
- `./.github/workflows/npmpkg.ci.yml`,
127
- `./.github/workflows/ghpkg.ci.yml`,
128
- `./.github/workflows/gitlab.ci.yml`,
129
- `./.github/workflows/publish.ci.yml`,
130
- `./.github/workflows/release.cd.yml`,
131
- `./src/client/services/user/guest.service.js`,
132
- './src/api/user/guest.service.js',
133
- './src/ws/IoInterface.js',
134
- './src/ws/IoServer.js',
135
- ])
136
- fs.copyFileSync(_path, `../pwa-microservices-template/${_path}`);
137
-
138
- const originPackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
139
- const templatePackageJson = JSON.parse(fs.readFileSync('../pwa-microservices-template/package.json', 'utf8'));
140
-
141
- const name = templatePackageJson.name;
142
-
143
- templatePackageJson.dependencies = originPackageJson.dependencies;
144
- templatePackageJson.devDependencies = originPackageJson.devDependencies;
145
- templatePackageJson.version = originPackageJson.version;
146
- templatePackageJson.scripts = originPackageJson.scripts;
147
- templatePackageJson.overrides = originPackageJson.overrides;
148
- templatePackageJson.name = name;
149
- templatePackageJson.description =
150
- 'Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orchestration. Extensible via downstream CLIs.';
151
- templatePackageJson.keywords = uniqueArray(
152
- [
153
- 'underpost',
154
- 'underpost-platform',
155
- 'cli',
156
- 'toolchain',
157
- 'ci-cd',
158
- 'devops',
159
- 'kubernetes',
160
- 'k3s',
161
- 'kubeadm',
162
- 'lxd',
163
- 'bare-metal',
164
- 'container-orchestration',
165
- 'image-management',
166
- 'pwa',
167
- 'workbox',
168
- 'microservices',
169
- ].concat(templatePackageJson.keywords || []),
170
- );
171
- delete templatePackageJson.scripts['update:template'];
172
- fs.writeFileSync(
173
- '../pwa-microservices-template/package.json',
174
- JSON.stringify(templatePackageJson, null, 4),
175
- 'utf8',
176
- );
177
- const originPackageLockJson = JSON.parse(fs.readFileSync('./package-lock.json', 'utf8'));
178
-
179
- const templatePackageLockJson = JSON.parse(
180
- fs.readFileSync('../pwa-microservices-template/package-lock.json', 'utf8'),
181
- );
182
-
183
- const originBasePackageLock = newInstance(templatePackageLockJson.packages['']);
184
- templatePackageLockJson.name = name;
185
- templatePackageLockJson.version = originPackageLockJson.version;
186
- templatePackageLockJson.packages = originPackageLockJson.packages;
187
- templatePackageLockJson.packages[''].name = name;
188
- templatePackageLockJson.packages[''].version = originPackageLockJson.version;
189
- templatePackageLockJson.packages[''].hasInstallScript = originBasePackageLock.hasInstallScript;
190
- templatePackageLockJson.packages[''].license = originBasePackageLock.license;
191
- fs.writeFileSync(
192
- '../pwa-microservices-template/package-lock.json',
193
- JSON.stringify(templatePackageLockJson, null, 4),
194
- 'utf8',
195
- );
196
- // Regenerate package-lock.json to match the modified package.json
197
- // shellExec(`cd ../pwa-microservices-template && npm install --package-lock-only --ignore-scripts`);
198
- fs.writeFileSync(
199
- '../pwa-microservices-template/README.md',
200
- fs
201
- .readFileSync('./README.md', 'utf8')
202
- .replace('<!-- template-title -->', '#### Base template for pwa/api-rest projects.'),
203
- 'utf8',
204
- );
205
- }
206
-
207
- break;
208
- case 'create':
209
- const buildPath = `${path}/${name}${ext ? `.${ext}` : ''}`;
210
- logger.info('Build path', buildPath);
211
- fs.mkdirSync(path, { recursive: true });
212
- fs.writeFileSync(buildPath, content, 'utf8');
213
- default:
214
- logger.error('not found operator');
215
- break;
216
- }
217
- } catch (error) {
218
- logger.error(error, error.stack);
219
- process.exit(1);
220
- }
package/bin/vs.js DELETED
@@ -1,74 +0,0 @@
1
- import fs from 'fs-extra';
2
- import { shellExec } from '../src/server/process.js';
3
- import { loggerFactory } from '../src/server/logger.js';
4
-
5
- const logger = loggerFactory(import.meta);
6
-
7
- const vsCodeRootPath = '/root/.vscode-root';
8
- const vsConfigRootPath = '/root/.config/Code';
9
-
10
- const vsProgram = 'code';
11
-
12
- switch (process.argv[2]) {
13
- case 'info': {
14
- logger.info('Formatted', 'Ctrl shift I');
15
- logger.info('Command', 'Ctrl shift P');
16
- logger.info('Search', 'Ctrl shift F');
17
- logger.info('Debug', 'Ctrl shift D');
18
- logger.info('New File', 'Ctrl N');
19
- logger.info('Change tab', 'Ctrl Tab');
20
- logger.info('Fold All', 'Ctrl K + Ctrl 0');
21
- logger.info('Unfold All', 'Ctrl K + Ctrl J');
22
- logger.info('Close All tabs', 'Ctrl K + W');
23
- logger.info('Go to line number', 'Ctrl G');
24
- logger.info('Change current project folder', 'Ctrl K + Ctrl O');
25
- logger.info('Open new vs windows', 'Ctrl Shift N');
26
- logger.info('Close current vs windows', 'Ctrl Shift W');
27
- logger.info('Preview md', 'Ctrl shift V');
28
- logger.info('Open git changes', 'Ctrl G + G');
29
- logger.warn('Terminal shortcut configure with command pallette', 'Ctl shift T');
30
- break;
31
- }
32
- case 'import':
33
- {
34
- const extensions = JSON.parse(fs.readFileSync(`./.vscode/extensions.json`, 'utf8'));
35
- extensions.recommendations.map((extension) => {
36
- if (extension)
37
- shellExec(
38
- `sudo ${vsProgram} --user-data-dir="${vsCodeRootPath}" --no-sandbox --install-extension ${extension}`,
39
- );
40
- });
41
- }
42
- break;
43
- case 'export':
44
- {
45
- shellExec(
46
- `sudo ${vsProgram} --user-data-dir="${vsCodeRootPath}" --no-sandbox --list-extensions > vs-extensions.txt`,
47
- );
48
- fs.writeFileSync(
49
- `./.vscode/extensions.json`,
50
- JSON.stringify(
51
- {
52
- recommendations: fs
53
- .readFileSync(`./vs-extensions.txt`, 'utf8')
54
- .split(`\n`)
55
- .filter((ext) => ext.trim()),
56
- },
57
- null,
58
- 4,
59
- ),
60
- 'utf8',
61
- );
62
- fs.removeSync(`./vs-extensions.txt`);
63
- }
64
- break;
65
-
66
- case 'clean': {
67
- shellExec(`sudo rm -rf ${vsCodeRootPath}/*`);
68
- shellExec(`sudo rm -rf ${vsConfigRootPath}`);
69
- break;
70
- }
71
- default:
72
- shellExec(`sudo ${vsProgram} ${process.argv[2]} --user-data-dir="${vsCodeRootPath}" --no-sandbox`);
73
- break;
74
- }