@discover-cloud/shared 1.2.9 → 1.3.0
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.
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/permission-cache.service.d.ts +104 -16
- package/dist/authorization/permission-cache.service.js +156 -143
- package/dist/authorization/permission-checker.d.ts +30 -0
- package/dist/authorization/permission-checker.js +40 -0
- package/dist/contracts/auth-service/account.dto.d.ts +30 -0
- package/dist/contracts/auth-service/account.dto.js +7 -0
- package/dist/contracts/auth-service/auth.dto.d.ts +21 -0
- package/dist/contracts/auth-service/auth.dto.js +10 -0
- package/dist/dtos/auth-service.dto.d.ts +72 -26
- package/dist/dtos/auth-service.dto.js +4 -0
- package/dist/dtos/cloud-service.dto.d.ts +51 -27
- package/dist/dtos/cloud-service.dto.js +5 -0
- package/dist/dtos/insights-service.dto.d.ts +18 -27
- package/dist/dtos/insights-service.dto.js +8 -0
- package/dist/dtos/response.dto.d.ts +7 -84
- package/dist/dtos/response.dto.js +2 -21
- package/dist/dtos/user-service.dto.d.ts +118 -13
- package/dist/enums/domain.enums.d.ts +246 -75
- package/dist/enums/domain.enums.js +305 -102
- package/dist/enums/permissions.enums.d.ts +142 -80
- package/dist/enums/permissions.enums.js +174 -133
- package/dist/errors/app-error.d.ts +13 -18
- package/dist/errors/app-error.js +14 -20
- package/dist/errors/http-errors.d.ts +105 -17
- package/dist/errors/http-errors.js +118 -33
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.js +1 -0
- package/dist/http/request-context.d.ts +8 -0
- package/dist/http/request-context.js +37 -0
- package/dist/http/service-client.d.ts +91 -38
- package/dist/http/service-client.js +102 -53
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/jwt/index.d.ts +2 -1
- package/dist/jwt/index.js +2 -1
- package/dist/jwt/machine-jwt-verifier.d.ts +21 -0
- package/dist/jwt/machine-jwt-verifier.js +84 -0
- package/dist/jwt/machine-token-client.d.ts +35 -4
- package/dist/jwt/machine-token-client.js +57 -23
- package/dist/jwt/user-jwt-verifier.d.ts +31 -0
- package/dist/jwt/user-jwt-verifier.js +101 -0
- package/dist/messaging/index.d.ts +1 -0
- package/dist/{security → messaging}/index.js +1 -1
- package/dist/messaging/rabbitmq.client.d.ts +13 -0
- package/dist/messaging/rabbitmq.client.js +127 -0
- package/dist/middleware/error-handler.middleware.d.ts +8 -28
- package/dist/middleware/error-handler.middleware.js +61 -52
- package/dist/middleware/index.d.ts +7 -5
- package/dist/middleware/index.js +7 -5
- package/dist/middleware/request-context.middleware.d.ts +17 -0
- package/dist/middleware/request-context.middleware.js +73 -0
- package/dist/middleware/require-auth.middleware.d.ts +17 -70
- package/dist/middleware/require-auth.middleware.js +24 -103
- package/dist/middleware/require-machine.middleware.d.ts +38 -0
- package/dist/middleware/require-machine.middleware.js +123 -0
- package/dist/middleware/require-org-permission-from-body.middleware.d.ts +10 -0
- package/dist/middleware/require-org-permission-from-body.middleware.js +24 -0
- package/dist/middleware/require-org-permission.middleware.d.ts +19 -0
- package/dist/middleware/require-org-permission.middleware.js +115 -0
- package/dist/middleware/require-platform-permission.middleware.d.ts +19 -0
- package/dist/middleware/require-platform-permission.middleware.js +91 -0
- package/dist/middleware/require-user.middleware.d.ts +14 -0
- package/dist/middleware/require-user.middleware.js +30 -0
- package/dist/middleware/require-workspace-permission.middleware.d.ts +20 -0
- package/dist/middleware/require-workspace-permission.middleware.js +114 -0
- package/dist/middleware/validate.middleware.d.ts +29 -29
- package/dist/middleware/validate.middleware.js +30 -32
- package/dist/types/express.types.d.ts +83 -122
- package/dist/types/express.types.js +28 -47
- package/dist/utils/date.util.d.ts +6 -0
- package/dist/utils/date.util.js +11 -0
- package/dist/utils/env.util.d.ts +6 -0
- package/dist/utils/env.util.js +19 -0
- package/dist/utils/index.d.ts +5 -4
- package/dist/utils/index.js +5 -4
- package/dist/utils/logger.util.d.ts +26 -0
- package/dist/utils/logger.util.js +53 -0
- package/dist/utils/pagination.util.d.ts +6 -0
- package/dist/utils/pagination.util.js +20 -0
- package/dist/utils/response.util.d.ts +27 -0
- package/dist/utils/response.util.js +56 -0
- package/dist/utils/slug.util.d.ts +9 -0
- package/dist/utils/slug.util.js +32 -0
- package/dist/utils/url-safety.util.d.ts +6 -0
- package/dist/utils/url-safety.util.js +72 -0
- package/package.json +3 -1
- package/dist/authorization/permissions.d.ts +0 -78
- package/dist/authorization/permissions.js +0 -174
- package/dist/context/access-context.d.ts +0 -10
- package/dist/context/access-context.js +0 -2
- package/dist/context/index.d.ts +0 -1
- package/dist/context/index.js +0 -17
- package/dist/dto/auth-service.dtos.d.ts +0 -44
- package/dist/dto/auth-service.dtos.js +0 -2
- package/dist/dto/index.d.ts +0 -3
- package/dist/dto/index.js +0 -19
- package/dist/dto/response.dtos.d.ts +0 -55
- package/dist/dto/response.dtos.js +0 -6
- package/dist/dto/user-service.dtos.d.ts +0 -50
- package/dist/dto/user-service.dtos.js +0 -2
- package/dist/enums/auth-service.enums.d.ts +0 -12
- package/dist/enums/auth-service.enums.js +0 -17
- package/dist/enums/permissions.types.d.ts +0 -12
- package/dist/enums/permissions.types.js +0 -17
- package/dist/enums/user-service.enums.d.ts +0 -32
- package/dist/enums/user-service.enums.js +0 -41
- package/dist/internal/index.d.ts +0 -4
- package/dist/internal/index.js +0 -20
- package/dist/internal/internal-jwt.service.d.ts +0 -13
- package/dist/internal/internal-jwt.service.js +0 -88
- package/dist/internal/internal-jwt.types.d.ts +0 -7
- package/dist/internal/internal-jwt.types.js +0 -2
- package/dist/internal/internal-key-manager.d.ts +0 -16
- package/dist/internal/internal-key-manager.js +0 -67
- package/dist/internal/registry.d.ts +0 -8
- package/dist/internal/registry.js +0 -34
- package/dist/internal/service-client.d.ts +0 -9
- package/dist/internal/service-client.js +0 -94
- package/dist/jwt/internal-jwt-verifier.d.ts +0 -41
- package/dist/jwt/internal-jwt-verifier.js +0 -185
- package/dist/jwt/jwt-verifier.d.ts +0 -9
- package/dist/jwt/jwt-verifier.js +0 -36
- package/dist/jwt/service-client.d.ts +0 -7
- package/dist/jwt/service-client.js +0 -87
- package/dist/middleware/authorize.d.ts +0 -3
- package/dist/middleware/authorize.js +0 -24
- package/dist/middleware/authorize.middleware.d.ts +0 -54
- package/dist/middleware/authorize.middleware.js +0 -104
- package/dist/middleware/error-handler.d.ts +0 -4
- package/dist/middleware/error-handler.js +0 -23
- package/dist/middleware/request-id.d.ts +0 -2
- package/dist/middleware/request-id.js +0 -9
- package/dist/middleware/request-id.middleware.d.ts +0 -22
- package/dist/middleware/request-id.middleware.js +0 -34
- package/dist/middleware/require-auth.d.ts +0 -10
- package/dist/middleware/require-auth.js +0 -34
- package/dist/middleware/require-human.middleware.d.ts +0 -2
- package/dist/middleware/require-human.middleware.js +0 -18
- package/dist/middleware/require-internal.middleware.d.ts +0 -18
- package/dist/middleware/require-internal.middleware.js +0 -183
- package/dist/middleware/validate.d.ts +0 -5
- package/dist/middleware/validate.js +0 -18
- package/dist/middleware/validated-merge.middleware.d.ts +0 -20
- package/dist/middleware/validated-merge.middleware.js +0 -33
- package/dist/middleware/verify-internal-jwt.d.ts +0 -7
- package/dist/middleware/verify-internal-jwt.js +0 -25
- package/dist/security/guard.d.ts +0 -10
- package/dist/security/guard.js +0 -40
- package/dist/security/index.d.ts +0 -1
- package/dist/types/express.d.ts +0 -22
- package/dist/types/express.js +0 -3
- package/dist/utils/date.utils.d.ts +0 -25
- package/dist/utils/date.utils.js +0 -30
- package/dist/utils/env.d.ts +0 -46
- package/dist/utils/env.js +0 -61
- package/dist/utils/env.utils.d.ts +0 -46
- package/dist/utils/env.utils.js +0 -61
- package/dist/utils/logger.utils.d.ts +0 -66
- package/dist/utils/logger.utils.js +0 -97
- package/dist/utils/response.d.ts +0 -4
- package/dist/utils/response.js +0 -35
- package/dist/utils/response.utils.d.ts +0 -54
- package/dist/utils/response.utils.js +0 -85
package/dist/errors/app-error.js
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file app-error.ts
|
|
4
|
+
* @description Base class for operational errors throughout the application ecosystem.
|
|
5
|
+
* Structured to support clean serialization in global error boundaries.
|
|
6
|
+
*/
|
|
2
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
8
|
exports.AppError = void 0;
|
|
4
9
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Base class for all known operational errors across every service.
|
|
8
|
-
* Subclasses (see http-errors.ts) map to specific HTTP status codes and
|
|
9
|
-
* error codes that the global error handler serialises into responses.
|
|
10
|
-
*
|
|
11
|
-
* Design decisions:
|
|
12
|
-
* - GlobalErrorHandler catches `instanceof AppError` — no duck-typing,
|
|
13
|
-
* no accidental matches on arbitrary thrown objects.
|
|
14
|
-
* - details?: unknown (not any) — TypeScript's type checking is preserved
|
|
15
|
-
* on the most variable field. Callers that need a specific details shape
|
|
16
|
-
* should cast after an instanceof guard.
|
|
17
|
-
* - Object.freeze(this) — prevents accidental post-construction mutation of
|
|
18
|
-
* a thrown error. Freeze is shallow: if details is an object, its contents
|
|
19
|
-
* remain mutable. This is acceptable — details is for logging/response
|
|
20
|
-
* context, not program logic.
|
|
21
|
-
* - captureStackTrace — strips the AppError constructor frame from the stack
|
|
22
|
-
* so the trace points to the throw site, not the base class constructor.
|
|
10
|
+
* Base operational error class. Extends standard Error with application-specific
|
|
11
|
+
* machine codes and HTTP status mapping.
|
|
23
12
|
*/
|
|
24
13
|
class AppError extends Error {
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} code - Machine-readable stable error code identifier.
|
|
16
|
+
* @param {number} statusCode - Target HTTP status code mapping (e.g. 404, 409).
|
|
17
|
+
* @param {string} message - Human-readable error message.
|
|
18
|
+
* @param {unknown} [details] - Optional structured context context data.
|
|
19
|
+
*/
|
|
25
20
|
constructor(code, statusCode, message, details) {
|
|
26
21
|
super(message);
|
|
27
22
|
this.code = code;
|
|
28
23
|
this.statusCode = statusCode;
|
|
29
24
|
this.details = details;
|
|
30
|
-
this.name = this.constructor.name;
|
|
31
|
-
// Available in V8 (Node.js / Chrome) — no-ops gracefully in other engines.
|
|
25
|
+
this.name = this.constructor.name;
|
|
32
26
|
if (typeof Error.captureStackTrace === "function") {
|
|
33
27
|
Error.captureStackTrace(this, this.constructor);
|
|
34
28
|
}
|
|
@@ -1,47 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file http-errors.ts
|
|
3
|
+
* @description Operational error subclasses mapping common HTTP status codes to AppError types.
|
|
4
|
+
*/
|
|
1
5
|
import { AppError } from "./app-error";
|
|
2
6
|
/**
|
|
3
|
-
*
|
|
4
|
-
* ───────────────────────────────────────
|
|
5
|
-
* Typed subclasses of AppError for every common HTTP error status.
|
|
6
|
-
*
|
|
7
|
-
* GlobalErrorHandler catches these via `instanceof AppError` and maps
|
|
8
|
-
* statusCode + code directly to the response — no additional switch/if needed.
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* throw new NotFoundError("Account not found");
|
|
12
|
-
* throw new ConflictError("Email already in use");
|
|
13
|
-
* throw new BadRequestError("Validation failed", { field: "email" });
|
|
14
|
-
*
|
|
15
|
-
* Adding a new error type:
|
|
16
|
-
* 1. Add a subclass here following the existing pattern.
|
|
17
|
-
* 2. Pick the correct HTTP status code.
|
|
18
|
-
* 3. Choose a SCREAMING_SNAKE_CASE code that is stable across versions
|
|
19
|
-
* (clients may key on it for error handling).
|
|
7
|
+
* 400 Bad Request error.
|
|
20
8
|
*/
|
|
21
9
|
export declare class BadRequestError extends AppError {
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} [message] - Error explanation message.
|
|
12
|
+
* @param {unknown} [details] - Detailed error context.
|
|
13
|
+
*/
|
|
22
14
|
constructor(message?: string, details?: unknown);
|
|
23
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* 401 Unauthorized error.
|
|
18
|
+
*/
|
|
24
19
|
export declare class UnauthorizedError extends AppError {
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} [message] - Error explanation message.
|
|
22
|
+
* @param {unknown} [details] - Detailed error context.
|
|
23
|
+
*/
|
|
25
24
|
constructor(message?: string, details?: unknown);
|
|
26
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* 403 Forbidden error.
|
|
28
|
+
*/
|
|
27
29
|
export declare class ForbiddenError extends AppError {
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} [message] - Error explanation message.
|
|
32
|
+
* @param {unknown} [details] - Detailed error context.
|
|
33
|
+
*/
|
|
28
34
|
constructor(message?: string, details?: unknown);
|
|
29
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* 404 Not Found error.
|
|
38
|
+
*/
|
|
30
39
|
export declare class NotFoundError extends AppError {
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} [message] - Error explanation message.
|
|
42
|
+
* @param {unknown} [details] - Detailed error context.
|
|
43
|
+
*/
|
|
44
|
+
constructor(message?: string, details?: unknown);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 410 Gone error.
|
|
48
|
+
*/
|
|
49
|
+
export declare class GoneError extends AppError {
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} [message] - Error explanation message.
|
|
52
|
+
* @param {unknown} [details] - Detailed error context.
|
|
53
|
+
*/
|
|
31
54
|
constructor(message?: string, details?: unknown);
|
|
32
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* 409 Conflict error.
|
|
58
|
+
*/
|
|
33
59
|
export declare class ConflictError extends AppError {
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} [message] - Error explanation message.
|
|
62
|
+
* @param {unknown} [details] - Detailed error context.
|
|
63
|
+
*/
|
|
34
64
|
constructor(message?: string, details?: unknown);
|
|
35
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* 422 Unprocessable Entity error.
|
|
68
|
+
*/
|
|
36
69
|
export declare class UnprocessableEntityError extends AppError {
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} [message] - Error explanation message.
|
|
72
|
+
* @param {unknown} [details] - Detailed error context.
|
|
73
|
+
*/
|
|
37
74
|
constructor(message?: string, details?: unknown);
|
|
38
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 429 Too Many Requests error.
|
|
78
|
+
*/
|
|
39
79
|
export declare class TooManyRequestsError extends AppError {
|
|
80
|
+
/**
|
|
81
|
+
* @param {string} [message] - Error explanation message.
|
|
82
|
+
* @param {unknown} [details] - Detailed error context.
|
|
83
|
+
*/
|
|
40
84
|
constructor(message?: string, details?: unknown);
|
|
41
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* 500 Internal Server Error.
|
|
88
|
+
*/
|
|
42
89
|
export declare class InternalServerError extends AppError {
|
|
90
|
+
/**
|
|
91
|
+
* @param {string} [message] - Error explanation message.
|
|
92
|
+
* @param {unknown} [details] - Detailed error context.
|
|
93
|
+
*/
|
|
43
94
|
constructor(message?: string, details?: unknown);
|
|
44
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* 503 Service Unavailable error.
|
|
98
|
+
*/
|
|
45
99
|
export declare class ServiceUnavailableError extends AppError {
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} [message] - Error explanation message.
|
|
102
|
+
* @param {unknown} [details] - Detailed error context.
|
|
103
|
+
*/
|
|
104
|
+
constructor(message?: string, details?: unknown);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 403 Account Pending Deletion error.
|
|
108
|
+
*
|
|
109
|
+
* Thrown when a soft-deleted user account is accessed in a context that does
|
|
110
|
+
* not allow implicit restore (e.g. login). The client should present a recovery
|
|
111
|
+
* prompt rather than treating this as a generic auth failure.
|
|
112
|
+
*/
|
|
113
|
+
export declare class AccountPendingDeletionError extends AppError {
|
|
114
|
+
constructor(message?: string, details?: unknown);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 403 Organization Pending Deletion error.
|
|
118
|
+
*
|
|
119
|
+
* Thrown when a soft-deleted organization is accessed in a context that does
|
|
120
|
+
* not allow implicit restore (e.g. slug conflict on create). The client should
|
|
121
|
+
* prompt the user to restore the organization instead.
|
|
122
|
+
*/
|
|
123
|
+
export declare class OrganizationPendingDeletionError extends AppError {
|
|
124
|
+
constructor(message?: string, details?: unknown);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 403 Workspace Pending Deletion error.
|
|
128
|
+
*
|
|
129
|
+
* Thrown when a soft-deleted workspace is accessed in a context that does
|
|
130
|
+
* not allow implicit restore (e.g. slug conflict on create). The client should
|
|
131
|
+
* prompt the user to restore the workspace instead.
|
|
132
|
+
*/
|
|
133
|
+
export declare class WorkspacePendingDeletionError extends AppError {
|
|
46
134
|
constructor(message?: string, details?: unknown);
|
|
47
135
|
}
|
|
@@ -1,92 +1,177 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file http-errors.ts
|
|
4
|
+
* @description Operational error subclasses mapping common HTTP status codes to AppError types.
|
|
5
|
+
*/
|
|
2
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ServiceUnavailableError = exports.InternalServerError = exports.TooManyRequestsError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = void 0;
|
|
7
|
+
exports.WorkspacePendingDeletionError = exports.OrganizationPendingDeletionError = exports.AccountPendingDeletionError = exports.ServiceUnavailableError = exports.InternalServerError = exports.TooManyRequestsError = exports.UnprocessableEntityError = exports.ConflictError = exports.GoneError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = void 0;
|
|
4
8
|
const app_error_1 = require("./app-error");
|
|
5
9
|
/**
|
|
6
|
-
*
|
|
7
|
-
* ───────────────────────────────────────
|
|
8
|
-
* Typed subclasses of AppError for every common HTTP error status.
|
|
9
|
-
*
|
|
10
|
-
* GlobalErrorHandler catches these via `instanceof AppError` and maps
|
|
11
|
-
* statusCode + code directly to the response — no additional switch/if needed.
|
|
12
|
-
*
|
|
13
|
-
* Usage:
|
|
14
|
-
* throw new NotFoundError("Account not found");
|
|
15
|
-
* throw new ConflictError("Email already in use");
|
|
16
|
-
* throw new BadRequestError("Validation failed", { field: "email" });
|
|
17
|
-
*
|
|
18
|
-
* Adding a new error type:
|
|
19
|
-
* 1. Add a subclass here following the existing pattern.
|
|
20
|
-
* 2. Pick the correct HTTP status code.
|
|
21
|
-
* 3. Choose a SCREAMING_SNAKE_CASE code that is stable across versions
|
|
22
|
-
* (clients may key on it for error handling).
|
|
10
|
+
* 400 Bad Request error.
|
|
23
11
|
*/
|
|
24
|
-
// 400 — The request is malformed or contains invalid input.
|
|
25
12
|
class BadRequestError extends app_error_1.AppError {
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} [message] - Error explanation message.
|
|
15
|
+
* @param {unknown} [details] - Detailed error context.
|
|
16
|
+
*/
|
|
26
17
|
constructor(message = "Bad Request", details) {
|
|
27
18
|
super("BAD_REQUEST", 400, message, details);
|
|
28
19
|
}
|
|
29
20
|
}
|
|
30
21
|
exports.BadRequestError = BadRequestError;
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
/**
|
|
23
|
+
* 401 Unauthorized error.
|
|
24
|
+
*/
|
|
33
25
|
class UnauthorizedError extends app_error_1.AppError {
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} [message] - Error explanation message.
|
|
28
|
+
* @param {unknown} [details] - Detailed error context.
|
|
29
|
+
*/
|
|
34
30
|
constructor(message = "Unauthorized", details) {
|
|
35
31
|
super("UNAUTHORIZED", 401, message, details);
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
34
|
exports.UnauthorizedError = UnauthorizedError;
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
/**
|
|
36
|
+
* 403 Forbidden error.
|
|
37
|
+
*/
|
|
41
38
|
class ForbiddenError extends app_error_1.AppError {
|
|
39
|
+
/**
|
|
40
|
+
* @param {string} [message] - Error explanation message.
|
|
41
|
+
* @param {unknown} [details] - Detailed error context.
|
|
42
|
+
*/
|
|
42
43
|
constructor(message = "Forbidden", details) {
|
|
43
44
|
super("FORBIDDEN", 403, message, details);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
exports.ForbiddenError = ForbiddenError;
|
|
47
|
-
|
|
48
|
+
/**
|
|
49
|
+
* 404 Not Found error.
|
|
50
|
+
*/
|
|
48
51
|
class NotFoundError extends app_error_1.AppError {
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} [message] - Error explanation message.
|
|
54
|
+
* @param {unknown} [details] - Detailed error context.
|
|
55
|
+
*/
|
|
49
56
|
constructor(message = "Not Found", details) {
|
|
50
57
|
super("NOT_FOUND", 404, message, details);
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
60
|
exports.NotFoundError = NotFoundError;
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
/**
|
|
62
|
+
* 410 Gone error.
|
|
63
|
+
*/
|
|
64
|
+
class GoneError extends app_error_1.AppError {
|
|
65
|
+
/**
|
|
66
|
+
* @param {string} [message] - Error explanation message.
|
|
67
|
+
* @param {unknown} [details] - Detailed error context.
|
|
68
|
+
*/
|
|
69
|
+
constructor(message = "Gone", details) {
|
|
70
|
+
super("GONE", 410, message, details);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.GoneError = GoneError;
|
|
74
|
+
/**
|
|
75
|
+
* 409 Conflict error.
|
|
76
|
+
*/
|
|
56
77
|
class ConflictError extends app_error_1.AppError {
|
|
78
|
+
/**
|
|
79
|
+
* @param {string} [message] - Error explanation message.
|
|
80
|
+
* @param {unknown} [details] - Detailed error context.
|
|
81
|
+
*/
|
|
57
82
|
constructor(message = "Conflict", details) {
|
|
58
83
|
super("CONFLICT", 409, message, details);
|
|
59
84
|
}
|
|
60
85
|
}
|
|
61
86
|
exports.ConflictError = ConflictError;
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
/**
|
|
88
|
+
* 422 Unprocessable Entity error.
|
|
89
|
+
*/
|
|
64
90
|
class UnprocessableEntityError extends app_error_1.AppError {
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} [message] - Error explanation message.
|
|
93
|
+
* @param {unknown} [details] - Detailed error context.
|
|
94
|
+
*/
|
|
65
95
|
constructor(message = "Unprocessable Entity", details) {
|
|
66
96
|
super("UNPROCESSABLE_ENTITY", 422, message, details);
|
|
67
97
|
}
|
|
68
98
|
}
|
|
69
99
|
exports.UnprocessableEntityError = UnprocessableEntityError;
|
|
70
|
-
|
|
100
|
+
/**
|
|
101
|
+
* 429 Too Many Requests error.
|
|
102
|
+
*/
|
|
71
103
|
class TooManyRequestsError extends app_error_1.AppError {
|
|
104
|
+
/**
|
|
105
|
+
* @param {string} [message] - Error explanation message.
|
|
106
|
+
* @param {unknown} [details] - Detailed error context.
|
|
107
|
+
*/
|
|
72
108
|
constructor(message = "Too Many Requests", details) {
|
|
73
109
|
super("TOO_MANY_REQUESTS", 429, message, details);
|
|
74
110
|
}
|
|
75
111
|
}
|
|
76
112
|
exports.TooManyRequestsError = TooManyRequestsError;
|
|
77
|
-
|
|
78
|
-
|
|
113
|
+
/**
|
|
114
|
+
* 500 Internal Server Error.
|
|
115
|
+
*/
|
|
79
116
|
class InternalServerError extends app_error_1.AppError {
|
|
117
|
+
/**
|
|
118
|
+
* @param {string} [message] - Error explanation message.
|
|
119
|
+
* @param {unknown} [details] - Detailed error context.
|
|
120
|
+
*/
|
|
80
121
|
constructor(message = "Internal Server Error", details) {
|
|
81
122
|
super("INTERNAL_SERVER_ERROR", 500, message, details);
|
|
82
123
|
}
|
|
83
124
|
}
|
|
84
125
|
exports.InternalServerError = InternalServerError;
|
|
85
|
-
|
|
86
|
-
|
|
126
|
+
/**
|
|
127
|
+
* 503 Service Unavailable error.
|
|
128
|
+
*/
|
|
87
129
|
class ServiceUnavailableError extends app_error_1.AppError {
|
|
130
|
+
/**
|
|
131
|
+
* @param {string} [message] - Error explanation message.
|
|
132
|
+
* @param {unknown} [details] - Detailed error context.
|
|
133
|
+
*/
|
|
88
134
|
constructor(message = "Service Unavailable", details) {
|
|
89
135
|
super("SERVICE_UNAVAILABLE", 503, message, details);
|
|
90
136
|
}
|
|
91
137
|
}
|
|
92
138
|
exports.ServiceUnavailableError = ServiceUnavailableError;
|
|
139
|
+
/**
|
|
140
|
+
* 403 Account Pending Deletion error.
|
|
141
|
+
*
|
|
142
|
+
* Thrown when a soft-deleted user account is accessed in a context that does
|
|
143
|
+
* not allow implicit restore (e.g. login). The client should present a recovery
|
|
144
|
+
* prompt rather than treating this as a generic auth failure.
|
|
145
|
+
*/
|
|
146
|
+
class AccountPendingDeletionError extends app_error_1.AppError {
|
|
147
|
+
constructor(message = "This account is scheduled for deletion. Recover it within the 30-day window.", details) {
|
|
148
|
+
super("ACCOUNT_PENDING_DELETION", 403, message, details);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.AccountPendingDeletionError = AccountPendingDeletionError;
|
|
152
|
+
/**
|
|
153
|
+
* 403 Organization Pending Deletion error.
|
|
154
|
+
*
|
|
155
|
+
* Thrown when a soft-deleted organization is accessed in a context that does
|
|
156
|
+
* not allow implicit restore (e.g. slug conflict on create). The client should
|
|
157
|
+
* prompt the user to restore the organization instead.
|
|
158
|
+
*/
|
|
159
|
+
class OrganizationPendingDeletionError extends app_error_1.AppError {
|
|
160
|
+
constructor(message = "This organization is scheduled for deletion. Restore it within the 30-day window.", details) {
|
|
161
|
+
super("ORGANIZATION_PENDING_DELETION", 403, message, details);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.OrganizationPendingDeletionError = OrganizationPendingDeletionError;
|
|
165
|
+
/**
|
|
166
|
+
* 403 Workspace Pending Deletion error.
|
|
167
|
+
*
|
|
168
|
+
* Thrown when a soft-deleted workspace is accessed in a context that does
|
|
169
|
+
* not allow implicit restore (e.g. slug conflict on create). The client should
|
|
170
|
+
* prompt the user to restore the workspace instead.
|
|
171
|
+
*/
|
|
172
|
+
class WorkspacePendingDeletionError extends app_error_1.AppError {
|
|
173
|
+
constructor(message = "This workspace is scheduled for deletion. Restore it within the 30-day window.", details) {
|
|
174
|
+
super("WORKSPACE_PENDING_DELETION", 403, message, details);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.WorkspacePendingDeletionError = WorkspacePendingDeletionError;
|
package/dist/http/index.d.ts
CHANGED
package/dist/http/index.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Request } from "express";
|
|
2
|
+
import { UserContext, MachineContext, RequestMetadataContext } from "../types";
|
|
3
|
+
export declare function getUserContext(req: Request): UserContext;
|
|
4
|
+
export declare function getMachineContext(req: Request): MachineContext;
|
|
5
|
+
export declare function getRequestContext(req: Request): RequestMetadataContext;
|
|
6
|
+
export declare function getValidatedBody<T>(req: Request): T;
|
|
7
|
+
export declare function getValidatedParams<T>(req: Request): T;
|
|
8
|
+
export declare function getValidatedQuery<T>(req: Request): T;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUserContext = getUserContext;
|
|
4
|
+
exports.getMachineContext = getMachineContext;
|
|
5
|
+
exports.getRequestContext = getRequestContext;
|
|
6
|
+
exports.getValidatedBody = getValidatedBody;
|
|
7
|
+
exports.getValidatedParams = getValidatedParams;
|
|
8
|
+
exports.getValidatedQuery = getValidatedQuery;
|
|
9
|
+
function getUserContext(req) {
|
|
10
|
+
const ctx = req.authContext;
|
|
11
|
+
if (!ctx || ctx.type !== "user") {
|
|
12
|
+
throw new Error("User context missing. Did you forget requireUser?");
|
|
13
|
+
}
|
|
14
|
+
return ctx;
|
|
15
|
+
}
|
|
16
|
+
function getMachineContext(req) {
|
|
17
|
+
const ctx = req.authContext;
|
|
18
|
+
if (!ctx || ctx.type !== "machine") {
|
|
19
|
+
throw new Error("Machine context missing. Did you forget requireMachine?");
|
|
20
|
+
}
|
|
21
|
+
return ctx;
|
|
22
|
+
}
|
|
23
|
+
function getRequestContext(req) {
|
|
24
|
+
if (!req.requestContext) {
|
|
25
|
+
throw new Error("Request context missing. Did you forget requestContext middleware?");
|
|
26
|
+
}
|
|
27
|
+
return req.requestContext;
|
|
28
|
+
}
|
|
29
|
+
function getValidatedBody(req) {
|
|
30
|
+
return req.validated?.body;
|
|
31
|
+
}
|
|
32
|
+
function getValidatedParams(req) {
|
|
33
|
+
return req.validated?.params;
|
|
34
|
+
}
|
|
35
|
+
function getValidatedQuery(req) {
|
|
36
|
+
return req.validated?.query;
|
|
37
|
+
}
|
|
@@ -1,61 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file service-client.ts
|
|
3
|
+
* @description HTTP client wrapper for service-to-service communication.
|
|
4
|
+
* Handles automatic JWT forwarding, request correlation tracking via header propagation,
|
|
5
|
+
* and automatic retry behaviors on transient failures.
|
|
6
|
+
*/
|
|
1
7
|
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
|
|
2
8
|
import { Request } from "express";
|
|
3
9
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* HTTP client for service-to-service communication.
|
|
7
|
-
*
|
|
8
|
-
* Two call patterns:
|
|
9
|
-
*
|
|
10
|
-
* Pattern 1 — JWT-forwarding (user-initiated requests)
|
|
11
|
-
* Pass the current Express Request — Authorization + x-request-id are
|
|
12
|
-
* forwarded automatically. Used when the downstream service needs to
|
|
13
|
-
* act on behalf of the authenticated user.
|
|
14
|
-
* Methods: getWithAuth, postWithAuth, patchWithAuth, deleteWithAuth
|
|
15
|
-
*
|
|
16
|
-
* Pattern 2 — Internal calls (service-initiated, no incoming request)
|
|
17
|
-
* Pass explicit headers — used when calls originate from service logic
|
|
18
|
-
* rather than from an HTTP handler (e.g. auth service → user service
|
|
19
|
-
* during account creation). Caller is responsible for providing the
|
|
20
|
-
* X-Internal-Secret header.
|
|
21
|
-
* Methods: get, post, patch, delete
|
|
22
|
-
*
|
|
23
|
-
* Retry strategy:
|
|
24
|
-
* - Retries on network errors and 5xx responses only (up to 3 attempts,
|
|
25
|
-
* exponential backoff). 4xx responses are never retried — they are
|
|
26
|
-
* deterministic caller errors that won't resolve on retry.
|
|
27
|
-
*
|
|
28
|
-
* Timeout:
|
|
29
|
-
* - 8 seconds per request (covers retry delays separately via axiosRetry).
|
|
30
|
-
* Adjust per-call via config.timeout if a specific route needs more.
|
|
10
|
+
* ServiceClient encapsulates an AxiosInstance configured for service-to-service HTTP requests.
|
|
11
|
+
* Supports token forwarding (Pattern 1) and secure internal calls (Pattern 2).
|
|
31
12
|
*/
|
|
32
13
|
export declare class ServiceClient {
|
|
33
14
|
readonly http: AxiosInstance;
|
|
15
|
+
/**
|
|
16
|
+
* Initializes the Axios instance with a base URL, timeout, and retry rules.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} baseURL - Downstream service base URL.
|
|
19
|
+
*/
|
|
34
20
|
constructor(baseURL: string);
|
|
21
|
+
/**
|
|
22
|
+
* Performs an HTTP GET request while forwarding authorization and request headers.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} url - Request target endpoint relative path.
|
|
25
|
+
* @param {Request} req - The current Express request object.
|
|
26
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
27
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
28
|
+
*/
|
|
35
29
|
getWithAuth<T = unknown>(url: string, req: Request, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
30
|
+
/**
|
|
31
|
+
* Performs an HTTP POST request while forwarding authorization and request headers.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} url - Request target endpoint relative path.
|
|
34
|
+
* @param {unknown} data - JSON request body data payload.
|
|
35
|
+
* @param {Request} req - The current Express request object.
|
|
36
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
37
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
38
|
+
*/
|
|
36
39
|
postWithAuth<T = unknown>(url: string, data: unknown, req: Request, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
40
|
+
/**
|
|
41
|
+
* Performs an HTTP PATCH request while forwarding authorization and request headers.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} url - Request target endpoint relative path.
|
|
44
|
+
* @param {unknown} data - JSON request body data payload.
|
|
45
|
+
* @param {Request} req - The current Express request object.
|
|
46
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
47
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
48
|
+
*/
|
|
37
49
|
patchWithAuth<T = unknown>(url: string, data: unknown, req: Request, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
50
|
+
/**
|
|
51
|
+
* Performs an HTTP DELETE request while forwarding authorization and request headers.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} url - Request target endpoint relative path.
|
|
54
|
+
* @param {Request} req - The current Express request object.
|
|
55
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
56
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
57
|
+
*/
|
|
38
58
|
deleteWithAuth<T = unknown>(url: string, req: Request, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
59
|
+
/**
|
|
60
|
+
* Performs an HTTP GET request with explicit header configurations.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} url - Request target endpoint relative path.
|
|
63
|
+
* @param {Record<string, string>} headers - Header keys and values to attach.
|
|
64
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
65
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
66
|
+
*/
|
|
39
67
|
get<T = unknown>(url: string, headers: Record<string, string>, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
68
|
+
/**
|
|
69
|
+
* Performs an HTTP POST request with explicit header configurations.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} url - Request target endpoint relative path.
|
|
72
|
+
* @param {unknown} data - JSON request body data payload.
|
|
73
|
+
* @param {Record<string, string>} headers - Header keys and values to attach.
|
|
74
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
75
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
76
|
+
*/
|
|
40
77
|
post<T = unknown>(url: string, data: unknown, headers: Record<string, string>, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
78
|
+
/**
|
|
79
|
+
* Performs an HTTP PATCH request with explicit header configurations.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} url - Request target endpoint relative path.
|
|
82
|
+
* @param {unknown} data - JSON request body data payload.
|
|
83
|
+
* @param {Record<string, string>} headers - Header keys and values to attach.
|
|
84
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
85
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
86
|
+
*/
|
|
41
87
|
patch<T = unknown>(url: string, data: unknown, headers: Record<string, string>, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
88
|
+
/**
|
|
89
|
+
* Performs an HTTP DELETE request with explicit header configurations.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} url - Request target endpoint relative path.
|
|
92
|
+
* @param {Record<string, string>} headers - Header keys and values to attach.
|
|
93
|
+
* @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
|
|
94
|
+
* @returns {Promise<AxiosResponse<T>>} Axios response promise.
|
|
95
|
+
*/
|
|
42
96
|
delete<T = unknown>(url: string, headers: Record<string, string>, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
43
97
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* and merges them into the Axios config headers.
|
|
98
|
+
* Extracts authorization credentials and tracing identifiers from Express requests
|
|
99
|
+
* and merges them into Axios config header values.
|
|
47
100
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* 3. Synthetic fallback (timestamp) — should not appear in production
|
|
52
|
-
* if request-id middleware is wired correctly in the gateway
|
|
101
|
+
* @param {Request} req - The current Express request.
|
|
102
|
+
* @param {AxiosRequestConfig} [config] - The existing Axios request configuration.
|
|
103
|
+
* @returns {AxiosRequestConfig} The merged Axios request configuration.
|
|
53
104
|
*/
|
|
54
105
|
private mergeAuth;
|
|
55
106
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
107
|
+
* Integrates user-supplied headers into the request configuration object.
|
|
108
|
+
*
|
|
109
|
+
* @param {Record<string, string>} headers - The headers to merge.
|
|
110
|
+
* @param {AxiosRequestConfig} [config] - The existing Axios request configuration.
|
|
111
|
+
* @returns {AxiosRequestConfig} The merged Axios request configuration.
|
|
59
112
|
*/
|
|
60
113
|
private mergeHeaders;
|
|
61
114
|
}
|