@discover-cloud/shared 1.0.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.
Files changed (75) hide show
  1. package/dist/context/access-context.d.ts +10 -0
  2. package/dist/context/access-context.js +2 -0
  3. package/dist/context/index.d.ts +1 -0
  4. package/dist/context/index.js +17 -0
  5. package/dist/dto/auth-service.dtos.d.ts +51 -0
  6. package/dist/dto/auth-service.dtos.js +2 -0
  7. package/dist/dto/index.d.ts +3 -0
  8. package/dist/dto/index.js +19 -0
  9. package/dist/dto/response.dtos.d.ts +48 -0
  10. package/dist/dto/response.dtos.js +2 -0
  11. package/dist/dto/user-service.dtos.d.ts +54 -0
  12. package/dist/dto/user-service.dtos.js +2 -0
  13. package/dist/enums/auth-service.enums.d.ts +12 -0
  14. package/dist/enums/auth-service.enums.js +17 -0
  15. package/dist/enums/index.d.ts +3 -0
  16. package/dist/enums/index.js +19 -0
  17. package/dist/enums/permissions.types.d.ts +12 -0
  18. package/dist/enums/permissions.types.js +17 -0
  19. package/dist/enums/user-service.enums.d.ts +32 -0
  20. package/dist/enums/user-service.enums.js +41 -0
  21. package/dist/errors/app-error.d.ts +6 -0
  22. package/dist/errors/app-error.js +19 -0
  23. package/dist/errors/http-errors.d.ts +22 -0
  24. package/dist/errors/http-errors.js +46 -0
  25. package/dist/errors/index.d.ts +2 -0
  26. package/dist/errors/index.js +18 -0
  27. package/dist/http/service-client.d.ts +15 -0
  28. package/dist/http/service-client.js +57 -0
  29. package/dist/index.d.ts +8 -0
  30. package/dist/index.js +24 -0
  31. package/dist/internal/index.d.ts +4 -0
  32. package/dist/internal/index.js +20 -0
  33. package/dist/internal/internal-jwt.service.d.ts +13 -0
  34. package/dist/internal/internal-jwt.service.js +88 -0
  35. package/dist/internal/internal-jwt.types.d.ts +7 -0
  36. package/dist/internal/internal-jwt.types.js +2 -0
  37. package/dist/internal/internal-key-manager.d.ts +16 -0
  38. package/dist/internal/internal-key-manager.js +67 -0
  39. package/dist/internal/registry.d.ts +8 -0
  40. package/dist/internal/registry.js +34 -0
  41. package/dist/internal/service-client.d.ts +9 -0
  42. package/dist/internal/service-client.js +94 -0
  43. package/dist/jwt/index.d.ts +2 -0
  44. package/dist/jwt/index.js +18 -0
  45. package/dist/jwt/jwt-verifier.d.ts +9 -0
  46. package/dist/jwt/jwt-verifier.js +36 -0
  47. package/dist/jwt/service-client.d.ts +7 -0
  48. package/dist/jwt/service-client.js +87 -0
  49. package/dist/middleware/authorize.d.ts +3 -0
  50. package/dist/middleware/authorize.js +24 -0
  51. package/dist/middleware/error-handler.d.ts +4 -0
  52. package/dist/middleware/error-handler.js +23 -0
  53. package/dist/middleware/index.d.ts +5 -0
  54. package/dist/middleware/index.js +21 -0
  55. package/dist/middleware/request-id.d.ts +2 -0
  56. package/dist/middleware/request-id.js +9 -0
  57. package/dist/middleware/require-auth.d.ts +10 -0
  58. package/dist/middleware/require-auth.js +34 -0
  59. package/dist/middleware/validate.d.ts +5 -0
  60. package/dist/middleware/validate.js +18 -0
  61. package/dist/middleware/verify-internal-jwt.d.ts +7 -0
  62. package/dist/middleware/verify-internal-jwt.js +25 -0
  63. package/dist/security/guard.d.ts +10 -0
  64. package/dist/security/guard.js +40 -0
  65. package/dist/security/index.d.ts +1 -0
  66. package/dist/security/index.js +17 -0
  67. package/dist/types/express.d.ts +22 -0
  68. package/dist/types/express.js +3 -0
  69. package/dist/types/index.d.ts +1 -0
  70. package/dist/types/index.js +17 -0
  71. package/dist/utils/index.d.ts +1 -0
  72. package/dist/utils/index.js +17 -0
  73. package/dist/utils/response.d.ts +3 -0
  74. package/dist/utils/response.js +32 -0
  75. package/package.json +35 -0
@@ -0,0 +1,13 @@
1
+ import { InternalKeyManager } from "./internal-key-manager";
2
+ import { InternalJwtPayload } from "./internal-jwt.types";
3
+ export declare class InternalJwtService {
4
+ private readonly keyManager;
5
+ private readonly serviceName;
6
+ private jwksCache;
7
+ constructor(keyManager: InternalKeyManager);
8
+ sign(payload: {
9
+ requestId: string;
10
+ }, targetService: string): Promise<string>;
11
+ verify(token: string): Promise<InternalJwtPayload>;
12
+ private getRemoteJWKS;
13
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.InternalJwtService = void 0;
37
+ const jose = __importStar(require("jose"));
38
+ class InternalJwtService {
39
+ constructor(keyManager) {
40
+ this.keyManager = keyManager;
41
+ this.jwksCache = new Map();
42
+ this.serviceName = process.env.SERVICE_NAME || "unknown-service";
43
+ }
44
+ async sign(payload, targetService) {
45
+ const signer = this.keyManager.getPrivateKey();
46
+ const kid = this.keyManager.getKid();
47
+ return new jose.SignJWT({
48
+ ...payload,
49
+ typ: "internal"
50
+ })
51
+ .setProtectedHeader({ alg: "RS256", kid })
52
+ .setIssuer(this.serviceName)
53
+ .setAudience(targetService)
54
+ .setIssuedAt()
55
+ .setExpirationTime("1m")
56
+ .sign(signer);
57
+ }
58
+ async verify(token) {
59
+ const unverified = jose.decodeJwt(token);
60
+ if (!unverified.iss)
61
+ throw new Error("Missing issuer");
62
+ if (unverified.typ !== "internal")
63
+ throw new Error("Invalid token type");
64
+ const jwks = this.getRemoteJWKS(unverified.iss);
65
+ const { payload } = await jose.jwtVerify(token, jwks, {
66
+ algorithms: ["RS256"],
67
+ audience: this.serviceName,
68
+ issuer: unverified.iss
69
+ });
70
+ return payload;
71
+ }
72
+ getRemoteJWKS(issuer) {
73
+ const envKey = `${issuer.replace(/-/g, "_").toUpperCase()}_URL`;
74
+ const baseUrl = process.env[envKey];
75
+ const url = baseUrl
76
+ ? `${baseUrl}/internal/jwks`
77
+ : `http://${issuer}/internal/jwks`;
78
+ if (!this.jwksCache.has(url)) {
79
+ console.log(`[InternalJwt] Caching JWKS for ${issuer} at ${url}`);
80
+ this.jwksCache.set(url, jose.createRemoteJWKSet(new URL(url), {
81
+ cacheMaxAge: 600000,
82
+ cooldownDuration: 30000
83
+ }));
84
+ }
85
+ return this.jwksCache.get(url);
86
+ }
87
+ }
88
+ exports.InternalJwtService = InternalJwtService;
@@ -0,0 +1,7 @@
1
+ import { JWTPayload } from "jose";
2
+ export interface InternalJwtPayload extends JWTPayload {
3
+ iss: string;
4
+ aud: string;
5
+ typ: "internal";
6
+ requestId: string;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,16 @@
1
+ import { JWK } from "jose";
2
+ import { KeyObject } from "crypto";
3
+ export declare class InternalKeyManager {
4
+ private privateKey;
5
+ private publicKey;
6
+ private jwks;
7
+ private readonly serviceName;
8
+ private readonly keyPath;
9
+ constructor();
10
+ private init;
11
+ getPrivateKey(): CryptoKey | KeyObject;
12
+ getPublicJwks(): {
13
+ keys: JWK[];
14
+ };
15
+ getKid(): string;
16
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InternalKeyManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const jose_1 = require("jose");
10
+ class InternalKeyManager {
11
+ constructor() {
12
+ this.jwks = [];
13
+ this.serviceName = process.env.SERVICE_NAME || "unknown-service";
14
+ this.keyPath = (() => {
15
+ const envPath = process.env.INTERNAL_KEYS_PATH;
16
+ if (!envPath) {
17
+ console.warn("[InternalKeyManager] INTERNAL_KEYS_PATH not set. Using default: src/keys/internal");
18
+ return path_1.default.join(process.cwd(), "src/keys/internal");
19
+ }
20
+ return path_1.default.isAbsolute(envPath) ? envPath : path_1.default.join(process.cwd(), envPath);
21
+ })();
22
+ this.init();
23
+ }
24
+ async init() {
25
+ try {
26
+ if (!fs_1.default.existsSync(this.keyPath)) {
27
+ console.error(`[InternalKeyManager] Missing keys directory: ${this.keyPath}`);
28
+ return;
29
+ }
30
+ const privPath = path_1.default.join(this.keyPath, "/private/private.pem");
31
+ if (fs_1.default.existsSync(privPath)) {
32
+ const privPem = fs_1.default.readFileSync(privPath, "utf8");
33
+ this.privateKey = await (0, jose_1.importPKCS8)(privPem, "RS256");
34
+ }
35
+ const pubPath = path_1.default.join(this.keyPath, "/public/public.pem");
36
+ if (fs_1.default.existsSync(pubPath)) {
37
+ const pubPem = fs_1.default.readFileSync(pubPath, "utf8");
38
+ this.publicKey = await (0, jose_1.importSPKI)(pubPem, "RS256");
39
+ const jwk = await (0, jose_1.exportJWK)(this.publicKey);
40
+ this.jwks = [{
41
+ ...jwk,
42
+ kid: `${this.serviceName}-internal`,
43
+ use: "sig",
44
+ alg: "RS256"
45
+ }];
46
+ }
47
+ console.log(`[InternalKeyManager] Loaded keys for: ${this.serviceName}`);
48
+ }
49
+ catch (error) {
50
+ console.error("[InternalKeyManager] Failed to load keys.", error);
51
+ if (process.env.NODE_ENV === "production")
52
+ process.exit(1);
53
+ }
54
+ }
55
+ getPrivateKey() {
56
+ if (!this.privateKey)
57
+ throw new Error("Private key not loaded");
58
+ return this.privateKey;
59
+ }
60
+ getPublicJwks() {
61
+ return { keys: this.jwks };
62
+ }
63
+ getKid() {
64
+ return `${this.serviceName}-internal`;
65
+ }
66
+ }
67
+ exports.InternalKeyManager = InternalKeyManager;
@@ -0,0 +1,8 @@
1
+ export declare const SERVICE_REGISTRY: {
2
+ readonly auth: "auth-service";
3
+ readonly user: "user-service";
4
+ readonly billing: "billing-service";
5
+ readonly notifications: "notification-service";
6
+ };
7
+ export type ServiceName = typeof SERVICE_REGISTRY[keyof typeof SERVICE_REGISTRY];
8
+ export declare const extractServiceName: (url?: string) => ServiceName | null;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractServiceName = exports.SERVICE_REGISTRY = void 0;
4
+ exports.SERVICE_REGISTRY = {
5
+ auth: "auth-service",
6
+ user: "user-service",
7
+ billing: "billing-service",
8
+ notifications: "notification-service"
9
+ };
10
+ const extractServiceName = (url) => {
11
+ if (!url)
12
+ return null;
13
+ try {
14
+ const u = new URL(url);
15
+ // If localhost, infer by port
16
+ switch (u.port) {
17
+ case "3001": return "auth-service";
18
+ case "3002": return "user-service";
19
+ case "3003": return "billing-service";
20
+ case "3004": return "notification-service";
21
+ default: break;
22
+ }
23
+ // Docker/K8s case: hostname is service name
24
+ const host = u.hostname.split(".")[0];
25
+ if (Object.values(exports.SERVICE_REGISTRY).includes(host)) {
26
+ return host;
27
+ }
28
+ return null;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ };
34
+ exports.extractServiceName = extractServiceName;
@@ -0,0 +1,9 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { InternalJwtService } from "./internal-jwt.service";
3
+ export declare class ServiceClient {
4
+ private readonly internalJwt;
5
+ readonly http: AxiosInstance;
6
+ constructor(internalJwt: InternalJwtService);
7
+ private setupRetry;
8
+ private setupInterceptors;
9
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ServiceClient = void 0;
40
+ const axios_1 = __importStar(require("axios"));
41
+ const axios_retry_1 = __importDefault(require("axios-retry"));
42
+ const registry_1 = require("./registry");
43
+ class ServiceClient {
44
+ constructor(internalJwt) {
45
+ this.internalJwt = internalJwt;
46
+ this.http = axios_1.default.create({
47
+ timeout: 8000,
48
+ validateStatus: () => true
49
+ });
50
+ this.setupRetry();
51
+ this.setupInterceptors();
52
+ }
53
+ setupRetry() {
54
+ (0, axios_retry_1.default)(this.http, {
55
+ retries: 3,
56
+ retryDelay: axios_retry_1.default.exponentialDelay,
57
+ retryCondition: (err) => {
58
+ if (axios_retry_1.default.isNetworkError(err))
59
+ return true;
60
+ return (err.response?.status ?? 0) >= 500;
61
+ }
62
+ });
63
+ }
64
+ setupInterceptors() {
65
+ this.http.interceptors.request.use(async (config) => {
66
+ if (!config.headers)
67
+ config.headers = new axios_1.AxiosHeaders();
68
+ const reqId = config.headers["x-request-id"] ||
69
+ `req_${Math.random().toString(36).slice(2)}`;
70
+ config.headers["x-request-id"] = reqId;
71
+ const fullUrl = config.url?.startsWith("http")
72
+ ? config.url
73
+ : config.baseURL;
74
+ if (!fullUrl)
75
+ throw new Error("Missing baseURL or absolute URL for internal service request");
76
+ const target = (0, registry_1.extractServiceName)(fullUrl);
77
+ if (!target)
78
+ throw new Error(`Cannot extract serviceName from ${fullUrl}`);
79
+ const token = await this.internalJwt.sign({ requestId: reqId }, target);
80
+ config.headers["x-internal-jwt"] = token;
81
+ return config;
82
+ });
83
+ this.http.interceptors.response.use((res) => {
84
+ if (res.status >= 200 && res.status < 300)
85
+ return res;
86
+ throw {
87
+ status: res.status,
88
+ message: res.data?.error?.message ?? "Service Error",
89
+ details: res.data
90
+ };
91
+ });
92
+ }
93
+ }
94
+ exports.ServiceClient = ServiceClient;
@@ -0,0 +1,2 @@
1
+ export * from "./jwt-verifier";
2
+ export * from "./service-client";
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./jwt-verifier"), exports);
18
+ __exportStar(require("./service-client"), exports);
@@ -0,0 +1,9 @@
1
+ import { InternalJwtPayload } from "../types";
2
+ export declare class JwtVerifier {
3
+ private remoteJWKS;
4
+ private getJWKS;
5
+ /**
6
+ * Verifies the Internal JWT sent by the Gateway.
7
+ */
8
+ verifyAccessToken(token: string): Promise<InternalJwtPayload>;
9
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JwtVerifier = void 0;
4
+ const jose_1 = require("jose");
5
+ const errors_1 = require("../errors");
6
+ class JwtVerifier {
7
+ constructor() {
8
+ this.remoteJWKS = null;
9
+ }
10
+ async getJWKS() {
11
+ if (!this.remoteJWKS) {
12
+ const base = process.env.API_GATEWAY_URL;
13
+ this.remoteJWKS = (0, jose_1.createRemoteJWKSet)(new URL(`${base}/.well-known/jwks.json`));
14
+ }
15
+ return this.remoteJWKS;
16
+ }
17
+ /**
18
+ * Verifies the Internal JWT sent by the Gateway.
19
+ */
20
+ async verifyAccessToken(token) {
21
+ try {
22
+ const JWKS = await this.getJWKS();
23
+ const { payload } = await (0, jose_1.jwtVerify)(token, JWKS, {
24
+ issuer: process.env.INTERNAL_JWT_ISSUER,
25
+ audience: process.env.INTERNAL_JWT_AUDIENCE,
26
+ });
27
+ // Cast to our internal payload which includes the jti
28
+ return payload;
29
+ }
30
+ catch (err) {
31
+ console.error("[JwtVerifier] Internal Token Validation Failed:", err);
32
+ throw new errors_1.UnauthorizedError("Invalid or expired internal token");
33
+ }
34
+ }
35
+ }
36
+ exports.JwtVerifier = JwtVerifier;
@@ -0,0 +1,7 @@
1
+ import { AxiosInstance } from "axios";
2
+ export declare class ServiceClient {
3
+ readonly http: AxiosInstance;
4
+ constructor();
5
+ private setupRetry;
6
+ private setupInterceptors;
7
+ }
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ServiceClient = void 0;
40
+ const axios_1 = __importStar(require("axios"));
41
+ const axios_retry_1 = __importDefault(require("axios-retry"));
42
+ class ServiceClient {
43
+ constructor() {
44
+ this.http = axios_1.default.create({
45
+ timeout: 8000,
46
+ validateStatus: () => true
47
+ });
48
+ this.setupRetry();
49
+ this.setupInterceptors();
50
+ }
51
+ setupRetry() {
52
+ (0, axios_retry_1.default)(this.http, {
53
+ retries: 3,
54
+ retryDelay: axios_retry_1.default.exponentialDelay,
55
+ retryCondition: (err) => {
56
+ if (axios_retry_1.default.isNetworkError(err))
57
+ return true;
58
+ return (err.response?.status ?? 0) >= 500;
59
+ }
60
+ });
61
+ }
62
+ setupInterceptors() {
63
+ this.http.interceptors.request.use(async (config) => {
64
+ if (!config.headers)
65
+ config.headers = new axios_1.AxiosHeaders();
66
+ // Ensure every request has a tracing ID.
67
+ // If the caller passed one down from the incoming Express request, use it.
68
+ // Otherwise, generate a new one.
69
+ const reqId = config.headers["x-request-id"] ||
70
+ `req_${Math.random().toString(36).slice(2)}`;
71
+ config.headers["x-request-id"] = reqId;
72
+ return config;
73
+ });
74
+ this.http.interceptors.response.use((res) => {
75
+ // Pass through successful responses cleanly
76
+ if (res.status >= 200 && res.status < 300)
77
+ return res;
78
+ // Standardize error throwing for downstream microservice failures
79
+ throw {
80
+ status: res.status,
81
+ message: res.data?.error?.message ?? "Downstream Service Error",
82
+ details: res.data
83
+ };
84
+ });
85
+ }
86
+ }
87
+ exports.ServiceClient = ServiceClient;
@@ -0,0 +1,3 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { GlobalPermission } from "../enums";
3
+ export declare const authorize: (permission: GlobalPermission) => (req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>> | undefined;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorize = void 0;
4
+ const security_1 = require("../security");
5
+ const authorize = (permission) => {
6
+ return (req, res, next) => {
7
+ // 1. Ensure the RequireAuthMiddleware has already run
8
+ if (!req.accessContext) {
9
+ return res.status(401).json({
10
+ success: false,
11
+ error: { message: "Unauthorized: No access context", code: "UNAUTHORIZED" }
12
+ });
13
+ }
14
+ // 2. Check if the Role in the accessContext has the required Permission
15
+ if (!(0, security_1.isAllowed)(req.accessContext, permission)) {
16
+ return res.status(403).json({
17
+ success: false,
18
+ error: { message: `Forbidden: Missing permission ${permission}`, code: "FORBIDDEN" }
19
+ });
20
+ }
21
+ next();
22
+ };
23
+ };
24
+ exports.authorize = authorize;
@@ -0,0 +1,4 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ export declare class GlobalErrorHandler {
3
+ static handle(err: unknown, req: Request, res: Response, _next: NextFunction): Response<any, Record<string, any>>;
4
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GlobalErrorHandler = void 0;
4
+ const zod_1 = require("zod");
5
+ const utils_1 = require("../utils");
6
+ class GlobalErrorHandler {
7
+ static handle(err, req, res, _next) {
8
+ // Standardized logging using req.id from your requestId middleware
9
+ console.error(`[req ${req.id}]`, err);
10
+ // 1. Zod Validation Errors
11
+ if (err instanceof zod_1.ZodError) {
12
+ return (0, utils_1.failure)(res, "Validation failed", 400, err.flatten());
13
+ }
14
+ // 2. Custom App Errors (instanceof checks for BadRequestError, etc.)
15
+ const custom = err;
16
+ if (custom.statusCode) {
17
+ return (0, utils_1.failure)(res, custom.message ?? "Error", custom.statusCode, custom.details);
18
+ }
19
+ // 3. Fallback: Internal Server Error
20
+ return (0, utils_1.failure)(res, "Internal Server Error", 500);
21
+ }
22
+ }
23
+ exports.GlobalErrorHandler = GlobalErrorHandler;
@@ -0,0 +1,5 @@
1
+ export * from "./error-handler";
2
+ export * from "./validate";
3
+ export * from "./request-id";
4
+ export * from "./require-auth";
5
+ export * from "./authorize";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./error-handler"), exports);
18
+ __exportStar(require("./validate"), exports);
19
+ __exportStar(require("./request-id"), exports);
20
+ __exportStar(require("./require-auth"), exports);
21
+ __exportStar(require("./authorize"), exports);
@@ -0,0 +1,2 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ export declare const requestId: (req: Request, _res: Response, next: NextFunction) => void;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestId = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const requestId = (req, _res, next) => {
6
+ req.id = (0, crypto_1.randomUUID)();
7
+ next();
8
+ };
9
+ exports.requestId = requestId;
@@ -0,0 +1,10 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { InternalJwtPayload } from "../types";
3
+ export interface IJwtVerifier {
4
+ verifyAccessToken(token: string): Promise<InternalJwtPayload>;
5
+ }
6
+ export declare class RequireAuthMiddleware {
7
+ private readonly verifier;
8
+ constructor(verifier: IJwtVerifier);
9
+ handle: (req: Request, _res: Response, next: NextFunction) => Promise<void>;
10
+ }