underpost 2.8.866 → 2.8.871

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 (42) hide show
  1. package/README.md +52 -36
  2. package/bin/build.js +1 -0
  3. package/bin/deploy.js +30 -1
  4. package/bin/file.js +3 -0
  5. package/bin/util.js +1 -56
  6. package/cli.md +88 -86
  7. package/conf.js +1 -1
  8. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  9. package/manifests/deployment/mongo-express/deployment.yaml +12 -12
  10. package/manifests/maas/nvim.sh +91 -0
  11. package/package.json +1 -10
  12. package/src/api/file/file.service.js +28 -8
  13. package/src/api/user/user.router.js +24 -0
  14. package/src/api/user/user.service.js +3 -4
  15. package/src/cli/cluster.js +2 -13
  16. package/src/cli/cron.js +0 -1
  17. package/src/cli/db.js +0 -19
  18. package/src/cli/deploy.js +17 -26
  19. package/src/cli/fs.js +1 -0
  20. package/src/cli/index.js +1 -0
  21. package/src/cli/run.js +9 -2
  22. package/src/client/components/core/CalendarCore.js +1 -1
  23. package/src/client/components/core/CssCore.js +12 -0
  24. package/src/client/components/core/Docs.js +2 -2
  25. package/src/client/components/core/FullScreen.js +19 -28
  26. package/src/client/components/core/Input.js +1 -0
  27. package/src/client/components/core/Modal.js +66 -63
  28. package/src/client/components/core/ObjectLayerEngine.js +229 -4
  29. package/src/client/components/core/ObjectLayerEngineModal.js +441 -0
  30. package/src/client/components/core/Panel.js +4 -1
  31. package/src/client/components/core/PanelForm.js +1 -1
  32. package/src/client/components/core/Router.js +29 -25
  33. package/src/client/components/core/ToggleSwitch.js +15 -1
  34. package/src/client/components/core/VanillaJs.js +12 -13
  35. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  36. package/src/index.js +1 -1
  37. package/src/server/client-build.js +3 -11
  38. package/src/server/client-icons.js +6 -78
  39. package/src/server/conf.js +20 -64
  40. package/src/server/process.js +2 -1
  41. package/test/api.test.js +3 -2
  42. package/bin/cyberia0.js +0 -78
@@ -5,14 +5,18 @@ import crypto from 'crypto';
5
5
  const logger = loggerFactory(import.meta);
6
6
 
7
7
  const FileFactory = {
8
- upload: async function (req, File) {
9
- const results = [];
10
- if (!req.files) throw { message: 'not file found' };
11
- if (Array.isArray(req.files.file)) for (const file of req.files.file) results.push(await new File(file).save());
8
+ filesExtract: (req) => {
9
+ const files = [];
10
+ if (Array.isArray(req.files.file)) for (const file of req.files.file) files.push(file);
12
11
  else if (Object.keys(req.files).length > 0)
13
- for (const keyFile of Object.keys(req.files)) results.push(await new File(req.files[keyFile]).save());
12
+ for (const keyFile of Object.keys(req.files)) files.push(req.files[keyFile]);
13
+ return files;
14
+ },
15
+ upload: async function (req, File) {
16
+ const results = FileFactory.filesExtract(req);
14
17
  let index = -1;
15
- for (const file of results) {
18
+ for (let file of results) {
19
+ file = await new File(file).save();
16
20
  index++;
17
21
  const [result] = await File.find({
18
22
  _id: file._id,
@@ -25,7 +29,23 @@ const FileFactory = {
25
29
  return Buffer.from(raw, 'utf8').toString('hex');
26
30
  // reverse hexValue.toString()
27
31
  },
28
- svg: (data = new Buffer(), name = '') => {
32
+ getMymeTypeFromPath: (path) => {
33
+ switch (path.split('.').pop()) {
34
+ case 'png':
35
+ return 'image/png';
36
+ case 'jpg':
37
+ return 'image/jpeg';
38
+ case 'jpeg':
39
+ return 'image/jpeg';
40
+ case 'gif':
41
+ return 'image/gif';
42
+ case 'svg':
43
+ return 'image/svg+xml';
44
+ default:
45
+ return 'application/octet-stream';
46
+ }
47
+ },
48
+ create: (data = Buffer.from([]), name = '') => {
29
49
  return {
30
50
  name: name,
31
51
  data: data,
@@ -33,7 +53,7 @@ const FileFactory = {
33
53
  encoding: '7bit',
34
54
  tempFilePath: '',
35
55
  truncated: false,
36
- mimetype: 'image/svg+xml',
56
+ mimetype: FileFactory.getMymeTypeFromPath(name),
37
57
  md5: crypto.createHash('md5').update(data).digest('hex'),
38
58
  cid: undefined,
39
59
  };
@@ -4,6 +4,7 @@ import { loggerFactory } from '../../server/logger.js';
4
4
  import { UserController } from './user.controller.js';
5
5
  import express from 'express';
6
6
  import { DataBaseProvider } from '../../db/DataBaseProvider.js';
7
+ import { FileFactory } from '../file/file.service.js';
7
8
 
8
9
  const logger = loggerFactory(import.meta);
9
10
 
@@ -11,6 +12,7 @@ const UserRouter = (options) => {
11
12
  const router = express.Router();
12
13
 
13
14
  (async () => {
15
+ // admin user seed
14
16
  try {
15
17
  const models = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models;
16
18
  if (models.User) {
@@ -35,6 +37,7 @@ const UserRouter = (options) => {
35
37
  console.log(error);
36
38
  }
37
39
 
40
+ // default user avatar seed
38
41
  options.png = {
39
42
  buffer: {
40
43
  'invalid-token': fs.readFileSync(`./src/client/public/default/assets/mailer/api-user-invalid-token.png`),
@@ -45,6 +48,27 @@ const UserRouter = (options) => {
45
48
  res.set('Content-Type', 'image/png');
46
49
  },
47
50
  };
51
+
52
+ try {
53
+ const models = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models;
54
+ const name = 'api-user-default-avatar.png';
55
+ const imageFile = await models.File.findOne({ name });
56
+ let _id;
57
+ if (imageFile) {
58
+ _id = imageFile._id;
59
+ } else {
60
+ const file = await new models.File(
61
+ FileFactory.create(fs.readFileSync(`./src/client/public/default/assets/mailer/${name}`), name),
62
+ ).save();
63
+ _id = file._id;
64
+ }
65
+ options.getDefaultProfileImageId = async () => {
66
+ return _id;
67
+ };
68
+ } catch (error) {
69
+ logger.error('Error checking/creating default profile image');
70
+ console.log(error);
71
+ }
48
72
  })();
49
73
 
50
74
  router.post(`/mailer/:id`, authMiddleware, async (req, res) => {
@@ -9,7 +9,6 @@ import { DataBaseProvider } from '../../db/DataBaseProvider.js';
9
9
  import { FileFactory } from '../file/file.service.js';
10
10
  import { UserDto } from './user.model.js';
11
11
  import { selectDtoFactory, ValkeyAPI } from '../../server/valkey.js';
12
- import { getDefaultProfileImageId } from '../../server/client-icons.js';
13
12
 
14
13
  const logger = loggerFactory(import.meta);
15
14
 
@@ -129,7 +128,7 @@ const UserService = {
129
128
  if (!user.profileImageId)
130
129
  await User.findByIdAndUpdate(
131
130
  user._id,
132
- { profileImageId: await getDefaultProfileImageId(File) },
131
+ { profileImageId: await options.getDefaultProfileImageId(File) },
133
132
  {
134
133
  runValidators: true,
135
134
  },
@@ -212,7 +211,7 @@ const UserService = {
212
211
  if (validatePassword.status === 'error') throw new Error(validatePassword.message);
213
212
  req.body.password = await hashPassword(req.body.password);
214
213
  req.body.role = req.body.role === 'guest' ? 'guest' : 'user';
215
- req.body.profileImageId = await getDefaultProfileImageId(File);
214
+ req.body.profileImageId = await options.getDefaultProfileImageId(File);
216
215
  const { _id } = await new User(req.body).save();
217
216
  if (_id) {
218
217
  const user = await User.findOne({ _id }).select(UserDto.select.get());
@@ -313,7 +312,7 @@ const UserService = {
313
312
  if (!file && !(await ValkeyAPI.getValkeyObject(options, req.auth.user.email))) {
314
313
  await User.findByIdAndUpdate(
315
314
  user._id,
316
- { profileImageId: await getDefaultProfileImageId(File) },
315
+ { profileImageId: await options.getDefaultProfileImageId(File) },
317
316
  {
318
317
  runValidators: true,
319
318
  },
@@ -410,21 +410,10 @@ EOF
410
410
  const successInstance = await UnderpostTest.API.statusMonitor('mongodb-0', 'Running', 'pods', 1000, 60 * 10);
411
411
 
412
412
  if (successInstance) {
413
- if (!options.mongoDbHost) options.mongoDbHost = 'mongodb-service';
413
+ if (!options.mongoDbHost) options.mongoDbHost = 'mongodb-0.mongodb-service';
414
414
  const mongoConfig = {
415
415
  _id: 'rs0',
416
- members: [
417
- {
418
- _id: 0,
419
- host: `${options.mongoDbHost === 'mongodb-service' ? 'mongodb-0.' : ''}${options.mongoDbHost}:27017`,
420
- priority: 1,
421
- },
422
- // {
423
- // _id: 1,
424
- // host: `${options.mongoDbHost === 'mongodb-service' ? 'mongodb-1.' : ''}${options.mongoDbHost}:27017`,
425
- // priority: 1,
426
- // },
427
- ],
416
+ members: options.mongoDbHost.split(',').map((host, index) => ({ _id: index, host: `${host}:27017` })),
428
417
  };
429
418
 
430
419
  shellExec(
package/src/cli/cron.js CHANGED
@@ -64,7 +64,6 @@ class UnderpostCron {
64
64
  shellExec(Cmd.cron(deployId, job, name, confCronConfig.jobs[job].expression, options));
65
65
  }
66
66
  }
67
- if (fs.existsSync(`./tmp/await-deploy`)) fs.remove(`./tmp/await-deploy`);
68
67
  return;
69
68
  }
70
69
  for (const _jobId of jobList.split(',')) {
package/src/cli/db.js CHANGED
@@ -177,25 +177,6 @@ class UnderpostDB {
177
177
  }`,
178
178
  );
179
179
  }
180
- if (false) {
181
- const containerBaseBackupPath = '/backup';
182
- let timeFolder = shellExec(
183
- `sudo kubectl exec -i ${podName} -- sh -c "cd ${containerBaseBackupPath} && ls -a"`,
184
- {
185
- stdout: true,
186
- disableLog: false,
187
- silent: true,
188
- },
189
- ).split(`\n`);
190
- timeFolder = timeFolder[timeFolder.length - 2];
191
- if (timeFolder === '..') {
192
- logger.warn(`Cannot backup available`, { timeFolder });
193
- } else {
194
- shellExec(
195
- `sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
196
- );
197
- }
198
- }
199
180
  }
200
181
  break;
201
182
  }
package/src/cli/deploy.js CHANGED
@@ -247,6 +247,7 @@ spec:
247
247
  restoreHosts: false,
248
248
  disableUpdateDeployment: false,
249
249
  infoTraffic: false,
250
+ etcHosts: false,
250
251
  },
251
252
  ) {
252
253
  if (options.infoUtil === true)
@@ -326,14 +327,10 @@ Password: <Your Key>
326
327
  }
327
328
  UnderpostDeploy.API.configMap(env);
328
329
  let renderHosts = '';
329
- let concatHots = '';
330
- const etcHost = (
331
- concat,
332
- ) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
333
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
330
+ let etcHosts = [];
334
331
  if (options.restoreHosts === true) {
335
- renderHosts = etcHost(concatHots);
336
- fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
332
+ const factoryResult = UnderpostDeploy.API.etcHostFactory(etcHosts);
333
+ renderHosts = factoryResult.renderHosts;
337
334
  logger.info(renderHosts);
338
335
  return;
339
336
  }
@@ -362,7 +359,7 @@ Password: <Your Key>
362
359
  for (const host of Object.keys(confServer)) {
363
360
  shellExec(`sudo kubectl delete HTTPProxy ${host}`);
364
361
  if (env === 'production' && options.cert === true) shellExec(`sudo kubectl delete Certificate ${host}`);
365
- if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
362
+ if (!options.remove === true && env === 'development') etcHosts.push(host);
366
363
  }
367
364
 
368
365
  const manifestsPath =
@@ -377,24 +374,9 @@ Password: <Your Key>
377
374
  shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
378
375
  }
379
376
  }
380
- switch (process.platform) {
381
- case 'linux':
382
- {
383
- switch (env) {
384
- case 'development':
385
- renderHosts = etcHost(concatHots);
386
- fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
387
-
388
- break;
389
-
390
- default:
391
- break;
392
- }
393
- }
394
- break;
395
-
396
- default:
397
- break;
377
+ if (options.etcHosts === true) {
378
+ const factoryResult = UnderpostDeploy.API.etcHostFactory(etcHosts);
379
+ renderHosts = factoryResult.renderHosts;
398
380
  }
399
381
  if (renderHosts)
400
382
  logger.info(
@@ -488,6 +470,15 @@ Password: <Your Key>
488
470
  );
489
471
  shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml`);
490
472
  },
473
+ etcHostFactory(hosts = []) {
474
+ const renderHosts = `127.0.0.1 ${hosts.join(
475
+ ' ',
476
+ )} localhost localhost.localdomain localhost4 localhost4.localdomain4
477
+ ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
478
+
479
+ fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
480
+ return { renderHosts };
481
+ },
491
482
  };
492
483
  }
493
484
 
package/src/cli/fs.js CHANGED
@@ -61,6 +61,7 @@ class UnderpostFileStorage {
61
61
  await UnderpostFileStorage.API.pull(_path, options);
62
62
  } else logger.warn(`Pull path already exists`, _path);
63
63
  }
64
+ shellExec(`cd ${path} && git init && git add . && git commit -m "Base pull state"`);
64
65
  } else {
65
66
  const files =
66
67
  options.git === true
package/src/cli/index.js CHANGED
@@ -169,6 +169,7 @@ program
169
169
  .option('--disable-update-deployment', 'Disables updates to deployments.')
170
170
  .option('--info-traffic', 'Retrieves traffic configuration from current resource deployments.')
171
171
  .option('--kubeadm', 'Enables the kubeadm context for deployment operations.')
172
+ .option('--etc-hosts', 'Enables the etc-hosts context for deployment operations.')
172
173
  .option('--restore-hosts', 'Restores default `/etc/hosts` entries.')
173
174
  .description('Manages application deployments, defaulting to deploying development pods.')
174
175
  .action(Underpost.deploy.callback);
package/src/cli/run.js CHANGED
@@ -72,12 +72,19 @@ class UnderpostRun {
72
72
  const baseCommand = options.dev ? 'node bin' : 'underpost';
73
73
  shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --reset`);
74
74
  shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''}`);
75
+ const mongoHosts = ['mongodb-0.mongodb-service'];
75
76
  shellExec(
76
- `${baseCommand} cluster${options.dev ? ' --dev' : ''} --mongodb --mongo-db-host ${'127.0.0.1'} --pull-image`,
77
+ `${baseCommand} cluster${options.dev ? ' --dev' : ''} --mongodb --mongo-db-host ${mongoHosts.join(
78
+ ',',
79
+ )} --pull-image`,
77
80
  );
78
81
  shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --valkey --pull-image`);
79
82
  shellExec(`${baseCommand} deploy --expose mongo`, { async: true });
80
83
  shellExec(`${baseCommand} deploy --expose valkey`, { async: true });
84
+ {
85
+ const hostListenResult = UnderpostDeploy.API.etcHostFactory(mongoHosts);
86
+ logger.info(hostListenResult.renderHosts);
87
+ }
81
88
  },
82
89
  'ssh-cluster-info': (path, options = UnderpostRun.DEFAULT_OPTION) => {
83
90
  const { underpostRoot } = options;
@@ -306,7 +313,7 @@ class UnderpostRun {
306
313
 
307
314
  UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
308
315
 
309
- shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${currentTraffic}`);
316
+ // shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${currentTraffic}`);
310
317
  },
311
318
  'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
312
319
  const { underpostRoot } = options;
@@ -346,7 +346,7 @@ const CalendarCore = {
346
346
  status,
347
347
  });
348
348
 
349
- setQueryPath({ path: options.route, queryPath: '' });
349
+ setQueryPath({ path: options.route, queryPath: '', replace: true });
350
350
  await CalendarCore.Data[options.idModal].updatePanel();
351
351
 
352
352
  return { status };
@@ -524,6 +524,12 @@ const CssCoreDark = {
524
524
  }
525
525
  .btn-input-extension:hover {
526
526
  }
527
+ .section-mp-border {
528
+ border: 2px solid #313131;
529
+ border-radius: 5px;
530
+ padding: 5px;
531
+ margin: 5px;
532
+ }
527
533
  </style>
528
534
  ${scrollBarDarkRender()} ${borderChar(1, 'black', ['.main-body-btn-container'])}
529
535
  `,
@@ -848,6 +854,12 @@ const CssCoreLight = {
848
854
  }
849
855
  .btn-input-extension:hover {
850
856
  }
857
+ .section-mp-border {
858
+ border: 2px solid #bbb;
859
+ border-radius: 5px;
860
+ padding: 5px;
861
+ margin: 5px;
862
+ }
851
863
  </style>
852
864
  ${scrollBarLightRender()} ${borderChar(1, 'white', ['.main-body-btn-container'])}
853
865
  `,
@@ -4,7 +4,7 @@ import { rgbToHex } from './CommonJs.js';
4
4
  import { Css, darkTheme, dynamicCol, renderCssAttr, simpleIconsRender, ThemeEvents, Themes } from './Css.js';
5
5
  import { DropDown } from './DropDown.js';
6
6
  import { buildBadgeToolTipMenuOption, Modal, renderMenuLabel, renderViewTitle } from './Modal.js';
7
- import { listenQueryPathInstance, setQueryPath } from './Router.js';
7
+ import { listenQueryPathInstance, setQueryPath, closeModalRouteChangeEvent } from './Router.js';
8
8
  import { Translate } from './Translate.js';
9
9
  import { getProxyPath, getQueryParams, htmls, s, sa } from './VanillaJs.js';
10
10
  import Sortable from 'sortablejs';
@@ -51,7 +51,7 @@ const Docs = {
51
51
  };
52
52
  Modal.Data[ModalId].onObserverListener[ModalId]();
53
53
  Modal.Data[ModalId].onCloseListener[ModalId] = () => {
54
- setQueryPath({ path: 'docs', queryPath: '' });
54
+ closeModalRouteChangeEvent({ closedId: ModalId });
55
55
  };
56
56
  },
57
57
  Data: [
@@ -9,35 +9,26 @@ const FullScreen = {
9
9
  Responsive.Event['full-screen-settings'] = () => {
10
10
  let fullScreenMode = checkFullScreen();
11
11
  if ((fullScreenSwitch && !fullScreenMode) || (!fullScreenSwitch && fullScreenMode))
12
- if (s('.fullscreen-toggle')) ToggleSwitch.Tokens[`fullscreen-toggle`].click();
12
+ if (s('.fullscreen')) ToggleSwitch.Tokens[`fullscreen`].click();
13
13
  };
14
- setTimeout(
15
- () => (s(`.toggle-form-container-fullscreen`).onclick = () => ToggleSwitch.Tokens[`fullscreen-toggle`].click()),
16
- );
17
- return html`<div class="in section-mp toggle-form-container toggle-form-container-fullscreen hover">
18
- <div class="fl ">
19
- <div class="in fll" style="width: 70%">
20
- <div class="in"><i class="fa-solid fa-expand"></i> ${Translate.Render('fullscreen')}</div>
21
- </div>
22
- <div class="in fll" style="width: 30%">
23
- ${await ToggleSwitch.Render({
24
- id: 'fullscreen-toggle',
25
- containerClass: 'inl',
26
- disabledOnClick: true,
27
- checked: fullScreenSwitch,
28
- on: {
29
- unchecked: () => {
30
- fullScreenSwitch = false;
31
- if (checkFullScreen()) fullScreenOut();
32
- },
33
- checked: () => {
34
- fullScreenSwitch = true;
35
- if (!checkFullScreen()) fullScreenIn();
36
- },
37
- },
38
- })}
39
- </div>
40
- </div>
14
+ return html`<div class="in section-mp">
15
+ ${await ToggleSwitch.Render({
16
+ wrapper: true,
17
+ wrapperLabel: html`<i class="fa-solid fa-expand"></i> ${Translate.Render('fullscreen')}`,
18
+ id: 'fullscreen',
19
+ disabledOnClick: true,
20
+ checked: fullScreenSwitch,
21
+ on: {
22
+ unchecked: () => {
23
+ fullScreenSwitch = false;
24
+ if (checkFullScreen()) fullScreenOut();
25
+ },
26
+ checked: () => {
27
+ fullScreenSwitch = true;
28
+ if (!checkFullScreen()) fullScreenIn();
29
+ },
30
+ },
31
+ })}
41
32
  </div>`;
42
33
  },
43
34
  };
@@ -65,6 +65,7 @@ const Input = {
65
65
  type="${options?.type ? options.type : 'text'}"
66
66
  class="${options.inputClass ? options.inputClass : 'in wfa'} ${id}"
67
67
  ${options?.min !== undefined ? `min="${options.min}"` : ''}
68
+ ${options?.max !== undefined ? `max="${options.max}"` : ''}
68
69
  placeholder${options?.placeholder ? `="${options.placeholder}"` : ''}
69
70
  ${options?.value !== undefined ? `value="${options.value}"` : ''}
70
71
  ${options?.autocomplete ? `autocomplete="${options.autocomplete}"` : ''}