@discover-cloud/shared 1.2.9 → 1.4.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 +2 -2
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/permission-cache.service.d.ts +104 -16
- package/dist/authorization/permission-cache.service.js +177 -148
- package/dist/authorization/permission-checker.d.ts +30 -0
- package/dist/authorization/permission-checker.js +40 -0
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/request-context.storage.d.ts +21 -0
- package/dist/context/request-context.storage.js +37 -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/contracts/index.d.ts +1 -0
- package/dist/{security → contracts}/index.js +1 -1
- package/dist/contracts/visibility.d.ts +63 -0
- package/dist/contracts/visibility.js +10 -0
- package/dist/dtos/audit-service.types.d.ts +42 -0
- package/dist/dtos/audit-service.types.js +31 -0
- package/dist/dtos/auth-service.dto.d.ts +87 -26
- package/dist/dtos/auth-service.dto.js +4 -0
- package/dist/dtos/cloud-service.dto.d.ts +57 -27
- package/dist/dtos/cloud-service.dto.js +5 -0
- package/dist/dtos/index.d.ts +6 -5
- package/dist/dtos/index.js +1 -0
- package/dist/dtos/insights-service.dto.d.ts +184 -32
- package/dist/dtos/insights-service.dto.js +8 -0
- package/dist/dtos/response.dto.d.ts +12 -83
- package/dist/dtos/response.dto.js +2 -21
- package/dist/dtos/user-service.dto.d.ts +163 -13
- package/dist/enums/domain.enums.d.ts +272 -75
- package/dist/enums/domain.enums.js +329 -102
- package/dist/enums/index.d.ts +2 -2
- 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 +15 -21
- package/dist/errors/http-errors.d.ts +106 -18
- package/dist/errors/http-errors.js +136 -51
- package/dist/errors/index.d.ts +2 -2
- package/dist/http/index.d.ts +2 -1
- 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 +93 -40
- package/dist/http/service-client.js +104 -55
- package/dist/index.d.ts +11 -9
- package/dist/index.js +2 -0
- package/dist/jwt/index.d.ts +3 -2
- package/dist/jwt/index.js +2 -1
- package/dist/jwt/machine-jwt-verifier.d.ts +21 -0
- package/dist/jwt/machine-jwt-verifier.js +83 -0
- package/dist/jwt/machine-token-client.d.ts +36 -5
- package/dist/jwt/machine-token-client.js +61 -27
- package/dist/jwt/user-jwt-verifier.d.ts +31 -0
- package/dist/jwt/user-jwt-verifier.js +102 -0
- package/dist/messaging/audit.publisher.d.ts +14 -0
- package/dist/messaging/audit.publisher.js +49 -0
- package/dist/messaging/index.d.ts +2 -0
- package/dist/{dto → messaging}/index.js +2 -3
- package/dist/messaging/rabbitmq.client.d.ts +15 -0
- package/dist/messaging/rabbitmq.client.js +133 -0
- package/dist/middleware/error-handler.middleware.d.ts +8 -28
- package/dist/middleware/error-handler.middleware.js +63 -54
- package/dist/middleware/index.d.ts +10 -8
- package/dist/middleware/index.js +7 -5
- package/dist/middleware/request-context.middleware.d.ts +6 -0
- package/dist/middleware/request-context.middleware.js +48 -0
- package/dist/middleware/require-auth.middleware.d.ts +7 -76
- package/dist/middleware/require-auth.middleware.js +29 -117
- package/dist/middleware/require-machine.middleware.d.ts +13 -0
- package/dist/middleware/require-machine.middleware.js +128 -0
- package/dist/middleware/require-org-permission-from-body.middleware.d.ts +10 -0
- package/dist/middleware/require-org-permission-from-body.middleware.js +23 -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 +31 -31
- package/dist/middleware/validate.middleware.js +31 -33
- package/dist/types/audit.types.d.ts +39 -0
- package/dist/types/audit.types.js +30 -0
- package/dist/types/express.types.d.ts +92 -124
- package/dist/types/express.types.js +30 -49
- package/dist/types/index.d.ts +1 -1
- 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 +31 -0
- package/dist/utils/logger.util.js +91 -0
- package/dist/utils/pagination.util.d.ts +6 -0
- package/dist/utils/pagination.util.js +20 -0
- package/dist/utils/request-context.als.d.ts +10 -0
- package/dist/utils/request-context.als.js +5 -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 +75 -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/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/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
|
@@ -1,49 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for everything attached to Express's Request object
|
|
5
|
-
* and all internal JWT payload shapes.
|
|
6
|
-
*
|
|
7
|
-
* Import in each service's entrypoint to activate the augmentation:
|
|
8
|
-
* import "@discover-cloud/shared/types/express";
|
|
9
|
-
*
|
|
10
|
-
* ─── Permission flow ────────────────────────────────────────────────────
|
|
11
|
-
* JWT carries: accountId + accountRole (lean payload, no perms)
|
|
12
|
-
* Redis derives: GlobalPermission[] (role map on cache miss)
|
|
13
|
-
* AccessContext has: perms (resolved by auth middleware)
|
|
14
|
-
*
|
|
15
|
-
* perms never touch the JWT — they live in the Redis permission cache and
|
|
16
|
-
* are resolved into req.accessContext by RequireAuthMiddleware per request.
|
|
17
|
-
* ────────────────────────────────────────────────────────────────────────
|
|
2
|
+
* @file express.types.ts
|
|
3
|
+
* @description Express Request type augmentations and authentication context definitions.
|
|
18
4
|
*/
|
|
19
|
-
import { JWTPayload } from
|
|
20
|
-
import {
|
|
21
|
-
interface
|
|
22
|
-
/**
|
|
23
|
-
* JWT ID — required.
|
|
24
|
-
* Used for the Redis kill-switch (session revocation / account suspension).
|
|
25
|
-
* Overrides JWTPayload's optional jti with a required string.
|
|
26
|
-
*/
|
|
5
|
+
import { JWTPayload } from 'jose';
|
|
6
|
+
import { ResourceQueryScope } from '../contracts';
|
|
7
|
+
interface BaseTokenPayload extends JWTPayload {
|
|
27
8
|
jti: string;
|
|
28
|
-
/**
|
|
29
|
-
* Token type discriminator — guards against token confusion attacks.
|
|
30
|
-
* InternalJwtVerifier rejects any token where typ !== "internal",
|
|
31
|
-
* even if it passes signature verification.
|
|
32
|
-
*/
|
|
33
|
-
typ: "internal";
|
|
34
|
-
/**
|
|
35
|
-
* The entity that last minted or forwarded this token.
|
|
36
|
-
* "api-gateway" → direct user-initiated request
|
|
37
|
-
* "notification-service" → service-to-service call on behalf of a user
|
|
38
|
-
* Used for audit logging and conditional authorization.
|
|
39
|
-
*/
|
|
40
|
-
caller: string;
|
|
41
|
-
/**
|
|
42
|
-
* Propagated request ID for distributed tracing.
|
|
43
|
-
* Ties together logs across the entire service call chain.
|
|
44
|
-
* Set by the gateway from the incoming x-request-id header.
|
|
45
|
-
*/
|
|
46
|
-
requestId?: string;
|
|
47
9
|
iss: string;
|
|
48
10
|
aud: string | string[];
|
|
49
11
|
iat: number;
|
|
@@ -51,116 +13,122 @@ interface BaseInternalJwtPayload extends JWTPayload {
|
|
|
51
13
|
nbf: number;
|
|
52
14
|
}
|
|
53
15
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
16
|
+
* Short-lived user access token.
|
|
17
|
+
*
|
|
18
|
+
* Contains authentication identity only.
|
|
19
|
+
* Authorization is resolved dynamically using RBAC.
|
|
58
20
|
*/
|
|
59
|
-
export interface
|
|
60
|
-
|
|
21
|
+
export interface AccessTokenPayload extends BaseTokenPayload {
|
|
22
|
+
typ: 'access';
|
|
23
|
+
/** Account identifier. */
|
|
61
24
|
accountId: string;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
25
|
+
/** Active session identifier. */
|
|
26
|
+
sessionId: string;
|
|
27
|
+
/** Token/version invalidation marker. */
|
|
28
|
+
ver: number;
|
|
29
|
+
/** Whether the session was generated via impersonation. */
|
|
30
|
+
impersonated?: boolean;
|
|
65
31
|
}
|
|
66
32
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
33
|
+
* Long-lived refresh token payload.
|
|
34
|
+
*
|
|
35
|
+
* Refresh tokens are only used for rotation.
|
|
70
36
|
*/
|
|
71
|
-
export interface
|
|
72
|
-
|
|
37
|
+
export interface RefreshTokenPayload extends BaseTokenPayload {
|
|
38
|
+
typ: 'refresh';
|
|
39
|
+
accountId: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Service-to-service authentication token.
|
|
43
|
+
*/
|
|
44
|
+
export interface MachineTokenPayload extends BaseTokenPayload {
|
|
45
|
+
typ: 'machine';
|
|
73
46
|
serviceId: string;
|
|
47
|
+
scopes: string[];
|
|
48
|
+
requestId?: string;
|
|
74
49
|
}
|
|
75
|
-
/**
|
|
76
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Any verified JWT generated by auth-service.
|
|
52
|
+
*/
|
|
53
|
+
export type VerifiedTokenPayload = AccessTokenPayload | RefreshTokenPayload | MachineTokenPayload;
|
|
54
|
+
/**
|
|
55
|
+
* Minimal data needed to revoke a JWT.
|
|
56
|
+
*/
|
|
77
57
|
export interface TokenRevocationContext {
|
|
78
58
|
jti: string;
|
|
79
59
|
exp: number;
|
|
80
60
|
}
|
|
81
|
-
|
|
82
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Authenticated user request context.
|
|
63
|
+
*
|
|
64
|
+
* Created from access tokens only.
|
|
65
|
+
*/
|
|
66
|
+
export interface UserContext {
|
|
67
|
+
type: 'user';
|
|
83
68
|
accountId: string;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Resolved from Redis permission cache — NOT from the JWT.
|
|
87
|
-
* Always present by the time req.accessContext is populated.
|
|
88
|
-
* Invalidated on role change, suspension, and account deletion.
|
|
89
|
-
*/
|
|
90
|
-
perms: GlobalPermission[];
|
|
69
|
+
sessionId: string;
|
|
91
70
|
}
|
|
92
|
-
|
|
93
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Authenticated internal service context.
|
|
73
|
+
*/
|
|
74
|
+
export interface MachineContext {
|
|
75
|
+
type: 'machine';
|
|
94
76
|
serviceId: string;
|
|
77
|
+
scopes: string[];
|
|
78
|
+
}
|
|
79
|
+
export type AuthContext = UserContext | MachineContext;
|
|
80
|
+
export interface RequestMetadataContext {
|
|
81
|
+
requestId: string;
|
|
82
|
+
ipAddress: string | null;
|
|
83
|
+
userAgent: string | null;
|
|
95
84
|
}
|
|
96
|
-
export type AccessContext = HumanAccessContext | MachineAccessContext;
|
|
97
|
-
export declare function isHumanPayload(payload: InternalJwtPayload): payload is HumanInternalJwtPayload;
|
|
98
|
-
export declare function isMachinePayload(payload: InternalJwtPayload): payload is MachineInternalJwtPayload;
|
|
99
85
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* jose returns a generic JWTPayload because it cannot know
|
|
103
|
-
* our custom claims. After verification + this assertion,
|
|
104
|
-
* TypeScript safely treats it as MachineInternalJwtPayload.
|
|
86
|
+
* Passed into application services for immutable auditing.
|
|
105
87
|
*/
|
|
106
|
-
export
|
|
107
|
-
|
|
108
|
-
export declare function isMachineContext(ctx: AccessContext): ctx is MachineAccessContext;
|
|
109
|
-
export interface VerifiedAccessPayload {
|
|
110
|
-
accountId: string;
|
|
111
|
-
accountRole: AccountRole;
|
|
112
|
-
typ: "access";
|
|
113
|
-
iss: string;
|
|
114
|
-
aud: string | string[];
|
|
115
|
-
iat: number;
|
|
116
|
-
exp: number;
|
|
117
|
-
nbf: number;
|
|
118
|
-
jti: string;
|
|
88
|
+
export interface AuditContext extends Partial<RequestMetadataContext> {
|
|
89
|
+
actorId: string | null;
|
|
119
90
|
}
|
|
120
|
-
export
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
91
|
+
export declare function isAccessToken(payload: VerifiedTokenPayload): payload is AccessTokenPayload;
|
|
92
|
+
export declare function isRefreshToken(payload: VerifiedTokenPayload): payload is RefreshTokenPayload;
|
|
93
|
+
export declare function isMachineToken(payload: VerifiedTokenPayload): payload is MachineTokenPayload;
|
|
94
|
+
export declare function isUserContext(ctx: AuthContext): ctx is UserContext;
|
|
95
|
+
export declare function isMachineContext(ctx: AuthContext): ctx is MachineContext;
|
|
96
|
+
/**
|
|
97
|
+
* Runtime assertion for service tokens.
|
|
98
|
+
*/
|
|
99
|
+
export declare function assertMachineToken(payload: JWTPayload): asserts payload is MachineTokenPayload;
|
|
100
|
+
export interface ValidatedRequestData {
|
|
101
|
+
params?: Record<string, unknown>;
|
|
102
|
+
query?: Record<string, unknown>;
|
|
103
|
+
body?: Record<string, unknown>;
|
|
104
|
+
headers?: Record<string, unknown>;
|
|
129
105
|
}
|
|
130
|
-
declare module
|
|
106
|
+
declare module 'express-serve-static-core' {
|
|
131
107
|
interface Request {
|
|
132
108
|
/**
|
|
133
|
-
*
|
|
134
|
-
* Respects upstream x-request-id forwarded by the gateway / load balancer.
|
|
135
|
-
* Always present after requestId middleware runs.
|
|
109
|
+
* Request correlation ID.
|
|
136
110
|
*/
|
|
137
111
|
id: string;
|
|
138
112
|
/**
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
*
|
|
144
|
-
|
|
113
|
+
* Request metadata.
|
|
114
|
+
*/
|
|
115
|
+
requestContext: RequestMetadataContext;
|
|
116
|
+
/**
|
|
117
|
+
* Validated request data.
|
|
118
|
+
*/
|
|
119
|
+
validated?: ValidatedRequestData;
|
|
120
|
+
/**
|
|
121
|
+
* Raw verified JWT payload.
|
|
145
122
|
*/
|
|
146
|
-
|
|
123
|
+
authPayload?: VerifiedTokenPayload;
|
|
147
124
|
/**
|
|
148
|
-
*
|
|
149
|
-
* Set by RequireAuthMiddleware after InternalJwtVerifier.verifyInternal().
|
|
150
|
-
*
|
|
151
|
-
* Prefer req.accessContext in route handlers and controllers.
|
|
152
|
-
* Access internalAuth only when you need raw JWT claims (e.g. jti).
|
|
125
|
+
* Runtime authenticated identity.
|
|
153
126
|
*/
|
|
154
|
-
|
|
127
|
+
authContext?: AuthContext;
|
|
155
128
|
/**
|
|
156
|
-
*
|
|
157
|
-
* This is what route handlers, controllers, and domain services consume.
|
|
158
|
-
*
|
|
159
|
-
* if (isHumanContext(req.accessContext)) {
|
|
160
|
-
* const { accountId, accountRole, perms } = req.accessContext;
|
|
161
|
-
* }
|
|
129
|
+
* Resolved resource query scope for insights queries.
|
|
162
130
|
*/
|
|
163
|
-
|
|
131
|
+
visibilityScope?: ResourceQueryScope;
|
|
164
132
|
}
|
|
165
133
|
}
|
|
166
134
|
export {};
|
|
@@ -1,60 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Single source of truth for everything attached to Express's Request object
|
|
6
|
-
* and all internal JWT payload shapes.
|
|
7
|
-
*
|
|
8
|
-
* Import in each service's entrypoint to activate the augmentation:
|
|
9
|
-
* import "@discover-cloud/shared/types/express";
|
|
10
|
-
*
|
|
11
|
-
* ─── Permission flow ────────────────────────────────────────────────────
|
|
12
|
-
* JWT carries: accountId + accountRole (lean payload, no perms)
|
|
13
|
-
* Redis derives: GlobalPermission[] (role map on cache miss)
|
|
14
|
-
* AccessContext has: perms (resolved by auth middleware)
|
|
15
|
-
*
|
|
16
|
-
* perms never touch the JWT — they live in the Redis permission cache and
|
|
17
|
-
* are resolved into req.accessContext by RequireAuthMiddleware per request.
|
|
18
|
-
* ────────────────────────────────────────────────────────────────────────
|
|
3
|
+
* @file express.types.ts
|
|
4
|
+
* @description Express Request type augmentations and authentication context definitions.
|
|
19
5
|
*/
|
|
20
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
7
|
+
exports.isAccessToken = isAccessToken;
|
|
8
|
+
exports.isRefreshToken = isRefreshToken;
|
|
9
|
+
exports.isMachineToken = isMachineToken;
|
|
10
|
+
exports.isUserContext = isUserContext;
|
|
25
11
|
exports.isMachineContext = isMachineContext;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
==================================================================== */
|
|
33
|
-
function isHumanPayload(payload) {
|
|
34
|
-
return payload.isMachine === false;
|
|
12
|
+
exports.assertMachineToken = assertMachineToken;
|
|
13
|
+
/* ---------------------------------------------------------------------------
|
|
14
|
+
Type Guards
|
|
15
|
+
--------------------------------------------------------------------------- */
|
|
16
|
+
function isAccessToken(payload) {
|
|
17
|
+
return payload.typ === 'access';
|
|
35
18
|
}
|
|
36
|
-
function
|
|
37
|
-
return payload.
|
|
19
|
+
function isRefreshToken(payload) {
|
|
20
|
+
return payload.typ === 'refresh';
|
|
38
21
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
* jose returns a generic JWTPayload because it cannot know
|
|
43
|
-
* our custom claims. After verification + this assertion,
|
|
44
|
-
* TypeScript safely treats it as MachineInternalJwtPayload.
|
|
45
|
-
*/
|
|
46
|
-
function assertMachinePayload(payload) {
|
|
47
|
-
if (payload["typ"] !== "internal" ||
|
|
48
|
-
payload["isMachine"] !== true ||
|
|
49
|
-
typeof payload["serviceId"] !== "string" ||
|
|
50
|
-
typeof payload["jti"] !== "string" ||
|
|
51
|
-
typeof payload["caller"] !== "string") {
|
|
52
|
-
throw new Error("Invalid machine JWT payload");
|
|
53
|
-
}
|
|
22
|
+
function isMachineToken(payload) {
|
|
23
|
+
return payload.typ === 'machine';
|
|
54
24
|
}
|
|
55
|
-
function
|
|
56
|
-
return ctx.
|
|
25
|
+
function isUserContext(ctx) {
|
|
26
|
+
return ctx.type === 'user';
|
|
57
27
|
}
|
|
58
28
|
function isMachineContext(ctx) {
|
|
59
|
-
return ctx.
|
|
29
|
+
return ctx.type === 'machine';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Runtime assertion for service tokens.
|
|
33
|
+
*/
|
|
34
|
+
function assertMachineToken(payload) {
|
|
35
|
+
if (payload['typ'] !== 'machine' ||
|
|
36
|
+
typeof payload['serviceId'] !== 'string' ||
|
|
37
|
+
typeof payload['jti'] !== 'string' ||
|
|
38
|
+
!Array.isArray(payload['scopes'])) {
|
|
39
|
+
throw new Error('Invalid machine token payload');
|
|
40
|
+
}
|
|
60
41
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from './express.types';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file date.util.ts
|
|
4
|
+
* @description Date formatting and serialization helper utilities.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.toIsoOrNull = exports.toIso = void 0;
|
|
8
|
+
const toIso = (date) => date.toISOString();
|
|
9
|
+
exports.toIso = toIso;
|
|
10
|
+
const toIsoOrNull = (date) => date ? date.toISOString() : null;
|
|
11
|
+
exports.toIsoOrNull = toIsoOrNull;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file env.util.ts
|
|
4
|
+
* @description Helper functions to retrieve and validate environment variable settings safely.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getEnv = getEnv;
|
|
8
|
+
exports.getEnvOptional = getEnvOptional;
|
|
9
|
+
function getEnv(name) {
|
|
10
|
+
const value = process.env[name];
|
|
11
|
+
if (!value) {
|
|
12
|
+
throw new Error(`Missing required environment variable: ${name}. Ensure it is set in your .env file.`);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function getEnvOptional(name) {
|
|
17
|
+
const value = process.env[name];
|
|
18
|
+
return value === '' ? undefined : value;
|
|
19
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from './response.util';
|
|
2
|
+
export * from './logger.util';
|
|
3
|
+
export * from './date.util';
|
|
4
|
+
export * from './env.util';
|
|
5
|
+
export * from './pagination.util';
|
package/dist/utils/index.js
CHANGED
|
@@ -14,7 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./response.
|
|
18
|
-
__exportStar(require("./logger.
|
|
19
|
-
__exportStar(require("./date.
|
|
20
|
-
__exportStar(require("./env.
|
|
17
|
+
__exportStar(require("./response.util"), exports);
|
|
18
|
+
__exportStar(require("./logger.util"), exports);
|
|
19
|
+
__exportStar(require("./date.util"), exports);
|
|
20
|
+
__exportStar(require("./env.util"), exports);
|
|
21
|
+
__exportStar(require("./pagination.util"), exports);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file logger.utils.ts
|
|
3
|
+
* @description Minimal logger contract interface and common logger implementations (console, silent no-op).
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Standard logger interface that components can depend on to avoid coupling to
|
|
7
|
+
* specific third-party logging engines.
|
|
8
|
+
*/
|
|
9
|
+
export interface ILogger {
|
|
10
|
+
debug(obj: object, msg?: string): void;
|
|
11
|
+
debug(msg: string): void;
|
|
12
|
+
info(obj: object, msg?: string): void;
|
|
13
|
+
info(msg: string): void;
|
|
14
|
+
warn(obj: object, msg?: string): void;
|
|
15
|
+
warn(msg: string): void;
|
|
16
|
+
error(obj: object, msg?: string): void;
|
|
17
|
+
error(msg: string): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Silent no-op implementation discarded all log payloads.
|
|
21
|
+
*/
|
|
22
|
+
export declare const noopLogger: ILogger;
|
|
23
|
+
/**
|
|
24
|
+
* Console logger implementing the ILogger interface mapping to native console output.
|
|
25
|
+
*/
|
|
26
|
+
export declare const consoleLogger: ILogger;
|
|
27
|
+
/**
|
|
28
|
+
* Creates an ILogger adapter for a given Pino logger instance.
|
|
29
|
+
* @param pinoLogger Any Pino logger instance.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createPinoAdapter(pinoLogger: any): ILogger;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file logger.utils.ts
|
|
4
|
+
* @description Minimal logger contract interface and common logger implementations (console, silent no-op).
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.consoleLogger = exports.noopLogger = void 0;
|
|
8
|
+
exports.createPinoAdapter = createPinoAdapter;
|
|
9
|
+
/**
|
|
10
|
+
* Silent no-op implementation discarded all log payloads.
|
|
11
|
+
*/
|
|
12
|
+
exports.noopLogger = {
|
|
13
|
+
debug: () => { },
|
|
14
|
+
info: () => { },
|
|
15
|
+
warn: () => { },
|
|
16
|
+
error: () => { },
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Console logger implementing the ILogger interface mapping to native console output.
|
|
20
|
+
*/
|
|
21
|
+
exports.consoleLogger = {
|
|
22
|
+
debug: (objOrMsg, msg) => {
|
|
23
|
+
if (typeof objOrMsg === 'string') {
|
|
24
|
+
console.debug(objOrMsg);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.debug(msg ?? '', objOrMsg);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
info: (objOrMsg, msg) => {
|
|
31
|
+
if (typeof objOrMsg === 'string') {
|
|
32
|
+
console.info(objOrMsg);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.info(msg ?? '', objOrMsg);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
warn: (objOrMsg, msg) => {
|
|
39
|
+
if (typeof objOrMsg === 'string') {
|
|
40
|
+
console.warn(objOrMsg);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.warn(msg ?? '', objOrMsg);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
error: (objOrMsg, msg) => {
|
|
47
|
+
if (typeof objOrMsg === 'string') {
|
|
48
|
+
console.error(objOrMsg);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error(msg ?? '', objOrMsg);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Creates an ILogger adapter for a given Pino logger instance.
|
|
57
|
+
* @param pinoLogger Any Pino logger instance.
|
|
58
|
+
*/
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
function createPinoAdapter(pinoLogger) {
|
|
61
|
+
return {
|
|
62
|
+
debug(objOrMsg, msg) {
|
|
63
|
+
if (typeof objOrMsg === 'string') {
|
|
64
|
+
pinoLogger.debug(objOrMsg);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
pinoLogger.debug(objOrMsg, msg);
|
|
68
|
+
},
|
|
69
|
+
info(objOrMsg, msg) {
|
|
70
|
+
if (typeof objOrMsg === 'string') {
|
|
71
|
+
pinoLogger.info(objOrMsg);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
pinoLogger.info(objOrMsg, msg);
|
|
75
|
+
},
|
|
76
|
+
warn(objOrMsg, msg) {
|
|
77
|
+
if (typeof objOrMsg === 'string') {
|
|
78
|
+
pinoLogger.warn(objOrMsg);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
pinoLogger.warn(objOrMsg, msg);
|
|
82
|
+
},
|
|
83
|
+
error(objOrMsg, msg) {
|
|
84
|
+
if (typeof objOrMsg === 'string') {
|
|
85
|
+
pinoLogger.error(objOrMsg);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
pinoLogger.error(objOrMsg, msg);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file pagination.utils.ts
|
|
3
|
+
* @description Helper functions to calculate pagination metadata from repository outputs.
|
|
4
|
+
*/
|
|
5
|
+
import { PaginationMeta } from '../dtos';
|
|
6
|
+
export declare function buildPaginationMeta(totalItems: number, limit: number, offset: number): PaginationMeta;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file pagination.utils.ts
|
|
4
|
+
* @description Helper functions to calculate pagination metadata from repository outputs.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.buildPaginationMeta = buildPaginationMeta;
|
|
8
|
+
function buildPaginationMeta(totalItems, limit, offset) {
|
|
9
|
+
const pageSize = limit > 0 ? limit : 1;
|
|
10
|
+
const totalPages = Math.ceil(totalItems / pageSize);
|
|
11
|
+
const currentPage = Math.floor(offset / pageSize) + 1;
|
|
12
|
+
return {
|
|
13
|
+
page: currentPage,
|
|
14
|
+
pageSize,
|
|
15
|
+
totalItems,
|
|
16
|
+
totalPages,
|
|
17
|
+
hasNext: currentPage < totalPages,
|
|
18
|
+
hasPrev: currentPage > 1,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
import { AuditActorType } from '../types/audit.types';
|
|
3
|
+
export interface RequestContextData {
|
|
4
|
+
requestId: string;
|
|
5
|
+
ipAddress: string | null;
|
|
6
|
+
userAgent: string | null;
|
|
7
|
+
actorId?: string | null;
|
|
8
|
+
actorType?: AuditActorType;
|
|
9
|
+
}
|
|
10
|
+
export declare const requestContextStorage: AsyncLocalStorage<RequestContextData>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file response.utils.ts
|
|
3
|
+
* @description Helper functions to construct and send standardized API success and error response envelopes.
|
|
4
|
+
*/
|
|
5
|
+
import { Response, Request } from 'express';
|
|
6
|
+
/**
|
|
7
|
+
* Sends a successful standardized API response containing the data payload.
|
|
8
|
+
*
|
|
9
|
+
* @param {Response} res - Express response object.
|
|
10
|
+
* @param {Request} req - Express request object.
|
|
11
|
+
* @param {T} data - The payload data.
|
|
12
|
+
* @param {number} [statusCode=200] - HTTP status code.
|
|
13
|
+
* @returns {void}
|
|
14
|
+
*/
|
|
15
|
+
export declare const success: <T>(res: Response, req: Request, data: T, statusCode?: number) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Sends a failed standardized API response containing error details.
|
|
18
|
+
*
|
|
19
|
+
* @param {Response} res - Express response object.
|
|
20
|
+
* @param {Request} req - Express request object.
|
|
21
|
+
* @param {string} message - Human-readable error message.
|
|
22
|
+
* @param {string} code - Error code mapping.
|
|
23
|
+
* @param {number} [statusCode=400] - HTTP status code.
|
|
24
|
+
* @param {unknown} [details] - Optional error metadata details.
|
|
25
|
+
* @returns {void}
|
|
26
|
+
*/
|
|
27
|
+
export declare const failure: (res: Response, req: Request, message: string, code: string, statusCode?: number, details?: unknown) => void;
|