underpost 2.8.86 → 2.8.88

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 (116) hide show
  1. package/.env.development +39 -2
  2. package/.env.production +42 -2
  3. package/.env.test +39 -2
  4. package/.github/workflows/ghpkg.ci.yml +1 -1
  5. package/.github/workflows/npmpkg.ci.yml +1 -1
  6. package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -5
  7. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  8. package/.github/workflows/release.cd.yml +3 -3
  9. package/README.md +76 -2
  10. package/bin/build.js +5 -0
  11. package/bin/deploy.js +93 -27
  12. package/bin/file.js +8 -4
  13. package/bin/util.js +1 -56
  14. package/cli.md +16 -5
  15. package/conf.js +33 -7
  16. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  17. package/manifests/deployment/dd-test-development/deployment.yaml +174 -0
  18. package/manifests/deployment/dd-test-development/proxy.yaml +51 -0
  19. package/manifests/deployment/mongo-express/deployment.yaml +12 -12
  20. package/manifests/maas/nvim.sh +91 -0
  21. package/package.json +8 -15
  22. package/src/api/core/core.router.js +2 -1
  23. package/src/api/default/default.controller.js +6 -1
  24. package/src/api/default/default.router.js +6 -2
  25. package/src/api/default/default.service.js +10 -1
  26. package/src/api/document/document.controller.js +66 -0
  27. package/src/api/document/document.model.js +51 -0
  28. package/src/api/document/document.router.js +24 -0
  29. package/src/api/document/document.service.js +125 -0
  30. package/src/api/file/file.controller.js +15 -1
  31. package/src/api/file/file.router.js +2 -1
  32. package/src/api/file/file.service.js +28 -8
  33. package/src/api/test/test.router.js +1 -1
  34. package/src/api/user/postman_collection.json +216 -0
  35. package/src/api/user/user.controller.js +25 -60
  36. package/src/api/user/user.model.js +29 -7
  37. package/src/api/user/user.router.js +40 -8
  38. package/src/api/user/user.service.js +86 -35
  39. package/src/cli/baremetal.js +33 -3
  40. package/src/cli/cloud-init.js +11 -0
  41. package/src/cli/cluster.js +4 -23
  42. package/src/cli/cron.js +0 -1
  43. package/src/cli/db.js +0 -19
  44. package/src/cli/deploy.js +67 -52
  45. package/src/cli/fs.js +1 -0
  46. package/src/cli/index.js +9 -1
  47. package/src/cli/lxd.js +7 -0
  48. package/src/cli/repository.js +44 -6
  49. package/src/cli/run.js +56 -9
  50. package/src/cli/ssh.js +20 -6
  51. package/src/client/Default.index.js +42 -1
  52. package/src/client/components/core/Account.js +10 -2
  53. package/src/client/components/core/AgGrid.js +30 -8
  54. package/src/client/components/core/Auth.js +99 -56
  55. package/src/client/components/core/BtnIcon.js +3 -2
  56. package/src/client/components/core/CalendarCore.js +2 -3
  57. package/src/client/components/core/CommonJs.js +1 -2
  58. package/src/client/components/core/Content.js +15 -12
  59. package/src/client/components/core/Css.js +2 -1
  60. package/src/client/components/core/CssCore.js +18 -1
  61. package/src/client/components/core/Docs.js +5 -5
  62. package/src/client/components/core/FileExplorer.js +3 -3
  63. package/src/client/components/core/FullScreen.js +19 -28
  64. package/src/client/components/core/Input.js +22 -16
  65. package/src/client/components/core/JoyStick.js +2 -2
  66. package/src/client/components/core/LoadingAnimation.js +2 -2
  67. package/src/client/components/core/LogIn.js +16 -23
  68. package/src/client/components/core/LogOut.js +5 -1
  69. package/src/client/components/core/Logger.js +4 -1
  70. package/src/client/components/core/Modal.js +102 -87
  71. package/src/client/components/core/ObjectLayerEngine.js +229 -4
  72. package/src/client/components/core/ObjectLayerEngineModal.js +442 -0
  73. package/src/client/components/core/Pagination.js +207 -0
  74. package/src/client/components/core/Panel.js +10 -10
  75. package/src/client/components/core/PanelForm.js +130 -33
  76. package/src/client/components/core/Recover.js +2 -2
  77. package/src/client/components/core/Router.js +210 -34
  78. package/src/client/components/core/SignUp.js +1 -2
  79. package/src/client/components/core/Stream.js +1 -1
  80. package/src/client/components/core/ToggleSwitch.js +15 -1
  81. package/src/client/components/core/VanillaJs.js +3 -84
  82. package/src/client/components/core/Worker.js +2 -2
  83. package/src/client/components/default/LogInDefault.js +0 -6
  84. package/src/client/components/default/LogOutDefault.js +0 -16
  85. package/src/client/components/default/MenuDefault.js +97 -44
  86. package/src/client/components/default/RoutesDefault.js +5 -2
  87. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  88. package/src/client/services/core/core.service.js +8 -20
  89. package/src/client/services/default/default.management.js +115 -18
  90. package/src/client/services/default/default.service.js +13 -4
  91. package/src/client/services/document/document.service.js +97 -0
  92. package/src/client/services/file/file.service.js +2 -0
  93. package/src/client/services/test/test.service.js +3 -0
  94. package/src/client/services/user/user.management.js +6 -0
  95. package/src/client/services/user/user.service.js +15 -4
  96. package/src/client/ssr/Render.js +1 -1
  97. package/src/client/ssr/head/DefaultScripts.js +3 -0
  98. package/src/client/ssr/head/Seo.js +1 -0
  99. package/src/index.js +24 -2
  100. package/src/runtime/lampp/Lampp.js +89 -2
  101. package/src/runtime/xampp/Xampp.js +48 -1
  102. package/src/server/auth.js +519 -155
  103. package/src/server/backup.js +2 -2
  104. package/src/server/client-build-docs.js +1 -1
  105. package/src/server/client-build.js +4 -12
  106. package/src/server/client-icons.js +6 -78
  107. package/src/server/conf.js +144 -141
  108. package/src/server/process.js +2 -1
  109. package/src/server/proxy.js +1 -1
  110. package/src/server/runtime.js +136 -288
  111. package/src/server/ssl.js +1 -2
  112. package/src/server/ssr.js +85 -0
  113. package/src/server/start.js +4 -4
  114. package/src/server/valkey.js +2 -1
  115. package/test/api.test.js +3 -2
  116. package/bin/cyberia0.js +0 -78
@@ -7,6 +7,7 @@ import { loggerFactory } from '../../components/core/Logger.js';
7
7
  import { Modal } from '../../components/core/Modal.js';
8
8
  import { NotificationManager } from '../../components/core/NotificationManager.js';
9
9
  import { Translate } from '../../components/core/Translate.js';
10
+ import { getQueryParams, RouterEvents, setQueryParams } from '../../components/core/Router.js';
10
11
  import { s } from '../../components/core/VanillaJs.js';
11
12
  import { DefaultService } from './default.service.js';
12
13
 
@@ -47,19 +48,48 @@ const columnDefFormatter = (obj, columnDefs, customFormat) => {
47
48
 
48
49
  const DefaultManagement = {
49
50
  Tokens: {},
51
+ loadTable: async function (id, options = { reload: true }) {
52
+ const { serviceId, columnDefs, customFormat } = this.Tokens[id];
53
+ const result = await this.Tokens[id].ServiceProvider.get({
54
+ page: this.Tokens[id].page,
55
+ limit: this.Tokens[id].limit,
56
+ id: this.Tokens[id].serviceOptions?.get?.id ?? undefined,
57
+ });
58
+ if (result.status === 'success') {
59
+ const { data, total, page, totalPages } = result.data;
60
+ this.Tokens[id].total = total;
61
+ this.Tokens[id].page = page;
62
+ this.Tokens[id].totalPages = totalPages;
63
+ const rowDataScope = data.map((row) => columnDefFormatter(row, columnDefs, customFormat));
64
+ if (options.reload) AgGrid.grids[this.Tokens[id].gridId].setGridOption('rowData', rowDataScope);
65
+ const paginationComp = s(`#ag-pagination-${this.Tokens[id].gridId}`);
66
+ paginationComp.setAttribute('current-page', this.Tokens[id].page);
67
+ paginationComp.setAttribute('total-pages', this.Tokens[id].totalPages);
68
+ paginationComp.setAttribute('total-items', this.Tokens[id].total);
69
+ }
70
+ },
50
71
  RenderTable: async function (options = DefaultOptions) {
51
72
  if (!options) options = DefaultOptions;
52
73
  const { serviceId, columnDefs, entity, defaultColKeyFocus, ServiceProvider, permissions } = options;
53
74
  logger.info('DefaultManagement RenderTable', options);
54
75
  const id = options?.idModal ? options.idModal : getId(this.Tokens, `${serviceId}-`);
55
76
  const gridId = `${serviceId}-grid-${id}`;
56
- this.Tokens[id] = { gridId };
77
+ const queryParams = getQueryParams();
78
+ const page = parseInt(queryParams.page) || 1;
79
+ const limit = parseInt(queryParams.limit) || 10;
80
+ this.Tokens[id] = {
81
+ ...options,
82
+ gridId,
83
+ page,
84
+ limit,
85
+ total: 0,
86
+ totalPages: 1,
87
+ };
57
88
 
89
+ setQueryParams({ page, limit });
58
90
  setTimeout(async () => {
59
91
  // https://www.ag-grid.com/javascript-data-grid/data-update-transactions/
60
92
 
61
- let rowDataScope = [];
62
-
63
93
  class RemoveActionGridRenderer {
64
94
  eGui;
65
95
  tokens;
@@ -110,6 +140,16 @@ const DefaultManagement = {
110
140
  });
111
141
  if (result.status === 'success') {
112
142
  AgGrid.grids[gridId].applyTransaction({ remove: [params.data] });
143
+ const token = DefaultManagement.Tokens[id];
144
+ // if we are on the last page and we delete the last item, go to the previous page
145
+ const newTotal = token.total - 1;
146
+ const newTotalPages = Math.ceil(newTotal / token.limit);
147
+ if (token.page > newTotalPages && newTotalPages > 0) {
148
+ token.page = newTotalPages;
149
+ }
150
+
151
+ // reload the current page
152
+ await DefaultManagement.loadTable(id, { reload: false });
113
153
  }
114
154
  },
115
155
  { context: 'modal' },
@@ -142,13 +182,14 @@ const DefaultManagement = {
142
182
  : [],
143
183
  ),
144
184
  );
145
- {
146
- const result = await ServiceProvider.get();
147
- if (result.status === 'success') {
148
- rowDataScope = result.data.map((row) => columnDefFormatter(row, columnDefs, options.customFormat));
149
- AgGrid.grids[gridId].setGridOption('rowData', rowDataScope);
150
- }
151
- }
185
+ DefaultManagement.loadTable(id);
186
+ // {
187
+ // const result = await ServiceProvider.get();
188
+ // if (result.status === 'success') {
189
+ // rowDataScope = result.data.map((row) => columnDefFormatter(row, columnDefs, options.customFormat));
190
+ // AgGrid.grids[gridId].setGridOption('rowData', rowDataScope);
191
+ // }
192
+ // }
152
193
  s(`.management-table-btn-save-${id}`).onclick = () => {
153
194
  AgGrid.grids[gridId].stopEditing();
154
195
  };
@@ -168,9 +209,13 @@ const DefaultManagement = {
168
209
  // });
169
210
  if (result.status === 'success') {
170
211
  AgGrid.grids[gridId].applyTransaction({
171
- add: [columnDefFormatter(result.data, columnDefs, options.customFormat)],
212
+ add: [columnDefFormatter(rowObj, columnDefs, options.customFormat)],
172
213
  addIndex: 0,
173
214
  });
215
+ // AgGrid.grids[gridId].applyTransaction({
216
+ // add: [columnDefFormatter(result.data, columnDefs, options.customFormat)],
217
+ // addIndex: 0,
218
+ // });
174
219
  // AgGrid.grids[gridId].applyColumnState({
175
220
  // state: [
176
221
  // // { colId: 'country', sort: 'asc', sortIndex: 1 },
@@ -244,9 +289,34 @@ const DefaultManagement = {
244
289
  status: result.status,
245
290
  });
246
291
  if (result.status === 'success') {
247
- AgGrid.grids[gridId].setGridOption('rowData', []);
292
+ DefaultManagement.loadTable(id);
248
293
  }
249
294
  });
295
+ s(`#ag-pagination-${gridId}`).addEventListener('page-change', async (event) => {
296
+ const token = DefaultManagement.Tokens[id];
297
+ token.page = event.detail.page;
298
+ await DefaultManagement.loadTable(id);
299
+ });
300
+ s(`#ag-pagination-${gridId}`).addEventListener('limit-change', async (event) => {
301
+ const token = DefaultManagement.Tokens[id];
302
+ token.limit = event.detail.limit;
303
+ token.page = 1; // Reset to first page
304
+ await DefaultManagement.loadTable(id);
305
+ });
306
+ RouterEvents[id] = async (...args) => {
307
+ const queryParams = getQueryParams();
308
+ const page = parseInt(queryParams.page) || 1;
309
+ const limit = parseInt(queryParams.limit) || 10;
310
+ const token = DefaultManagement.Tokens[id];
311
+
312
+ // Check if the pagination state in the URL is different from the current state
313
+ if (token.page !== page || token.limit !== limit) {
314
+ token.page = page;
315
+ token.limit = limit;
316
+ // Reload the table with the new pagination state from the URL
317
+ await DefaultManagement.loadTable(id);
318
+ }
319
+ };
250
320
  }, 1);
251
321
  return html`<div class="fl">
252
322
  ${await BtnIcon.Render({
@@ -274,6 +344,7 @@ const DefaultManagement = {
274
344
  <div class="in section-mp">
275
345
  ${await AgGrid.Render({
276
346
  id: gridId,
347
+ usePagination: true,
277
348
  darkTheme,
278
349
  gridOptions: {
279
350
  defaultColDef: {
@@ -327,7 +398,32 @@ const DefaultManagement = {
327
398
  status: result.status,
328
399
  });
329
400
  if (result.status === 'success') {
330
- event.data._id = result.data[entity] ? result.data[entity]._id : result.data._id;
401
+ this.Tokens[id].page = 1;
402
+ await DefaultManagement.loadTable(id);
403
+ // const newItemId = result.data?.[entity]?._id || result.data?._id;
404
+ // The `event.node.id` is the temporary ID assigned by AG Grid.
405
+ // const rowNode = AgGrid.grids[gridId].getRowNode(event.node.id);
406
+ setQueryParams({ page: 1, limit: this.Tokens[id].limit });
407
+
408
+ let rowNode;
409
+ AgGrid.grids[gridId].forEachLeafNode((_rowNode) => {
410
+ if (_rowNode.data._id === result.data._id) {
411
+ rowNode = _rowNode;
412
+ }
413
+ });
414
+ if (rowNode) {
415
+ const newRow = columnDefFormatter(result.data, columnDefs, options.customFormat);
416
+ // Add a temporary flag to the new row data.
417
+ newRow._new = true;
418
+ // Update the row data with the data from the server, which includes the new permanent `_id`.
419
+ rowNode.setData(newRow);
420
+ // The `rowClassRules` will automatically apply the 'row-new-highlight' class.
421
+ // Now, remove the flag after a delay to remove the highlight.
422
+ // setTimeout(() => {
423
+ // delete newRow._new;
424
+ // rowNode.setData(newRow);
425
+ // }, 2000);
426
+ }
331
427
  }
332
428
  } else {
333
429
  const body = event.data ? event.data : {};
@@ -336,11 +432,12 @@ const DefaultManagement = {
336
432
  html: result.status === 'error' ? result.message : `${Translate.Render('success-update-item')}`,
337
433
  status: result.status,
338
434
  });
339
- }
340
- if (result.status === 'success') {
341
- AgGrid.grids[gridId].applyTransaction({
342
- update: [event.data],
343
- });
435
+ if (result.status === 'success') {
436
+ AgGrid.grids[gridId].applyTransaction({
437
+ update: [event.data],
438
+ });
439
+ DefaultManagement.loadTable(id, { reload: false });
440
+ }
344
441
  }
345
442
  },
346
443
  },
@@ -14,6 +14,7 @@ const DefaultService = {
14
14
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
15
15
  method: 'POST',
16
16
  headers: headersFactory(),
17
+ credentials: 'include',
17
18
  body: payloadFactory(options.body),
18
19
  })
19
20
  .then(async (res) => {
@@ -33,6 +34,7 @@ const DefaultService = {
33
34
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
34
35
  method: 'PUT',
35
36
  headers: headersFactory(),
37
+ credentials: 'include',
36
38
  body: payloadFactory(options.body),
37
39
  })
38
40
  .then(async (res) => {
@@ -47,11 +49,16 @@ const DefaultService = {
47
49
  return reject(error);
48
50
  }),
49
51
  ),
50
- get: (options = { id: '', body: {} }) =>
51
- new Promise((resolve, reject) =>
52
- fetch(getApiBaseUrl({ id: options.id, endpoint }), {
52
+ get: (options = { id: '', body: {}, page: 1, limit: 10 }) => {
53
+ const { id, page, limit } = options;
54
+ const url = new URL(getApiBaseUrl({ id, endpoint }));
55
+ url.searchParams.append('page', page);
56
+ url.searchParams.append('limit', limit);
57
+ return new Promise((resolve, reject) =>
58
+ fetch(url.toString(), {
53
59
  method: 'GET',
54
60
  headers: headersFactory(),
61
+ credentials: 'include',
55
62
  })
56
63
  .then(async (res) => {
57
64
  return await res.json();
@@ -64,12 +71,14 @@ const DefaultService = {
64
71
  logger.error(error);
65
72
  return reject(error);
66
73
  }),
67
- ),
74
+ );
75
+ },
68
76
  delete: (options = { id: '', body: {} }) =>
69
77
  new Promise((resolve, reject) =>
70
78
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
71
79
  method: 'DELETE',
72
80
  headers: headersFactory(),
81
+ credentials: 'include',
73
82
  body: payloadFactory(options.body),
74
83
  })
75
84
  .then(async (res) => {
@@ -0,0 +1,97 @@
1
+ import { Auth } from '../../components/core/Auth.js';
2
+ import { loggerFactory } from '../../components/core/Logger.js';
3
+ import { getApiBaseUrl, headersFactory, payloadFactory } from '../core/core.service.js';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ logger.info('Load service');
8
+
9
+ const endpoint = 'document';
10
+
11
+ const DocumentService = {
12
+ post: (options = { id: '', body: {} }) =>
13
+ new Promise((resolve, reject) =>
14
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
15
+ method: 'POST',
16
+ headers: headersFactory(),
17
+ credentials: 'include',
18
+ body: payloadFactory(options.body),
19
+ })
20
+ .then(async (res) => {
21
+ return await res.json();
22
+ })
23
+ .then((res) => {
24
+ logger.info(res);
25
+ return resolve(res);
26
+ })
27
+ .catch((error) => {
28
+ logger.error(error);
29
+ return reject(error);
30
+ }),
31
+ ),
32
+ get: (options = { id: '' }) =>
33
+ new Promise((resolve, reject) => {
34
+ const url = new URL(getApiBaseUrl({ id: options.id, endpoint }));
35
+ if (options.params) {
36
+ Object.keys(options.params).forEach((key) => url.searchParams.append(key, options.params[key]));
37
+ }
38
+ fetch(url, {
39
+ method: 'GET',
40
+ headers: headersFactory(),
41
+ credentials: 'include',
42
+ })
43
+ .then(async (res) => {
44
+ return await res.json();
45
+ })
46
+ .then((res) => {
47
+ logger.info(res);
48
+ return resolve(res);
49
+ })
50
+ .catch((error) => {
51
+ logger.error(error);
52
+ return reject(error);
53
+ });
54
+ }),
55
+ delete: (options = { id: '', body: {} }) =>
56
+ new Promise((resolve, reject) =>
57
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
58
+ method: 'DELETE',
59
+ headers: headersFactory(),
60
+ credentials: 'include',
61
+ body: payloadFactory(options.body),
62
+ })
63
+ .then(async (res) => {
64
+ return await res.json();
65
+ })
66
+ .then((res) => {
67
+ logger.info(res);
68
+ return resolve(res);
69
+ })
70
+ .catch((error) => {
71
+ logger.error(error);
72
+ return reject(error);
73
+ }),
74
+ ),
75
+ put: (options = { id: '', body: {} }) =>
76
+ new Promise((resolve, reject) =>
77
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
78
+ method: 'PUT',
79
+ headers: headersFactory(),
80
+ credentials: 'include',
81
+ body: payloadFactory(options.body),
82
+ })
83
+ .then(async (res) => {
84
+ return await res.json();
85
+ })
86
+ .then((res) => {
87
+ logger.info(res);
88
+ return resolve(res);
89
+ })
90
+ .catch((error) => {
91
+ logger.error(error);
92
+ return reject(error);
93
+ }),
94
+ ),
95
+ };
96
+
97
+ export { DocumentService };
@@ -33,6 +33,7 @@ const FileService = {
33
33
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
34
34
  method: 'GET',
35
35
  headers: headersFactory(),
36
+ credentials: 'include',
36
37
  })
37
38
  .then(async (res) => {
38
39
  return await res.json();
@@ -51,6 +52,7 @@ const FileService = {
51
52
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
52
53
  method: 'DELETE',
53
54
  headers: headersFactory(),
55
+ credentials: 'include',
54
56
  body: payloadFactory(options.body),
55
57
  })
56
58
  .then(async (res) => {
@@ -14,6 +14,7 @@ const TestService = {
14
14
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
15
15
  method: 'POST',
16
16
  headers: headersFactory(),
17
+ credentials: 'include',
17
18
  body: payloadFactory(options.body),
18
19
  })
19
20
  .then(async (res) => {
@@ -33,6 +34,7 @@ const TestService = {
33
34
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
34
35
  method: 'GET',
35
36
  headers: headersFactory(),
37
+ credentials: 'include',
36
38
  })
37
39
  .then(async (res) => {
38
40
  return await res.json();
@@ -51,6 +53,7 @@ const TestService = {
51
53
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
52
54
  method: 'DELETE',
53
55
  headers: headersFactory(),
56
+ credentials: 'include',
54
57
  body: payloadFactory(options.body),
55
58
  })
56
59
  .then(async (res) => {
@@ -13,6 +13,7 @@ const UserManagement = {
13
13
  add: role === 'admin',
14
14
  remove: role === 'admin',
15
15
  },
16
+ usePagination: true,
16
17
  columnDefs: [
17
18
  { field: 'username', headerName: 'username', editable: role === 'admin' },
18
19
  { field: 'email', headerName: 'email', editable: role === 'admin' },
@@ -44,6 +45,11 @@ const UserManagement = {
44
45
  ],
45
46
  defaultColKeyFocus: 'username',
46
47
  ServiceProvider: UserService,
48
+ serviceOptions: {
49
+ get: {
50
+ id: 'all',
51
+ },
52
+ },
47
53
  });
48
54
  },
49
55
  };
@@ -22,6 +22,7 @@ const UserService = {
22
22
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
23
23
  method: 'POST',
24
24
  headers: headersFactory(),
25
+ credentials: 'include',
25
26
  body: payloadFactory(options.body),
26
27
  })
27
28
  .then(async (res) => {
@@ -36,11 +37,18 @@ const UserService = {
36
37
  return reject(error);
37
38
  }),
38
39
  ),
39
- get: (options = { id: '' }) =>
40
- new Promise((resolve, reject) =>
41
- fetch(getApiBaseUrl({ id: options.id, endpoint }), {
40
+ get: (options = { id: '', page: 1, limit: 10 }) => {
41
+ const { id = '', page, limit } = options;
42
+ const query = new URLSearchParams();
43
+ if (page) query.set('page', page);
44
+ if (limit) query.set('limit', limit);
45
+ const queryString = query.toString();
46
+ const url = `${getApiBaseUrl({ id, endpoint })}${queryString ? (id.includes('?') ? '&' : '?') + queryString : ''}`;
47
+ return new Promise((resolve, reject) =>
48
+ fetch(url, {
42
49
  method: 'GET',
43
50
  headers: headersFactory(),
51
+ credentials: 'include',
44
52
  })
45
53
  .then(async (res) => {
46
54
  return await res.json();
@@ -53,12 +61,14 @@ const UserService = {
53
61
  logger.error(error);
54
62
  return reject(error);
55
63
  }),
56
- ),
64
+ );
65
+ },
57
66
  delete: (options = { id: '', body: {} }) =>
58
67
  new Promise((resolve, reject) =>
59
68
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
60
69
  method: 'DELETE',
61
70
  headers: headersFactory(),
71
+ credentials: 'include',
62
72
  body: payloadFactory(options.body),
63
73
  })
64
74
  .then(async (res) => {
@@ -78,6 +88,7 @@ const UserService = {
78
88
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
79
89
  method: 'PUT',
80
90
  headers: headersFactory(options.headerId),
91
+ credentials: 'include',
81
92
  body: payloadFactory(options.body),
82
93
  })
83
94
  .then(async (res) => {
@@ -5,7 +5,7 @@ SrrComponent = ({ title, ssrPath, buildId, ssrHeadComponents, ssrBodyComponents,
5
5
  <title>${title}</title>
6
6
  <link rel="icon" type="image/x-icon" href="${ssrPath}favicon.ico" />
7
7
  <meta charset="UTF-8" />
8
- <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
9
  <script>
10
10
  window.renderPayload = ${renderApi.JSONweb(renderPayload)};
11
11
  </script>
@@ -1,3 +1,6 @@
1
1
  SrrComponent = ({ ssrPath }) => html`
2
2
  <script type="text/javascript" src="${ssrPath}dist/validator/validator.min.js"></script>
3
+ <script type="text/javascript" src="${ssrPath}dist/ag-grid-community/ag-grid-community.min.js"></script>
4
+ <script type="text/javascript" src="${ssrPath}dist/easymde/easymde.min.js"></script>
5
+ <link rel="stylesheet" href="${ssrPath}dist/easymde/easymde.min.css" />
3
6
  `;
@@ -7,6 +7,7 @@ SrrComponent = ({ title, author, keywords, description, themeColor, ssrPath, can
7
7
  <meta name="theme-color" content="${themeColor}" />
8
8
 
9
9
  <meta property="og:title" content="${title}" />
10
+ <meta property="og:type" content="website" />
10
11
  <meta property="og:description" content="${description}" />
11
12
  <meta property="og:image" content="${thumbnail}" />
12
13
  <meta property="og:url" content="${canonicalURL}" />
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ class Underpost {
35
35
  * @type {String}
36
36
  * @memberof Underpost
37
37
  */
38
- static version = 'v2.8.86';
38
+ static version = 'v2.8.88';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static
@@ -171,6 +171,28 @@ const up = Underpost;
171
171
 
172
172
  const underpost = Underpost;
173
173
 
174
- export { underpost, up, Underpost };
174
+ export {
175
+ underpost,
176
+ up,
177
+ Underpost,
178
+ UnderpostBaremetal,
179
+ UnderpostCloudInit,
180
+ UnderpostCluster,
181
+ UnderpostCron,
182
+ UnderpostDB,
183
+ UnderpostDeploy,
184
+ UnderpostRootEnv,
185
+ UnderpostFileStorage,
186
+ UnderpostImage,
187
+ UnderpostLxd,
188
+ UnderpostMonitor,
189
+ UnderpostRepository,
190
+ UnderpostRun,
191
+ UnderpostScript,
192
+ UnderpostSecret,
193
+ UnderpostSSH,
194
+ UnderpostTest,
195
+ UnderpostStartUp,
196
+ };
175
197
 
176
198
  export default Underpost;
@@ -1,6 +1,5 @@
1
1
  import fs from 'fs-extra';
2
- import { shellCd, shellExec } from '../../server/process.js';
3
- import { timer } from '../../client/components/core/CommonJs.js';
2
+ import { getRootDirectory, shellCd, shellExec } from '../../server/process.js';
4
3
  import { loggerFactory } from '../../server/logger.js';
5
4
 
6
5
  const logger = loggerFactory(import.meta);
@@ -107,6 +106,94 @@ const Lampp = {
107
106
  break;
108
107
  }
109
108
  },
109
+ createApp: async ({ port, host, path, directory, rootHostPath, redirect, redirectTarget, resetRouter }) => {
110
+ if (!Lampp.enabled()) return { disabled: true };
111
+ if (!Lampp.ports.includes(port)) Lampp.ports.push(port);
112
+ if (resetRouter) Lampp.removeRouter();
113
+ Lampp.appendRouter(`
114
+ Listen ${port}
115
+
116
+ <VirtualHost *:${port}>
117
+ DocumentRoot "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}"
118
+ ServerName ${host}:${port}
119
+
120
+ <Directory "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}">
121
+ Options Indexes FollowSymLinks MultiViews
122
+ AllowOverride All
123
+ Require all granted
124
+ </Directory>
125
+
126
+ ${
127
+ redirect
128
+ ? `
129
+ RewriteEngine on
130
+
131
+ RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge
132
+ RewriteRule ^(.*)$ ${redirectTarget}%{REQUEST_URI} [R=302,L]
133
+ `
134
+ : ''
135
+ }
136
+
137
+ ErrorDocument 400 ${path === '/' ? '' : path}/400.html
138
+ ErrorDocument 404 ${path === '/' ? '' : path}/400.html
139
+ ErrorDocument 500 ${path === '/' ? '' : path}/500.html
140
+ ErrorDocument 502 ${path === '/' ? '' : path}/500.html
141
+ ErrorDocument 503 ${path === '/' ? '' : path}/500.html
142
+ ErrorDocument 504 ${path === '/' ? '' : path}/500.html
143
+
144
+ </VirtualHost>
145
+
146
+ `);
147
+ // ERR too many redirects:
148
+ // Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
149
+ // Check: wp-config.php
150
+ // if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
151
+ // $_SERVER['HTTPS'] = 'on';
152
+ // }
153
+ // For plugins:
154
+ // define( 'FS_METHOD', 'direct' );
155
+
156
+ // ErrorDocument 404 /custom_404.html
157
+ // ErrorDocument 500 /custom_50x.html
158
+ // ErrorDocument 502 /custom_50x.html
159
+ // ErrorDocument 503 /custom_50x.html
160
+ // ErrorDocument 504 /custom_50x.html
161
+
162
+ // Respond When Error Pages are Directly Requested
163
+
164
+ // <Files "custom_404.html">
165
+ // <If "-z %{ENV:REDIRECT_STATUS}">
166
+ // RedirectMatch 404 ^/custom_404.html$
167
+ // </If>
168
+ // </Files>
169
+
170
+ // <Files "custom_50x.html">
171
+ // <If "-z %{ENV:REDIRECT_STATUS}">
172
+ // RedirectMatch 404 ^/custom_50x.html$
173
+ // </If>
174
+ // </Files>
175
+
176
+ // Add www or https with htaccess rewrite
177
+
178
+ // Options +FollowSymLinks
179
+ // RewriteEngine On
180
+ // RewriteCond %{HTTP_HOST} ^ejemplo.com [NC]
181
+ // RewriteRule ^(.*)$ http://ejemplo.com/$1 [R=301,L]
182
+
183
+ // Redirect http to https with htaccess rewrite
184
+
185
+ // RewriteEngine On
186
+ // RewriteCond %{SERVER_PORT} 80
187
+ // RewriteRule ^(.*)$ https://www.ejemplo.com/$1 [R,L]
188
+
189
+ // Redirect to HTTPS with www subdomain
190
+
191
+ // RewriteEngine On
192
+ // RewriteCond %{HTTPS} off [OR]
193
+ // RewriteCond %{HTTP_HOST} ^www\. [NC]
194
+ // RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
195
+ // RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
196
+ },
110
197
  };
111
198
 
112
199
  export { Lampp };