@noony-serverless/core 0.3.3 → 0.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/build/core/containerPool.d.ts +129 -26
- package/build/core/containerPool.js +213 -68
- package/build/core/handler.d.ts +2 -2
- package/build/core/handler.js +6 -12
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/logger.d.ts +89 -1
- package/build/core/logger.js +136 -5
- package/build/core/telemetry/config.d.ts +331 -0
- package/build/core/telemetry/config.js +153 -0
- package/build/core/telemetry/index.d.ts +22 -0
- package/build/core/telemetry/index.js +45 -0
- package/build/core/telemetry/provider.d.ts +203 -0
- package/build/core/telemetry/provider.js +3 -0
- package/build/core/telemetry/providers/console-provider.d.ts +54 -0
- package/build/core/telemetry/providers/console-provider.js +124 -0
- package/build/core/telemetry/providers/index.d.ts +10 -0
- package/build/core/telemetry/providers/index.js +19 -0
- package/build/core/telemetry/providers/noop-provider.d.ts +51 -0
- package/build/core/telemetry/providers/noop-provider.js +67 -0
- package/build/core/telemetry/providers/opentelemetry-provider.d.ts +102 -0
- package/build/core/telemetry/providers/opentelemetry-provider.js +342 -0
- package/build/middlewares/ProcessingMiddleware.d.ts +6 -3
- package/build/middlewares/ProcessingMiddleware.js +3 -0
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +23 -11
- package/build/middlewares/dependencyInjectionMiddleware.js +36 -12
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +1 -1
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/FastAuthGuard.js +3 -2
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +7 -9
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +11 -32
- package/build/middlewares/headerVariablesMiddleware.d.ts +8 -4
- package/build/middlewares/headerVariablesMiddleware.js +5 -1
- package/build/middlewares/httpAttributesMiddleware.d.ts +5 -3
- package/build/middlewares/httpAttributesMiddleware.js +3 -1
- package/build/middlewares/index.d.ts +1 -0
- package/build/middlewares/index.js +1 -0
- package/build/middlewares/openTelemetryMiddleware.d.ts +162 -0
- package/build/middlewares/openTelemetryMiddleware.js +359 -0
- package/build/middlewares/rateLimitingMiddleware.d.ts +8 -6
- package/build/middlewares/rateLimitingMiddleware.js +19 -6
- package/build/middlewares/securityAuditMiddleware.d.ts +6 -3
- package/build/middlewares/securityAuditMiddleware.js +3 -0
- package/build/middlewares/securityHeadersMiddleware.d.ts +5 -2
- package/build/middlewares/securityHeadersMiddleware.js +3 -0
- package/build/middlewares/validationMiddleware.d.ts +8 -4
- package/build/middlewares/validationMiddleware.js +5 -1
- package/build/utils/container.utils.js +4 -1
- package/build/utils/fastify-wrapper.d.ts +74 -0
- package/build/utils/fastify-wrapper.js +175 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.js +23 -1
- package/build/utils/otel.helper.d.ts +122 -0
- package/build/utils/otel.helper.js +258 -0
- package/build/utils/pubsub-trace.utils.d.ts +102 -0
- package/build/utils/pubsub-trace.utils.js +155 -0
- package/build/utils/wrapper-utils.d.ts +177 -0
- package/build/utils/wrapper-utils.js +236 -0
- package/package.json +61 -2
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.dependencyInjection = exports.DependencyInjectionMiddleware = void 0;
|
|
5
|
-
const
|
|
5
|
+
const containerPool_1 = require("../core/containerPool");
|
|
6
6
|
/**
|
|
7
7
|
* Middleware to inject dependencies into the request context using typedi.
|
|
8
8
|
* This allows handlers to access shared services or data via context.container.
|
|
9
9
|
*
|
|
10
|
-
* @
|
|
10
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
11
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
12
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
15
|
* Basic service injection:
|
|
@@ -151,14 +153,25 @@ const typedi_1 = require("typedi");
|
|
|
151
153
|
*/
|
|
152
154
|
class DependencyInjectionMiddleware {
|
|
153
155
|
services;
|
|
154
|
-
|
|
156
|
+
options;
|
|
157
|
+
constructor(services = [], options) {
|
|
155
158
|
this.services = services;
|
|
159
|
+
this.options = options;
|
|
156
160
|
}
|
|
157
161
|
async before(context) {
|
|
158
|
-
this.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
const scope = this.options?.scope || 'local';
|
|
163
|
+
if (scope === 'global') {
|
|
164
|
+
// Register services globally (process-lifetime)
|
|
165
|
+
// ⚠️ Use sparingly - only for truly shared services like DB connections
|
|
166
|
+
containerPool_1.containerPool.initializeGlobal(this.services);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Register services locally (request-lifetime)
|
|
170
|
+
// ✅ Recommended for most use cases - isolated per request
|
|
171
|
+
this.services.forEach((service) => {
|
|
172
|
+
context.container?.set(service.id, service.value);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
162
175
|
}
|
|
163
176
|
}
|
|
164
177
|
exports.DependencyInjectionMiddleware = DependencyInjectionMiddleware;
|
|
@@ -166,6 +179,8 @@ exports.DependencyInjectionMiddleware = DependencyInjectionMiddleware;
|
|
|
166
179
|
* Factory function that creates a dependency injection middleware.
|
|
167
180
|
* Creates a new container instance for each request to avoid shared state issues.
|
|
168
181
|
*
|
|
182
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
183
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
169
184
|
* @param services - Array of service definitions with id and value
|
|
170
185
|
* @returns BaseMiddleware object with dependency injection logic
|
|
171
186
|
*
|
|
@@ -254,12 +269,21 @@ exports.DependencyInjectionMiddleware = DependencyInjectionMiddleware;
|
|
|
254
269
|
* });
|
|
255
270
|
* ```
|
|
256
271
|
*/
|
|
257
|
-
const dependencyInjection = (services = []) => ({
|
|
272
|
+
const dependencyInjection = (services = [], options) => ({
|
|
258
273
|
before: async (context) => {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
274
|
+
const scope = options?.scope || 'local';
|
|
275
|
+
if (scope === 'global') {
|
|
276
|
+
// Register services globally (process-lifetime)
|
|
277
|
+
// ⚠️ Use sparingly - only for truly shared services like DB connections
|
|
278
|
+
containerPool_1.containerPool.initializeGlobal(services);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// Register services locally (request-lifetime)
|
|
282
|
+
// ✅ Recommended for most use cases - isolated per request
|
|
283
|
+
services.forEach((service) => {
|
|
284
|
+
context.container?.set(service.id, service.value);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
263
287
|
},
|
|
264
288
|
});
|
|
265
289
|
exports.dependencyInjection = dependencyInjection;
|
|
@@ -245,7 +245,7 @@ export declare class TokenVerificationAdapterFactory {
|
|
|
245
245
|
* @param expirationField - Optional field name for expiration (e.g., 'expiresAt', 'exp')
|
|
246
246
|
* @returns Configured adapter for API key tokens
|
|
247
247
|
*/
|
|
248
|
-
static forAPIKey<T extends
|
|
248
|
+
static forAPIKey<T extends object>(verificationPort: CustomTokenVerificationPort<T>, userIdField: keyof T, expirationField?: keyof T): CustomTokenVerificationPortAdapter<T>;
|
|
249
249
|
/**
|
|
250
250
|
* Create adapter for OAuth tokens with standard OAuth claims.
|
|
251
251
|
*
|
|
@@ -43,7 +43,7 @@ export interface AuthenticationResult {
|
|
|
43
43
|
success: boolean;
|
|
44
44
|
user?: UserContext;
|
|
45
45
|
token?: {
|
|
46
|
-
decoded:
|
|
46
|
+
decoded: unknown;
|
|
47
47
|
raw: string;
|
|
48
48
|
expiresAt: string;
|
|
49
49
|
issuer?: string;
|
|
@@ -63,7 +63,7 @@ export interface AuthGuardConfig {
|
|
|
63
63
|
allowedIssuers?: string[];
|
|
64
64
|
requireEmailVerification: boolean;
|
|
65
65
|
allowInactiveUsers: boolean;
|
|
66
|
-
customValidation?: (token:
|
|
66
|
+
customValidation?: (token: unknown, user: UserContext) => Promise<boolean>;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Token validation service interface
|
|
@@ -74,17 +74,17 @@ export interface TokenValidator {
|
|
|
74
74
|
*/
|
|
75
75
|
validateToken(token: string): Promise<{
|
|
76
76
|
valid: boolean;
|
|
77
|
-
decoded?:
|
|
77
|
+
decoded?: unknown;
|
|
78
78
|
error?: string;
|
|
79
79
|
}>;
|
|
80
80
|
/**
|
|
81
81
|
* Extract user ID from decoded token
|
|
82
82
|
*/
|
|
83
|
-
extractUserId(decoded:
|
|
83
|
+
extractUserId(decoded: unknown): string;
|
|
84
84
|
/**
|
|
85
85
|
* Check if token is expired
|
|
86
86
|
*/
|
|
87
|
-
isTokenExpired(decoded:
|
|
87
|
+
isTokenExpired(decoded: unknown): boolean;
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Fast Authentication Guard Implementation
|
|
@@ -215,14 +215,15 @@ let FastAuthGuard = class FastAuthGuard {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
// Build successful authentication result
|
|
218
|
+
const decoded = tokenValidation.decoded;
|
|
218
219
|
const authResult = {
|
|
219
220
|
success: true,
|
|
220
221
|
user: userContext,
|
|
221
222
|
token: {
|
|
222
223
|
decoded: tokenValidation.decoded,
|
|
223
224
|
raw: token,
|
|
224
|
-
expiresAt: new Date(
|
|
225
|
-
issuer:
|
|
225
|
+
expiresAt: new Date(decoded.exp * 1000).toISOString(),
|
|
226
|
+
issuer: decoded.iss,
|
|
226
227
|
},
|
|
227
228
|
cached: false,
|
|
228
229
|
resolutionTimeUs: Number(process.hrtime.bigint() - startTime) / 1000,
|
|
@@ -162,16 +162,14 @@ export declare class PermissionGuardFactory {
|
|
|
162
162
|
getStats(): {
|
|
163
163
|
totalGuards: number;
|
|
164
164
|
guardsByType: Record<string, number>;
|
|
165
|
-
individualGuardStats:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
individualGuardStats: ReturnType<BasePermissionGuard['getStats']>[];
|
|
166
|
+
aggregatedStats: {
|
|
167
|
+
totalChecks: number;
|
|
168
|
+
totalSuccesses: number;
|
|
169
|
+
totalFailures: number;
|
|
170
|
+
overallSuccessRate: number;
|
|
171
171
|
averageProcessingTimeUs: number;
|
|
172
|
-
|
|
173
|
-
}[];
|
|
174
|
-
aggregatedStats: any;
|
|
172
|
+
};
|
|
175
173
|
};
|
|
176
174
|
/**
|
|
177
175
|
* Clear guard cache
|
|
@@ -118,7 +118,7 @@ export declare class ExpressionPermissionResolver extends PermissionResolver<Per
|
|
|
118
118
|
/**
|
|
119
119
|
* Check if this resolver can handle the given requirement type
|
|
120
120
|
*/
|
|
121
|
-
canHandle(requirement:
|
|
121
|
+
canHandle(requirement: unknown): requirement is PermissionExpression;
|
|
122
122
|
/**
|
|
123
123
|
* Normalize expression for consistent cache keys
|
|
124
124
|
*
|
|
@@ -412,7 +412,7 @@ class ExpressionPermissionResolver extends PermissionResolver_1.PermissionResolv
|
|
|
412
412
|
* Check if this resolver can handle the given requirement type
|
|
413
413
|
*/
|
|
414
414
|
canHandle(requirement) {
|
|
415
|
-
return (requirement &&
|
|
415
|
+
return (!!requirement &&
|
|
416
416
|
typeof requirement === 'object' &&
|
|
417
417
|
PermissionResolver_1.PermissionUtils.isValidExpression(requirement));
|
|
418
418
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* different types of permission requirements. The generic type T represents
|
|
20
20
|
* the specific requirement format for each resolver.
|
|
21
21
|
*/
|
|
22
|
-
export declare abstract class PermissionResolver<T =
|
|
22
|
+
export declare abstract class PermissionResolver<T = unknown> {
|
|
23
23
|
/**
|
|
24
24
|
* Check if user permissions satisfy the requirement
|
|
25
25
|
*
|
|
@@ -96,6 +96,6 @@ export declare class PlainPermissionResolver extends PermissionResolver<string[]
|
|
|
96
96
|
* @param requirement - The requirement to check
|
|
97
97
|
* @returns true if this resolver can handle the requirement
|
|
98
98
|
*/
|
|
99
|
-
canHandle(requirement:
|
|
99
|
+
canHandle(requirement: unknown): requirement is string[];
|
|
100
100
|
}
|
|
101
101
|
//# sourceMappingURL=PlainPermissionResolver.d.ts.map
|
|
@@ -141,6 +141,6 @@ export declare class WildcardPermissionResolver extends PermissionResolver<strin
|
|
|
141
141
|
/**
|
|
142
142
|
* Check if this resolver can handle the given requirement type
|
|
143
143
|
*/
|
|
144
|
-
canHandle(requirement:
|
|
144
|
+
canHandle(requirement: unknown): requirement is string[];
|
|
145
145
|
}
|
|
146
146
|
//# sourceMappingURL=WildcardPermissionResolver.d.ts.map
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
* @version 1.0.0
|
|
24
24
|
*/
|
|
25
25
|
import { CacheAdapter } from '../cache/CacheAdapter';
|
|
26
|
-
import { GuardConfiguration
|
|
26
|
+
import { GuardConfiguration } from '../config/GuardConfiguration';
|
|
27
|
+
import { PlainPermissionResolver } from '../resolvers/PlainPermissionResolver';
|
|
28
|
+
import { WildcardPermissionResolver } from '../resolvers/WildcardPermissionResolver';
|
|
29
|
+
import { ExpressionPermissionResolver } from '../resolvers/ExpressionPermissionResolver';
|
|
27
30
|
import { PermissionRegistry } from '../registry/PermissionRegistry';
|
|
28
31
|
import { PermissionResolverType, PermissionCheckResult, PermissionExpression } from '../resolvers/PermissionResolver';
|
|
29
32
|
/**
|
|
@@ -38,7 +41,7 @@ export interface UserContext {
|
|
|
38
41
|
userId: string;
|
|
39
42
|
permissions: Set<string>;
|
|
40
43
|
roles: string[];
|
|
41
|
-
metadata: Record<string,
|
|
44
|
+
metadata: Record<string, unknown>;
|
|
42
45
|
expandedPermissions?: Set<string>;
|
|
43
46
|
lastUpdated: string;
|
|
44
47
|
expiresAt?: string;
|
|
@@ -53,7 +56,7 @@ export interface UserPermissionSource {
|
|
|
53
56
|
getUserPermissions(userId: string): Promise<{
|
|
54
57
|
permissions: string[];
|
|
55
58
|
roles: string[];
|
|
56
|
-
metadata?: Record<string,
|
|
59
|
+
metadata?: Record<string, unknown>;
|
|
57
60
|
} | null>;
|
|
58
61
|
/**
|
|
59
62
|
* Get role-based permissions for expansion
|
|
@@ -118,7 +121,7 @@ export declare class FastUserContextService {
|
|
|
118
121
|
* @param options - Check options
|
|
119
122
|
* @returns Detailed permission check result
|
|
120
123
|
*/
|
|
121
|
-
checkPermission(userId: string, requirement:
|
|
124
|
+
checkPermission(userId: string, requirement: unknown, options?: PermissionCheckOptions): Promise<PermissionCheckResult>;
|
|
122
125
|
/**
|
|
123
126
|
* Batch check multiple permissions for a user
|
|
124
127
|
*
|
|
@@ -131,7 +134,7 @@ export declare class FastUserContextService {
|
|
|
131
134
|
* @returns Array of permission check results
|
|
132
135
|
*/
|
|
133
136
|
checkPermissions(userId: string, requirements: Array<{
|
|
134
|
-
requirement:
|
|
137
|
+
requirement: unknown;
|
|
135
138
|
resolverType?: PermissionResolverType;
|
|
136
139
|
}>, options?: PermissionCheckOptions): Promise<PermissionCheckResult[]>;
|
|
137
140
|
/**
|
|
@@ -166,33 +169,9 @@ export declare class FastUserContextService {
|
|
|
166
169
|
averageResolutionTimeUs: number;
|
|
167
170
|
totalResolutionTimeUs: number;
|
|
168
171
|
resolverStats: {
|
|
169
|
-
plain:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
totalResolutionTimeUs: number;
|
|
173
|
-
};
|
|
174
|
-
wildcard: {
|
|
175
|
-
strategy: PermissionResolutionStrategy;
|
|
176
|
-
checkCount: number;
|
|
177
|
-
averageResolutionTimeUs: number;
|
|
178
|
-
totalResolutionTimeUs: number;
|
|
179
|
-
cacheHitRate: number;
|
|
180
|
-
cacheHits: number;
|
|
181
|
-
cacheMisses: number;
|
|
182
|
-
};
|
|
183
|
-
expression: {
|
|
184
|
-
checkCount: number;
|
|
185
|
-
averageResolutionTimeUs: number;
|
|
186
|
-
totalResolutionTimeUs: number;
|
|
187
|
-
cacheHitRate: number;
|
|
188
|
-
cacheHits: number;
|
|
189
|
-
cacheMisses: number;
|
|
190
|
-
complexityDistribution: {
|
|
191
|
-
simple: number;
|
|
192
|
-
moderate: number;
|
|
193
|
-
complex: number;
|
|
194
|
-
};
|
|
195
|
-
};
|
|
172
|
+
plain: ReturnType<PlainPermissionResolver['getStats']>;
|
|
173
|
+
wildcard: ReturnType<WildcardPermissionResolver['getStats']>;
|
|
174
|
+
expression: ReturnType<ExpressionPermissionResolver['getStats']>;
|
|
196
175
|
};
|
|
197
176
|
};
|
|
198
177
|
/**
|
|
@@ -3,7 +3,9 @@ import { BaseMiddleware, Context } from '../core';
|
|
|
3
3
|
* Middleware class that validates the presence of required HTTP headers.
|
|
4
4
|
* Throws a ValidationError if any required header is missing or empty.
|
|
5
5
|
*
|
|
6
|
-
* @
|
|
6
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
7
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
8
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
7
9
|
*
|
|
8
10
|
* @example
|
|
9
11
|
* API key authentication via headers:
|
|
@@ -63,15 +65,17 @@ import { BaseMiddleware, Context } from '../core';
|
|
|
63
65
|
* });
|
|
64
66
|
* ```
|
|
65
67
|
*/
|
|
66
|
-
export declare class HeaderVariablesMiddleware implements BaseMiddleware {
|
|
68
|
+
export declare class HeaderVariablesMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
67
69
|
private requiredHeaders;
|
|
68
70
|
constructor(requiredHeaders: string[]);
|
|
69
|
-
before(context: Context): Promise<void>;
|
|
71
|
+
before(context: Context<TBody, TUser>): Promise<void>;
|
|
70
72
|
}
|
|
71
73
|
/**
|
|
72
74
|
* Factory function that creates a header validation middleware.
|
|
73
75
|
* Validates that all required headers are present in the request.
|
|
74
76
|
*
|
|
77
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
78
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
75
79
|
* @param requiredHeaders - Array of header names that must be present
|
|
76
80
|
* @returns BaseMiddleware object with header validation logic
|
|
77
81
|
*
|
|
@@ -122,5 +126,5 @@ export declare class HeaderVariablesMiddleware implements BaseMiddleware {
|
|
|
122
126
|
* });
|
|
123
127
|
* ```
|
|
124
128
|
*/
|
|
125
|
-
export declare const headerVariablesMiddleware: (requiredHeaders: string[]) => BaseMiddleware
|
|
129
|
+
export declare const headerVariablesMiddleware: <TBody = unknown, TUser = unknown>(requiredHeaders: string[]) => BaseMiddleware<TBody, TUser>;
|
|
126
130
|
//# sourceMappingURL=headerVariablesMiddleware.d.ts.map
|
|
@@ -15,7 +15,9 @@ const validateHeaders = (requiredHeaders, headers) => {
|
|
|
15
15
|
* Middleware class that validates the presence of required HTTP headers.
|
|
16
16
|
* Throws a ValidationError if any required header is missing or empty.
|
|
17
17
|
*
|
|
18
|
-
* @
|
|
18
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
19
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
20
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
19
21
|
*
|
|
20
22
|
* @example
|
|
21
23
|
* API key authentication via headers:
|
|
@@ -90,6 +92,8 @@ exports.HeaderVariablesMiddleware = HeaderVariablesMiddleware;
|
|
|
90
92
|
* Factory function that creates a header validation middleware.
|
|
91
93
|
* Validates that all required headers are present in the request.
|
|
92
94
|
*
|
|
95
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
96
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
93
97
|
* @param requiredHeaders - Array of header names that must be present
|
|
94
98
|
* @returns BaseMiddleware object with header validation logic
|
|
95
99
|
*
|
|
@@ -5,7 +5,9 @@ import { ZodSchema } from 'zod';
|
|
|
5
5
|
* Middleware class that extracts path parameters from the URL.
|
|
6
6
|
* Parses URL segments and extracts parameters based on colon-prefixed patterns.
|
|
7
7
|
*
|
|
8
|
-
* @
|
|
8
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
9
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
10
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
9
11
|
*
|
|
10
12
|
* @example
|
|
11
13
|
* Basic path parameter extraction:
|
|
@@ -56,8 +58,8 @@ import { ZodSchema } from 'zod';
|
|
|
56
58
|
* });
|
|
57
59
|
* ```
|
|
58
60
|
*/
|
|
59
|
-
export declare class PathParametersMiddleware implements BaseMiddleware {
|
|
60
|
-
before(context: Context): Promise<void>;
|
|
61
|
+
export declare class PathParametersMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
62
|
+
before(context: Context<TBody, TUser>): Promise<void>;
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
63
65
|
* Factory function that creates a path parameters extraction middleware.
|
|
@@ -7,7 +7,9 @@ const zod_1 = require("zod");
|
|
|
7
7
|
* Middleware class that extracts path parameters from the URL.
|
|
8
8
|
* Parses URL segments and extracts parameters based on colon-prefixed patterns.
|
|
9
9
|
*
|
|
10
|
-
* @
|
|
10
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
11
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
12
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
15
|
* Basic path parameter extraction:
|
|
@@ -5,6 +5,7 @@ export * from './dependencyInjectionMiddleware';
|
|
|
5
5
|
export * from './errorHandlerMiddleware';
|
|
6
6
|
export * from './headerVariablesMiddleware';
|
|
7
7
|
export * from './httpAttributesMiddleware';
|
|
8
|
+
export * from './openTelemetryMiddleware';
|
|
8
9
|
export * from './queryParametersMiddleware';
|
|
9
10
|
export * from './rateLimitingMiddleware';
|
|
10
11
|
export * from './responseWrapperMiddleware';
|
|
@@ -21,6 +21,7 @@ __exportStar(require("./dependencyInjectionMiddleware"), exports);
|
|
|
21
21
|
__exportStar(require("./errorHandlerMiddleware"), exports);
|
|
22
22
|
__exportStar(require("./headerVariablesMiddleware"), exports);
|
|
23
23
|
__exportStar(require("./httpAttributesMiddleware"), exports);
|
|
24
|
+
__exportStar(require("./openTelemetryMiddleware"), exports);
|
|
24
25
|
__exportStar(require("./queryParametersMiddleware"), exports);
|
|
25
26
|
__exportStar(require("./rateLimitingMiddleware"), exports);
|
|
26
27
|
__exportStar(require("./responseWrapperMiddleware"), exports);
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { BaseMiddleware, Context } from '../core';
|
|
2
|
+
import { TelemetryProvider, TelemetryConfig } from '../core/telemetry/provider';
|
|
3
|
+
/**
|
|
4
|
+
* OpenTelemetry Middleware Options
|
|
5
|
+
*/
|
|
6
|
+
export interface OpenTelemetryOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Telemetry provider (auto-detects if not provided)
|
|
9
|
+
* @default Auto-detected based on environment variables
|
|
10
|
+
*/
|
|
11
|
+
provider?: TelemetryProvider;
|
|
12
|
+
/**
|
|
13
|
+
* Enable telemetry
|
|
14
|
+
* @default true for production, false for NODE_ENV=test
|
|
15
|
+
*/
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Extract custom attributes from context
|
|
19
|
+
* @default Extracts http.method, http.url, request.id, http.user_agent
|
|
20
|
+
*/
|
|
21
|
+
extractAttributes?: (context: Context<unknown, unknown>) => Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Filter which requests to trace
|
|
24
|
+
* @default Traces all requests
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* shouldTrace: (context) => context.req.path !== '/health'
|
|
28
|
+
*/
|
|
29
|
+
shouldTrace?: (context: Context<unknown, unknown>) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Custom error handler for telemetry errors
|
|
32
|
+
* @default Logs error to console
|
|
33
|
+
*/
|
|
34
|
+
onError?: (error: Error, context: Context<unknown, unknown>) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Fail silently on telemetry errors (never throw)
|
|
37
|
+
* @default true (telemetry errors never break application)
|
|
38
|
+
*/
|
|
39
|
+
failSilently?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Enable trace context propagation for Google Cloud Pub/Sub messages
|
|
42
|
+
*
|
|
43
|
+
* When enabled:
|
|
44
|
+
* - Extracts W3C Trace Context from incoming Pub/Sub message attributes
|
|
45
|
+
* - Links new spans to parent trace from publisher
|
|
46
|
+
* - Allows distributed tracing across Pub/Sub producers and consumers
|
|
47
|
+
*
|
|
48
|
+
* Trace context is stored in message attributes as:
|
|
49
|
+
* - `traceparent`: W3C Trace Context version-traceid-spanid-flags
|
|
50
|
+
* - `tracestate`: Vendor-specific trace state (optional)
|
|
51
|
+
*
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
propagatePubSubTraces?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* OpenTelemetry Middleware
|
|
58
|
+
*
|
|
59
|
+
* Provides distributed tracing and metrics collection with:
|
|
60
|
+
* - Auto-detection of telemetry provider from environment
|
|
61
|
+
* - Graceful degradation when configuration is missing
|
|
62
|
+
* - Zero-configuration local development support
|
|
63
|
+
* - Type-safe generics to preserve middleware chain
|
|
64
|
+
*
|
|
65
|
+
* Provider Auto-Detection Priority:
|
|
66
|
+
* 1. Explicit provider via options.provider
|
|
67
|
+
* 2. New Relic (if NEW_RELIC_LICENSE_KEY set)
|
|
68
|
+
* 3. Datadog (if DD_API_KEY or DD_SERVICE set)
|
|
69
|
+
* 4. Standard OTEL (if OTEL_EXPORTER_OTLP_ENDPOINT set)
|
|
70
|
+
* 5. Console (if NODE_ENV=development and no OTEL endpoint)
|
|
71
|
+
* 6. Noop (if NODE_ENV=test or no configuration)
|
|
72
|
+
*
|
|
73
|
+
* @template TBody - Request body type
|
|
74
|
+
* @template TUser - Authenticated user type
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // Zero configuration (auto-detects provider)
|
|
78
|
+
* const handler = new Handler()
|
|
79
|
+
* .use(new OpenTelemetryMiddleware())
|
|
80
|
+
* .handle(async (context) => {
|
|
81
|
+
* // Your business logic
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // With custom filtering
|
|
86
|
+
* const handler = new Handler()
|
|
87
|
+
* .use(new OpenTelemetryMiddleware({
|
|
88
|
+
* shouldTrace: (context) => context.req.path !== '/health'
|
|
89
|
+
* }))
|
|
90
|
+
* .handle(async (context) => {
|
|
91
|
+
* // Your business logic
|
|
92
|
+
* });
|
|
93
|
+
*/
|
|
94
|
+
export declare class OpenTelemetryMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
95
|
+
private provider;
|
|
96
|
+
private enabled;
|
|
97
|
+
private failSilently;
|
|
98
|
+
private propagatePubSubTraces;
|
|
99
|
+
private extractAttributes;
|
|
100
|
+
private shouldTrace;
|
|
101
|
+
private customErrorHandler;
|
|
102
|
+
private initialized;
|
|
103
|
+
constructor(options?: OpenTelemetryOptions);
|
|
104
|
+
/**
|
|
105
|
+
* Auto-detect telemetry provider based on environment
|
|
106
|
+
*/
|
|
107
|
+
private autoDetectProvider;
|
|
108
|
+
/**
|
|
109
|
+
* Initialize provider with configuration
|
|
110
|
+
*
|
|
111
|
+
* This should be called once at application startup.
|
|
112
|
+
* If not called explicitly, it will be initialized on first request.
|
|
113
|
+
*
|
|
114
|
+
* @param config Telemetry configuration
|
|
115
|
+
*/
|
|
116
|
+
initialize(config: TelemetryConfig): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Before hook - Create span and store in context
|
|
119
|
+
*
|
|
120
|
+
* If propagatePubSubTraces is enabled and the request is a Pub/Sub message:
|
|
121
|
+
* 1. Extracts W3C Trace Context from message attributes
|
|
122
|
+
* 2. Creates a child span linked to the publisher's trace
|
|
123
|
+
* 3. Enables end-to-end distributed tracing across Pub/Sub
|
|
124
|
+
*/
|
|
125
|
+
before(context: Context<TBody, TUser>): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* After hook - End span with success status and add X-Trace-Id header
|
|
128
|
+
*/
|
|
129
|
+
after(context: Context<TBody, TUser>): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Error hook - Record exception and end span
|
|
132
|
+
*/
|
|
133
|
+
onError(error: Error, context: Context<TBody, TUser>): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Default attribute extractor
|
|
136
|
+
*/
|
|
137
|
+
private defaultExtractAttributes;
|
|
138
|
+
/**
|
|
139
|
+
* Default error handler
|
|
140
|
+
*/
|
|
141
|
+
private defaultOnError;
|
|
142
|
+
/**
|
|
143
|
+
* Get current provider (useful for testing)
|
|
144
|
+
*/
|
|
145
|
+
getProvider(): TelemetryProvider;
|
|
146
|
+
/**
|
|
147
|
+
* Shutdown telemetry provider
|
|
148
|
+
*
|
|
149
|
+
* Should be called during application shutdown to flush pending data.
|
|
150
|
+
*/
|
|
151
|
+
shutdown(): Promise<void>;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Factory function for OpenTelemetry middleware
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* const handler = new Handler()
|
|
158
|
+
* .use(openTelemetry({ shouldTrace: ctx => ctx.req.path !== '/health' }))
|
|
159
|
+
* .handle(async (context) => { });
|
|
160
|
+
*/
|
|
161
|
+
export declare const openTelemetry: <TBody = unknown, TUser = unknown>(options?: OpenTelemetryOptions) => OpenTelemetryMiddleware<TBody, TUser>;
|
|
162
|
+
//# sourceMappingURL=openTelemetryMiddleware.d.ts.map
|