underpost 3.2.70 → 3.2.90

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 (60) hide show
  1. package/.github/workflows/publish.ci.yml +3 -3
  2. package/.github/workflows/release.cd.yml +1 -1
  3. package/CHANGELOG.md +1358 -1038
  4. package/CLI-HELP.md +39 -16
  5. package/README.md +3 -3
  6. package/bin/build.js +10 -4
  7. package/bin/deploy.js +18 -16
  8. package/docker-compose.yml +1 -1
  9. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  10. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  11. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  12. package/manifests/deployment/playwright/deployment.yaml +1 -1
  13. package/manifests/mongodb/kustomization.yaml +4 -1
  14. package/manifests/mongodb/statefulset.yaml +4 -0
  15. package/manifests/mongodb/storage-class.yaml +9 -2
  16. package/package.json +20 -20
  17. package/scripts/nat-iptables.sh +10 -4
  18. package/scripts/test-monitor.sh +4 -3
  19. package/src/api/core/core.controller.js +4 -65
  20. package/src/api/core/core.router.js +8 -14
  21. package/src/api/default/default.controller.js +2 -70
  22. package/src/api/default/default.router.js +7 -17
  23. package/src/api/document/document.controller.js +5 -77
  24. package/src/api/document/document.router.js +9 -13
  25. package/src/api/file/file.controller.js +9 -53
  26. package/src/api/file/file.router.js +14 -6
  27. package/src/api/test/test.controller.js +8 -53
  28. package/src/api/test/test.router.js +1 -4
  29. package/src/cli/cluster.js +771 -66
  30. package/src/cli/db.js +6 -4
  31. package/src/cli/deploy.js +1715 -168
  32. package/src/cli/docker-compose.js +19 -24
  33. package/src/cli/fs.js +0 -1
  34. package/src/cli/image.js +40 -13
  35. package/src/cli/index.js +129 -35
  36. package/src/cli/ipfs.js +82 -11
  37. package/src/cli/monitor.js +1 -1
  38. package/src/cli/release.js +4 -0
  39. package/src/cli/repository.js +14 -3
  40. package/src/cli/run.js +2253 -439
  41. package/src/cli/secrets.js +969 -0
  42. package/src/cli/ssh.js +38 -39
  43. package/src/client/components/core/Modal.js +38 -4
  44. package/src/client-builder/client-build.js +94 -11
  45. package/src/client-builder/ssr.js +27 -73
  46. package/src/db/mongo/MongoBootstrap.js +295 -54
  47. package/src/db/mongo/MongooseDB.js +47 -32
  48. package/src/index.js +1 -1
  49. package/src/server/conf.js +1307 -6
  50. package/src/server/cri.js +70 -0
  51. package/src/server/downloader.js +3 -3
  52. package/src/server/middlewares.js +152 -0
  53. package/src/server/underpost-gateway.js +1073 -0
  54. package/src/server/underpost-ingress.js +364 -0
  55. package/test/cluster-instances.test.js +435 -0
  56. package/test/deploy-node-placement.test.js +45 -0
  57. package/test/instance-traffic-plan.test.js +710 -0
  58. package/test/sops-secret-store.test.js +612 -0
  59. package/test/underpost-gateway.test.js +469 -0
  60. package/test/underpost-ingress.test.js +253 -0
@@ -1,9 +1,7 @@
1
+ import express from 'express';
2
+ import { registerCrudRoutes } from '../../server/middlewares.js';
1
3
  import { adminGuard } from '../../server/auth.js';
2
- import { loggerFactory } from '../../server/logger.js';
3
4
  import { CoreController } from './core.controller.js';
4
- import express from 'express';
5
-
6
- const logger = loggerFactory(import.meta);
7
5
 
8
6
  class CoreRouter {
9
7
  /**
@@ -11,16 +9,12 @@ class CoreRouter {
11
9
  * @returns {import('express').Router}
12
10
  */
13
11
  static router(options) {
14
- const router = express.Router();
15
- router.post(`/:id`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.post(req, res, options));
16
- router.post(`/`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.post(req, res, options));
17
- router.get(`/:id`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.get(req, res, options));
18
- router.get(`/`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.get(req, res, options));
19
- router.put(`/:id`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.put(req, res, options));
20
- router.put(`/`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.put(req, res, options));
21
- router.delete(`/:id`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.delete(req, res, options));
22
- router.delete(`/`, options.authMiddleware, adminGuard, async (req, res) => await CoreController.delete(req, res, options));
23
- return router;
12
+ const adminOnly = [options.authMiddleware, adminGuard];
13
+ return registerCrudRoutes(express.Router(), CoreController, options, {
14
+ readGuards: adminOnly,
15
+ writeGuards: adminOnly,
16
+ deleteAllGuards: adminOnly,
17
+ });
24
18
  }
25
19
  }
26
20
 
@@ -1,74 +1,6 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { buildCrudController } from '../../server/middlewares.js';
2
2
  import { DefaultService } from './default.service.js';
3
3
 
4
- const logger = loggerFactory(import.meta);
5
-
6
- class DefaultController {
7
- static post = async (req, res, options) => {
8
- try {
9
- const result = await DefaultService.post(req, res, options);
10
- return res.status(200).json({
11
- status: 'success',
12
- data: result,
13
- });
14
- } catch (error) {
15
- logger.error(error, error.stack);
16
- return res.status(400).json({
17
- status: 'error',
18
- message: error.message,
19
- });
20
- }
21
- };
22
- static get = async (req, res, options) => {
23
- try {
24
- const { page, limit } = req.query;
25
- const result = await DefaultService.get(
26
- { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
27
- res,
28
- options,
29
- );
30
- return res.status(200).json({
31
- status: 'success',
32
- data: result,
33
- });
34
- } catch (error) {
35
- logger.error(error, error.stack);
36
- return res.status(400).json({
37
- status: 'error',
38
- message: error.message,
39
- });
40
- }
41
- };
42
- static put = async (req, res, options) => {
43
- try {
44
- const result = await DefaultService.put(req, res, options);
45
- return res.status(200).json({
46
- status: 'success',
47
- data: result,
48
- });
49
- } catch (error) {
50
- logger.error(error, error.stack);
51
- return res.status(400).json({
52
- status: 'error',
53
- message: error.message,
54
- });
55
- }
56
- };
57
- static delete = async (req, res, options) => {
58
- try {
59
- const result = await DefaultService.delete(req, res, options);
60
- return res.status(200).json({
61
- status: 'success',
62
- data: result,
63
- });
64
- } catch (error) {
65
- logger.error(error, error.stack);
66
- return res.status(400).json({
67
- status: 'error',
68
- message: error.message,
69
- });
70
- }
71
- };
72
- }
4
+ const DefaultController = buildCrudController(DefaultService);
73
5
 
74
6
  export { DefaultController };
@@ -1,8 +1,6 @@
1
- import { loggerFactory } from '../../server/logger.js';
2
- import { DefaultController } from './default.controller.js';
3
1
  import express from 'express';
4
-
5
- const logger = loggerFactory(import.meta);
2
+ import { registerCrudRoutes } from '../../server/middlewares.js';
3
+ import { DefaultController } from './default.controller.js';
6
4
 
7
5
  class DefaultRouter {
8
6
  /**
@@ -10,19 +8,11 @@ class DefaultRouter {
10
8
  * @returns {import('express').Router}
11
9
  */
12
10
  static router(options) {
13
- const router = express.Router();
14
- router.post(`/:id`, async (req, res) => await DefaultController.post(req, res, options));
15
- router.post(`/`, async (req, res) => await DefaultController.post(req, res, options));
16
- router.get(`/:id`,
17
- // options.authMiddleware,
18
- async (req, res) => await DefaultController.get(req, res, options),
19
- );
20
- router.get(`/`, async (req, res) => await DefaultController.get(req, res, options));
21
- router.put(`/:id`, async (req, res) => await DefaultController.put(req, res, options));
22
- router.put(`/`, async (req, res) => await DefaultController.put(req, res, options));
23
- router.delete(`/:id`, async (req, res) => await DefaultController.delete(req, res, options));
24
- router.delete(`/`, async (req, res) => await DefaultController.delete(req, res, options));
25
- return router;
11
+ // Fully unguarded (matches prior behavior).
12
+ return registerCrudRoutes(express.Router(), DefaultController, options, {
13
+ writeGuards: [],
14
+ deleteAllGuards: [],
15
+ });
26
16
  }
27
17
  }
28
18
 
@@ -1,81 +1,9 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { buildCrudController, serviceHandler } from '../../server/middlewares.js';
2
2
  import { DocumentService } from './document.service.js';
3
- const logger = loggerFactory(import.meta);
4
3
 
5
- class DocumentController {
6
- static post = async (req, res, options) => {
7
- try {
8
- return res.status(200).json({
9
- status: 'success',
10
- data: await DocumentService.post(req, res, options),
11
- });
12
- } catch (error) {
13
- logger.error(error, error.stack);
14
- return res.status(400).json({
15
- status: 'error',
16
- message: error.message,
17
- });
18
- }
19
- };
20
- static get = async (req, res, options) => {
21
- try {
22
- return res.status(200).json({
23
- status: 'success',
24
- data: await DocumentService.get(req, res, options),
25
- });
26
- } catch (error) {
27
- logger.error(error, error.stack);
28
- return res.status(400).json({
29
- status: 'error',
30
- message: error.message,
31
- });
32
- }
33
- };
34
- static delete = async (req, res, options) => {
35
- try {
36
- const result = await DocumentService.delete(req, res, options);
37
- return res.status(200).json({
38
- status: 'success',
39
- data: result,
40
- });
41
- } catch (error) {
42
- logger.error(error, error.stack);
43
- return res.status(400).json({
44
- status: 'error',
45
- message: error.message,
46
- });
47
- }
48
- };
49
- static put = async (req, res, options) => {
50
- try {
51
- const result = await DocumentService.put(req, res, options);
52
- return res.status(200).json({
53
- status: 'success',
54
- data: result,
55
- });
56
- } catch (error) {
57
- logger.error(error, error.stack);
58
- return res.status(400).json({
59
- status: 'error',
60
- message: error.message,
61
- });
62
- }
63
- };
64
- static patch = async (req, res, options) => {
65
- try {
66
- const result = await DocumentService.patch(req, res, options);
67
- return res.status(200).json({
68
- status: 'success',
69
- data: result,
70
- });
71
- } catch (error) {
72
- logger.error(error, error.stack);
73
- return res.status(400).json({
74
- status: 'error',
75
- message: error.message,
76
- });
77
- }
78
- };
79
- }
4
+ const DocumentController = buildCrudController(DocumentService, {
5
+ get: serviceHandler(DocumentService.get),
6
+ patch: serviceHandler(DocumentService.patch),
7
+ });
80
8
 
81
9
  export { DocumentController };
@@ -1,8 +1,6 @@
1
- import { loggerFactory } from '../../server/logger.js';
2
- import { DocumentController } from './document.controller.js';
3
1
  import express from 'express';
4
-
5
- const logger = loggerFactory(import.meta);
2
+ import { registerCrudRoutes } from '../../server/middlewares.js';
3
+ import { DocumentController } from './document.controller.js';
6
4
 
7
5
  class DocumentRouter {
8
6
  /**
@@ -11,23 +9,21 @@ class DocumentRouter {
11
9
  */
12
10
  static router(options) {
13
11
  const router = express.Router();
14
- router.post(`/:id`, options.authMiddleware, async (req, res) => await DocumentController.post(req, res, options));
15
- router.post(`/`, options.authMiddleware, async (req, res) => await DocumentController.post(req, res, options));
12
+ const authOnly = [options.authMiddleware];
13
+ // Public listings must come before the guarded generic /:id routes.
16
14
  router.get(`/public/high`, async (req, res) => await DocumentController.get(req, res, options));
17
15
  router.get(`/public`, async (req, res) => await DocumentController.get(req, res, options));
18
- router.get(`/:id`, options.authMiddleware, async (req, res) => await DocumentController.get(req, res, options));
19
- router.get(`/`, options.authMiddleware, async (req, res) => await DocumentController.get(req, res, options));
20
- router.put(`/:id`, options.authMiddleware, async (req, res) => await DocumentController.put(req, res, options));
21
- router.put(`/`, options.authMiddleware, async (req, res) => await DocumentController.put(req, res, options));
22
16
  router.patch(`/:id/copy-share-link`, async (req, res) => await DocumentController.patch(req, res, options));
23
17
  router.patch(
24
18
  `/:id/toggle-public`,
25
19
  options.authMiddleware,
26
20
  async (req, res) => await DocumentController.patch(req, res, options),
27
21
  );
28
- router.delete(`/:id`, options.authMiddleware, async (req, res) => await DocumentController.delete(req, res, options));
29
- router.delete(`/`, options.authMiddleware, async (req, res) => await DocumentController.delete(req, res, options));
30
- return router;
22
+ return registerCrudRoutes(router, DocumentController, options, {
23
+ readGuards: authOnly,
24
+ writeGuards: authOnly,
25
+ deleteAllGuards: authOnly,
26
+ });
31
27
  }
32
28
  }
33
29
 
@@ -1,59 +1,15 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { controllerHandler, sendSuccess, serviceHandler, setCrossOriginHeaders } from '../../server/middlewares.js';
2
2
  import { FileService } from './file.service.js';
3
- const logger = loggerFactory(import.meta);
4
3
 
5
4
  class FileController {
6
- static post = async (req, res, options) => {
7
- try {
8
- return res.status(200).json({
9
- status: 'success',
10
- data: await FileService.post(req, res, options),
11
- });
12
- } catch (error) {
13
- logger.error(error, error.stack);
14
- return res.status(400).json({
15
- status: 'error',
16
- message: error.message,
17
- });
18
- }
19
- };
20
- static get = async (req, res, options) => {
21
- try {
22
- if (req && req.headers && req.headers.origin) {
23
- res.set('Access-Control-Allow-Origin', req.headers.origin);
24
- } else res.setHeader('Access-Control-Allow-Origin', '*');
25
- res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
26
- const result = await FileService.get(req, res, options);
27
- if (result instanceof Buffer) {
28
- return res.status(200).end(result);
29
- }
30
- return res.status(200).json({
31
- status: 'success',
32
- data: result,
33
- });
34
- } catch (error) {
35
- logger.error(error, error.stack);
36
- return res.status(400).json({
37
- status: 'error',
38
- message: error.message,
39
- });
40
- }
41
- };
42
- static delete = async (req, res, options) => {
43
- try {
44
- const result = await FileService.delete(req, res, options);
45
- return res.status(200).json({
46
- status: 'success',
47
- data: result,
48
- });
49
- } catch (error) {
50
- logger.error(error, error.stack);
51
- return res.status(400).json({
52
- status: 'error',
53
- message: error.message,
54
- });
55
- }
56
- };
5
+ static post = serviceHandler(FileService.post);
6
+ static get = controllerHandler(async (req, res, options) => {
7
+ setCrossOriginHeaders(req, res);
8
+ const result = await FileService.get(req, res, options);
9
+ if (result instanceof Buffer) return res.status(200).end(result);
10
+ return sendSuccess(res, result);
11
+ });
12
+ static delete = serviceHandler(FileService.delete);
57
13
  }
58
14
 
59
15
  export { FileController };
@@ -1,12 +1,10 @@
1
+ import express from 'express';
1
2
  import { adminGuard } from '../../server/auth.js';
2
- import { loggerFactory } from '../../server/logger.js';
3
3
  import { FileController } from './file.controller.js';
4
- import express from 'express';
5
-
6
- const logger = loggerFactory(import.meta);
7
4
 
8
5
  class FileRouter {
9
6
  /**
7
+ * authenticated writes, admin-only deletes.
10
8
  * @param {import('../types.js').RouterOptions} options
11
9
  * @returns {import('express').Router}
12
10
  */
@@ -17,8 +15,18 @@ class FileRouter {
17
15
  router.get(`/blob/:id`, async (req, res) => await FileController.get(req, res, options));
18
16
  router.get(`/:id`, async (req, res) => await FileController.get(req, res, options));
19
17
  router.get(`/`, async (req, res) => await FileController.get(req, res, options));
20
- router.delete(`/:id`, options.authMiddleware, adminGuard, async (req, res) => await FileController.delete(req, res, options));
21
- router.delete(`/`, options.authMiddleware, adminGuard, async (req, res) => await FileController.delete(req, res, options));
18
+ router.delete(
19
+ `/:id`,
20
+ options.authMiddleware,
21
+ adminGuard,
22
+ async (req, res) => await FileController.delete(req, res, options),
23
+ );
24
+ router.delete(
25
+ `/`,
26
+ options.authMiddleware,
27
+ adminGuard,
28
+ async (req, res) => await FileController.delete(req, res, options),
29
+ );
22
30
  return router;
23
31
  }
24
32
  }
@@ -1,59 +1,14 @@
1
- import { loggerFactory } from '../../server/logger.js';
1
+ import { controllerHandler, sendSuccess, serviceHandler } from '../../server/middlewares.js';
2
2
  import { TestService } from './test.service.js';
3
3
 
4
- const logger = loggerFactory(import.meta);
5
-
6
4
  class TestController {
7
- static post = async (req, res, options) => {
8
- try {
9
- return res.status(200).json({
10
- status: 'success',
11
- data: await TestService.post(req, res, options),
12
- });
13
- } catch (error) {
14
- logger.error(error, error.stack);
15
- return res.status(400).json({
16
- status: 'error',
17
- message: error.message,
18
- });
19
- }
20
- };
21
- static get = async (req, res, options) => {
22
- try {
23
- const result = await TestService.get(req, res, options);
24
- if (result)
25
- return res.status(200).json({
26
- status: 'success',
27
- data: result,
28
- });
29
- else
30
- return res.status(400).json({
31
- status: 'error',
32
- });
33
- } catch (error) {
34
- logger.error(error, error.stack);
35
- return res.status(400).json({
36
- status: 'error',
37
- message: error.message,
38
- });
39
- }
40
- };
41
- static delete = async (req, res, options) => {
42
- try {
43
- const result = await TestService.delete(req, res, options);
44
-
45
- return res.status(200).json({
46
- status: 'success',
47
- data: result,
48
- });
49
- } catch (error) {
50
- logger.error(error, error.stack);
51
- return res.status(400).json({
52
- status: 'error',
53
- message: error.message,
54
- });
55
- }
56
- };
5
+ static post = serviceHandler(TestService.post);
6
+ static get = controllerHandler(async (req, res, options) => {
7
+ const result = await TestService.get(req, res, options);
8
+ if (result) return sendSuccess(res, result);
9
+ return res.status(400).json({ status: 'error' });
10
+ });
11
+ static delete = serviceHandler(TestService.delete);
57
12
  }
58
13
 
59
14
  export { TestController };
@@ -1,8 +1,5 @@
1
- import { loggerFactory } from '../../server/logger.js';
2
- import { TestController } from './test.controller.js';
3
1
  import express from 'express';
4
-
5
- const logger = loggerFactory(import.meta);
2
+ import { TestController } from './test.controller.js';
6
3
 
7
4
  class TestRouter {
8
5
  /**