@revenium/openai 1.0.12 → 1.0.14
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/.env.example +10 -15
- package/CHANGELOG.md +59 -0
- package/CODE_OF_CONDUCT.md +57 -0
- package/CONTRIBUTING.md +38 -0
- package/README.md +109 -515
- package/SECURITY.md +34 -0
- package/dist/cjs/core/client/index.js +14 -0
- package/dist/cjs/core/client/index.js.map +1 -0
- package/dist/cjs/core/client/manager.js +109 -0
- package/dist/cjs/core/client/manager.js.map +1 -0
- package/dist/cjs/core/config/azure-config.js +5 -17
- package/dist/cjs/core/config/azure-config.js.map +1 -1
- package/dist/cjs/core/config/index.js +2 -2
- package/dist/cjs/core/config/index.js.map +1 -1
- package/dist/cjs/core/config/loader.js +34 -14
- package/dist/cjs/core/config/loader.js.map +1 -1
- package/dist/cjs/core/config/manager.js +12 -5
- package/dist/cjs/core/config/manager.js.map +1 -1
- package/dist/cjs/core/config/validator.js +3 -45
- package/dist/cjs/core/config/validator.js.map +1 -1
- package/dist/cjs/core/middleware/index.js +17 -0
- package/dist/cjs/core/middleware/index.js.map +1 -0
- package/dist/cjs/core/middleware/interfaces.js +361 -0
- package/dist/cjs/core/middleware/interfaces.js.map +1 -0
- package/dist/cjs/core/middleware/revenium-client.js +142 -0
- package/dist/cjs/core/middleware/revenium-client.js.map +1 -0
- package/dist/cjs/core/providers/detector.js +45 -23
- package/dist/cjs/core/providers/detector.js.map +1 -1
- package/dist/cjs/core/providers/index.js +2 -1
- package/dist/cjs/core/providers/index.js.map +1 -1
- package/dist/cjs/core/tracking/api-client.js +14 -13
- package/dist/cjs/core/tracking/api-client.js.map +1 -1
- package/dist/cjs/core/tracking/payload-builder.js +30 -35
- package/dist/cjs/core/tracking/payload-builder.js.map +1 -1
- package/dist/cjs/core/tracking/usage-tracker.js +22 -18
- package/dist/cjs/core/tracking/usage-tracker.js.map +1 -1
- package/dist/cjs/index.js +26 -174
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/index.js +0 -8
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/openai-augmentation.js +0 -49
- package/dist/cjs/types/openai-augmentation.js.map +1 -1
- package/dist/cjs/utils/constants.js +17 -20
- package/dist/cjs/utils/constants.js.map +1 -1
- package/dist/cjs/utils/error-handler.js +18 -14
- package/dist/cjs/utils/error-handler.js.map +1 -1
- package/dist/cjs/utils/metadata-builder.js +27 -19
- package/dist/cjs/utils/metadata-builder.js.map +1 -1
- package/dist/cjs/utils/provider-detection.js +25 -28
- package/dist/cjs/utils/provider-detection.js.map +1 -1
- package/dist/cjs/utils/stop-reason-mapper.js +4 -0
- package/dist/cjs/utils/stop-reason-mapper.js.map +1 -1
- package/dist/cjs/utils/url-builder.js +3 -3
- package/dist/esm/core/client/index.js +6 -0
- package/dist/esm/core/client/index.js.map +1 -0
- package/dist/esm/core/client/manager.js +102 -0
- package/dist/esm/core/client/manager.js.map +1 -0
- package/dist/esm/core/config/azure-config.js +6 -18
- package/dist/esm/core/config/azure-config.js.map +1 -1
- package/dist/esm/core/config/index.js +5 -4
- package/dist/esm/core/config/index.js.map +1 -1
- package/dist/esm/core/config/loader.js +33 -13
- package/dist/esm/core/config/loader.js.map +1 -1
- package/dist/esm/core/config/manager.js +14 -7
- package/dist/esm/core/config/manager.js.map +1 -1
- package/dist/esm/core/config/validator.js +3 -44
- package/dist/esm/core/config/validator.js.map +1 -1
- package/dist/esm/core/middleware/index.js +8 -0
- package/dist/esm/core/middleware/index.js.map +1 -0
- package/dist/esm/core/middleware/interfaces.js +353 -0
- package/dist/esm/core/middleware/interfaces.js.map +1 -0
- package/dist/esm/core/middleware/revenium-client.js +105 -0
- package/dist/esm/core/middleware/revenium-client.js.map +1 -0
- package/dist/esm/core/providers/detector.js +43 -22
- package/dist/esm/core/providers/detector.js.map +1 -1
- package/dist/esm/core/providers/index.js +2 -2
- package/dist/esm/core/providers/index.js.map +1 -1
- package/dist/esm/core/tracking/api-client.js +13 -12
- package/dist/esm/core/tracking/api-client.js.map +1 -1
- package/dist/esm/core/tracking/payload-builder.js +31 -36
- package/dist/esm/core/tracking/payload-builder.js.map +1 -1
- package/dist/esm/core/tracking/usage-tracker.js +24 -20
- package/dist/esm/core/tracking/usage-tracker.js.map +1 -1
- package/dist/esm/index.js +9 -157
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/index.js +2 -10
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/openai-augmentation.js +0 -49
- package/dist/esm/types/openai-augmentation.js.map +1 -1
- package/dist/esm/utils/constants.js +16 -19
- package/dist/esm/utils/constants.js.map +1 -1
- package/dist/esm/utils/error-handler.js +19 -15
- package/dist/esm/utils/error-handler.js.map +1 -1
- package/dist/esm/utils/metadata-builder.js +27 -19
- package/dist/esm/utils/metadata-builder.js.map +1 -1
- package/dist/esm/utils/provider-detection.js +26 -29
- package/dist/esm/utils/provider-detection.js.map +1 -1
- package/dist/esm/utils/stop-reason-mapper.js +4 -0
- package/dist/esm/utils/stop-reason-mapper.js.map +1 -1
- package/dist/esm/utils/url-builder.js +3 -3
- package/dist/types/core/client/index.d.ts +6 -0
- package/dist/types/core/client/index.d.ts.map +1 -0
- package/dist/types/core/client/manager.d.ts +32 -0
- package/dist/types/core/client/manager.d.ts.map +1 -0
- package/dist/types/core/config/azure-config.d.ts +2 -2
- package/dist/types/core/config/azure-config.d.ts.map +1 -1
- package/dist/types/core/config/index.d.ts +4 -4
- package/dist/types/core/config/index.d.ts.map +1 -1
- package/dist/types/core/config/loader.d.ts +3 -1
- package/dist/types/core/config/loader.d.ts.map +1 -1
- package/dist/types/core/config/manager.d.ts +1 -1
- package/dist/types/core/config/manager.d.ts.map +1 -1
- package/dist/types/core/config/validator.d.ts +1 -12
- package/dist/types/core/config/validator.d.ts.map +1 -1
- package/dist/types/core/middleware/index.d.ts +8 -0
- package/dist/types/core/middleware/index.d.ts.map +1 -0
- package/dist/types/core/middleware/interfaces.d.ts +74 -0
- package/dist/types/core/middleware/interfaces.d.ts.map +1 -0
- package/dist/types/core/middleware/revenium-client.d.ts +58 -0
- package/dist/types/core/middleware/revenium-client.d.ts.map +1 -0
- package/dist/types/core/providers/detector.d.ts +9 -2
- package/dist/types/core/providers/detector.d.ts.map +1 -1
- package/dist/types/core/providers/index.d.ts +2 -2
- package/dist/types/core/providers/index.d.ts.map +1 -1
- package/dist/types/core/tracking/api-client.d.ts +1 -1
- package/dist/types/core/tracking/api-client.d.ts.map +1 -1
- package/dist/types/core/tracking/payload-builder.d.ts +3 -3
- package/dist/types/core/tracking/payload-builder.d.ts.map +1 -1
- package/dist/types/core/tracking/usage-tracker.d.ts +2 -2
- package/dist/types/core/tracking/usage-tracker.d.ts.map +1 -1
- package/dist/types/index.d.ts +11 -114
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types/function-parameters.d.ts +2 -23
- package/dist/types/types/function-parameters.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +17 -115
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/openai-augmentation.d.ts +4 -139
- package/dist/types/types/openai-augmentation.d.ts.map +1 -1
- package/dist/types/utils/constants.d.ts +7 -1
- package/dist/types/utils/constants.d.ts.map +1 -1
- package/dist/types/utils/error-handler.d.ts +2 -2
- package/dist/types/utils/error-handler.d.ts.map +1 -1
- package/dist/types/utils/metadata-builder.d.ts +4 -3
- package/dist/types/utils/metadata-builder.d.ts.map +1 -1
- package/dist/types/utils/provider-detection.d.ts +3 -3
- package/dist/types/utils/provider-detection.d.ts.map +1 -1
- package/dist/types/utils/stop-reason-mapper.d.ts.map +1 -1
- package/dist/types/utils/url-builder.d.ts +3 -3
- package/examples/README.md +270 -224
- package/examples/azure/basic.ts +62 -0
- package/examples/azure/responses-basic.ts +45 -0
- package/examples/azure/responses-stream.ts +61 -0
- package/examples/azure/stream.ts +56 -0
- package/examples/getting_started.ts +31 -43
- package/examples/openai/basic.ts +45 -0
- package/examples/openai/metadata.ts +67 -0
- package/examples/openai/responses-basic.ts +44 -0
- package/examples/openai/responses-embed.ts +34 -0
- package/examples/openai/responses-streaming.ts +63 -0
- package/examples/openai/streaming.ts +59 -0
- package/package.json +20 -13
- package/dist/cjs/core/wrapper/index.js +0 -15
- package/dist/cjs/core/wrapper/index.js.map +0 -1
- package/dist/cjs/core/wrapper/instance-patcher.js +0 -202
- package/dist/cjs/core/wrapper/instance-patcher.js.map +0 -1
- package/dist/cjs/core/wrapper/request-handler.js +0 -317
- package/dist/cjs/core/wrapper/request-handler.js.map +0 -1
- package/dist/cjs/core/wrapper/stream-wrapper.js +0 -82
- package/dist/cjs/core/wrapper/stream-wrapper.js.map +0 -1
- package/dist/cjs/utils/azure-model-resolver.js +0 -211
- package/dist/cjs/utils/azure-model-resolver.js.map +0 -1
- package/dist/cjs/utils/request-handler-factory.js +0 -185
- package/dist/cjs/utils/request-handler-factory.js.map +0 -1
- package/dist/esm/core/wrapper/index.js +0 -9
- package/dist/esm/core/wrapper/index.js.map +0 -1
- package/dist/esm/core/wrapper/instance-patcher.js +0 -199
- package/dist/esm/core/wrapper/instance-patcher.js.map +0 -1
- package/dist/esm/core/wrapper/request-handler.js +0 -310
- package/dist/esm/core/wrapper/request-handler.js.map +0 -1
- package/dist/esm/core/wrapper/stream-wrapper.js +0 -79
- package/dist/esm/core/wrapper/stream-wrapper.js.map +0 -1
- package/dist/esm/utils/azure-model-resolver.js +0 -204
- package/dist/esm/utils/azure-model-resolver.js.map +0 -1
- package/dist/esm/utils/request-handler-factory.js +0 -146
- package/dist/esm/utils/request-handler-factory.js.map +0 -1
- package/dist/types/core/wrapper/index.d.ts +0 -8
- package/dist/types/core/wrapper/index.d.ts.map +0 -1
- package/dist/types/core/wrapper/instance-patcher.d.ts +0 -33
- package/dist/types/core/wrapper/instance-patcher.d.ts.map +0 -1
- package/dist/types/core/wrapper/request-handler.d.ts +0 -29
- package/dist/types/core/wrapper/request-handler.d.ts.map +0 -1
- package/dist/types/core/wrapper/stream-wrapper.d.ts +0 -13
- package/dist/types/core/wrapper/stream-wrapper.d.ts.map +0 -1
- package/dist/types/utils/azure-model-resolver.d.ts +0 -41
- package/dist/types/utils/azure-model-resolver.d.ts.map +0 -1
- package/dist/types/utils/request-handler-factory.d.ts +0 -81
- package/dist/types/utils/request-handler-factory.d.ts.map +0 -1
- package/examples/azure-basic.ts +0 -206
- package/examples/azure-responses-basic.ts +0 -233
- package/examples/azure-responses-streaming.ts +0 -255
- package/examples/azure-streaming.ts +0 -209
- package/examples/openai-basic.ts +0 -147
- package/examples/openai-function-calling.ts +0 -259
- package/examples/openai-responses-basic.ts +0 -212
- package/examples/openai-responses-streaming.ts +0 -232
- package/examples/openai-streaming.ts +0 -172
- package/examples/openai-vision.ts +0 -289
- package/src/core/config/azure-config.ts +0 -72
- package/src/core/config/index.ts +0 -23
- package/src/core/config/loader.ts +0 -66
- package/src/core/config/manager.ts +0 -94
- package/src/core/config/validator.ts +0 -89
- package/src/core/providers/detector.ts +0 -159
- package/src/core/providers/index.ts +0 -16
- package/src/core/tracking/api-client.ts +0 -78
- package/src/core/tracking/index.ts +0 -21
- package/src/core/tracking/payload-builder.ts +0 -132
- package/src/core/tracking/usage-tracker.ts +0 -189
- package/src/core/wrapper/index.ts +0 -9
- package/src/core/wrapper/instance-patcher.ts +0 -288
- package/src/core/wrapper/request-handler.ts +0 -423
- package/src/core/wrapper/stream-wrapper.ts +0 -100
- package/src/index.ts +0 -336
- package/src/types/function-parameters.ts +0 -251
- package/src/types/index.ts +0 -313
- package/src/types/openai-augmentation.ts +0 -233
- package/src/types/responses-api.ts +0 -308
- package/src/utils/azure-model-resolver.ts +0 -220
- package/src/utils/constants.ts +0 -21
- package/src/utils/error-handler.ts +0 -251
- package/src/utils/metadata-builder.ts +0 -219
- package/src/utils/provider-detection.ts +0 -257
- package/src/utils/request-handler-factory.ts +0 -285
- package/src/utils/stop-reason-mapper.ts +0 -74
- package/src/utils/type-guards.ts +0 -202
- package/src/utils/url-builder.ts +0 -68
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error Handler Utilities
|
|
3
|
-
*
|
|
4
|
-
* Centralized error handling patterns to eliminate repetitive try/catch blocks
|
|
5
|
-
* and provide consistent error logging and recovery strategies.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Logger } from '../types/index.js';
|
|
9
|
-
import { ERROR_MESSAGE_PATTERNS_TYPE_CONFIG, MESSAGE_PATTERNS_TYPE_NETWORK } from './constants.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Error handling strategy configuration
|
|
13
|
-
*/
|
|
14
|
-
export interface ErrorHandlingStrategy {
|
|
15
|
-
/** Whether to log the error */
|
|
16
|
-
logError?: boolean;
|
|
17
|
-
/** Whether to re-throw the error */
|
|
18
|
-
rethrow?: boolean;
|
|
19
|
-
/** Custom error message prefix */
|
|
20
|
-
messagePrefix?: string;
|
|
21
|
-
/** Fallback value to return on error */
|
|
22
|
-
fallbackValue?: unknown;
|
|
23
|
-
/** Custom error transformation function */
|
|
24
|
-
transformError?: (error: unknown) => Error;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Default error handling strategy
|
|
29
|
-
*/
|
|
30
|
-
const DEFAULT_STRATEGY: Required<ErrorHandlingStrategy> = {
|
|
31
|
-
logError: true,
|
|
32
|
-
rethrow: true,
|
|
33
|
-
messagePrefix: '',
|
|
34
|
-
fallbackValue: undefined,
|
|
35
|
-
transformError: (error: unknown) => (error instanceof Error ? error : new Error(String(error))),
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Safe async operation wrapper with comprehensive error handling
|
|
40
|
-
*
|
|
41
|
-
* @param operation - The async operation to execute
|
|
42
|
-
* @param context - Context information for logging
|
|
43
|
-
* @param strategy - Error handling strategy
|
|
44
|
-
* @param logger - Logger instance
|
|
45
|
-
* @returns Promise with result or fallback value
|
|
46
|
-
*/
|
|
47
|
-
export async function safeAsyncOperation<T>(
|
|
48
|
-
operation: () => Promise<T>,
|
|
49
|
-
context: string,
|
|
50
|
-
strategy: ErrorHandlingStrategy = {},
|
|
51
|
-
logger?: Logger
|
|
52
|
-
): Promise<T | undefined> {
|
|
53
|
-
const config = { ...DEFAULT_STRATEGY, ...strategy };
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
return await operation();
|
|
57
|
-
} catch (error) {
|
|
58
|
-
const transformedError = config.transformError(error);
|
|
59
|
-
|
|
60
|
-
if (config.logError && logger) {
|
|
61
|
-
logger.error(`${config.messagePrefix}${context}`, {
|
|
62
|
-
error: transformedError.message,
|
|
63
|
-
stack: transformedError.stack,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (config.rethrow) throw transformedError;
|
|
68
|
-
return config.fallbackValue as T | undefined;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Safe sync operation wrapper
|
|
74
|
-
*
|
|
75
|
-
* @param operation - The sync operation to execute
|
|
76
|
-
* @param context - Context information for logging
|
|
77
|
-
* @param strategy - Error handling strategy
|
|
78
|
-
* @param logger - Logger instance
|
|
79
|
-
* @returns Result or fallback value
|
|
80
|
-
*/
|
|
81
|
-
export function safeSyncOperation<T>(
|
|
82
|
-
operation: () => T,
|
|
83
|
-
context: string,
|
|
84
|
-
strategy: ErrorHandlingStrategy = {},
|
|
85
|
-
logger?: Logger
|
|
86
|
-
): T | undefined {
|
|
87
|
-
const config = { ...DEFAULT_STRATEGY, ...strategy };
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
return operation();
|
|
91
|
-
} catch (error) {
|
|
92
|
-
const transformedError = config.transformError(error);
|
|
93
|
-
|
|
94
|
-
if (config.logError && logger) {
|
|
95
|
-
logger.error(`${config.messagePrefix}${context}`, {
|
|
96
|
-
error: transformedError.message,
|
|
97
|
-
stack: transformedError.stack,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (config.rethrow) throw transformedError;
|
|
102
|
-
return config.fallbackValue as T | undefined;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Validation wrapper that provides clear error messages
|
|
108
|
-
*
|
|
109
|
-
* @param value - Value to validate
|
|
110
|
-
* @param validator - Validation function
|
|
111
|
-
* @param errorMessage - Error message if validation fails
|
|
112
|
-
* @returns Validated value
|
|
113
|
-
*/
|
|
114
|
-
export function validateOrThrow<T>(
|
|
115
|
-
value: unknown,
|
|
116
|
-
validator: (value: unknown) => value is T,
|
|
117
|
-
errorMessage: string
|
|
118
|
-
): T {
|
|
119
|
-
if (!validator(value)) throw new Error(errorMessage);
|
|
120
|
-
return value;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Validation wrapper that returns undefined on failure
|
|
125
|
-
*
|
|
126
|
-
* @param value - Value to validate
|
|
127
|
-
* @param validator - Validation function
|
|
128
|
-
* @param logger - Optional logger for warnings
|
|
129
|
-
* @param context - Context for logging
|
|
130
|
-
* @returns Validated value or undefined
|
|
131
|
-
*/
|
|
132
|
-
export function validateOrUndefined<T>(
|
|
133
|
-
value: unknown,
|
|
134
|
-
validator: (value: unknown) => value is T,
|
|
135
|
-
logger?: Logger,
|
|
136
|
-
context?: string
|
|
137
|
-
): T | undefined {
|
|
138
|
-
if (!validator(value)) {
|
|
139
|
-
if (logger && context) {
|
|
140
|
-
logger.warn(`Validation failed: ${context}`, { value });
|
|
141
|
-
}
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
return value;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Create a retry wrapper for operations that might fail temporarily
|
|
149
|
-
*
|
|
150
|
-
* @param operation - Operation to retry
|
|
151
|
-
* @param maxRetries - Maximum number of retries
|
|
152
|
-
* @param delayMs - Delay between retries in milliseconds
|
|
153
|
-
* @param logger - Logger for retry attempts
|
|
154
|
-
* @returns Promise with operation result
|
|
155
|
-
*/
|
|
156
|
-
export async function withRetry<T>(
|
|
157
|
-
operation: () => Promise<T>,
|
|
158
|
-
maxRetries: number = 3,
|
|
159
|
-
delayMs: number = 1000,
|
|
160
|
-
logger?: Logger
|
|
161
|
-
): Promise<T> {
|
|
162
|
-
let lastError: Error;
|
|
163
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
164
|
-
try {
|
|
165
|
-
return await operation();
|
|
166
|
-
} catch (error) {
|
|
167
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
168
|
-
|
|
169
|
-
if (attempt === maxRetries) {
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (logger) {
|
|
174
|
-
logger.warn(`Operation failed, retrying (${attempt}/${maxRetries})`, {
|
|
175
|
-
error: lastError.message,
|
|
176
|
-
nextRetryIn: delayMs,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// eslint-disable-next-line no-throw-literal
|
|
184
|
-
throw lastError!;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Common error types for better error handling
|
|
189
|
-
*/
|
|
190
|
-
export class ValidationError extends Error {
|
|
191
|
-
constructor(
|
|
192
|
-
message: string,
|
|
193
|
-
public readonly context?: Record<string, unknown>
|
|
194
|
-
) {
|
|
195
|
-
super(message);
|
|
196
|
-
this.name = 'ValidationError';
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export class ConfigurationError extends Error {
|
|
201
|
-
constructor(
|
|
202
|
-
message: string,
|
|
203
|
-
public readonly context?: Record<string, unknown>
|
|
204
|
-
) {
|
|
205
|
-
super(message);
|
|
206
|
-
this.name = 'ConfigurationError';
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export class NetworkError extends Error {
|
|
211
|
-
constructor(
|
|
212
|
-
message: string,
|
|
213
|
-
public readonly context?: Record<string, unknown>
|
|
214
|
-
) {
|
|
215
|
-
super(message);
|
|
216
|
-
this.name = 'NetworkError';
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Error classification utility
|
|
222
|
-
*/
|
|
223
|
-
export function classifyError(error: unknown): {
|
|
224
|
-
type: 'validation' | 'configuration' | 'network' | 'unknown';
|
|
225
|
-
message: string;
|
|
226
|
-
isRetryable: boolean;
|
|
227
|
-
} {
|
|
228
|
-
if (error instanceof ValidationError) {
|
|
229
|
-
return { type: 'validation', message: error.message, isRetryable: false };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (error instanceof ConfigurationError) {
|
|
233
|
-
return { type: 'configuration', message: error.message, isRetryable: false };
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (error instanceof NetworkError) {
|
|
237
|
-
return { type: 'network', message: error.message, isRetryable: true };
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
241
|
-
|
|
242
|
-
// Classify based on message patterns
|
|
243
|
-
if (MESSAGE_PATTERNS_TYPE_NETWORK.some(pattern => message.includes(pattern))) {
|
|
244
|
-
return { type: 'network', message, isRetryable: true };
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (ERROR_MESSAGE_PATTERNS_TYPE_CONFIG.some(pattern => message.includes(pattern))) {
|
|
248
|
-
return { type: 'configuration', message, isRetryable: false };
|
|
249
|
-
}
|
|
250
|
-
return { type: 'unknown', message, isRetryable: false };
|
|
251
|
-
}
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Metadata Builder Utilities
|
|
3
|
-
*
|
|
4
|
-
* Centralized metadata handling to eliminate repetitive spreading
|
|
5
|
-
* and provide consistent metadata processing across the codebase.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { UsageMetadata, Subscriber } from '../types/index.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Metadata field configuration for conditional inclusion
|
|
12
|
-
*/
|
|
13
|
-
interface MetadataFieldConfig {
|
|
14
|
-
/** Source field name in UsageMetadata */
|
|
15
|
-
source: keyof UsageMetadata;
|
|
16
|
-
/** Target field name in payload (defaults to source) */
|
|
17
|
-
target?: string;
|
|
18
|
-
/** Whether this field is required */
|
|
19
|
-
required?: boolean;
|
|
20
|
-
/** Custom transformation function */
|
|
21
|
-
transform?: (value: unknown) => unknown;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Metadata mapping configuration
|
|
26
|
-
* Maps UsageMetadata fields to payload fields with optional transformations
|
|
27
|
-
* Subscriber object is passed through directly without transformation
|
|
28
|
-
*/
|
|
29
|
-
const METADATA_FIELD_MAP: MetadataFieldConfig[] = [
|
|
30
|
-
{ source: 'traceId' },
|
|
31
|
-
{ source: 'taskType' },
|
|
32
|
-
{ source: 'agent' },
|
|
33
|
-
{ source: 'organizationId' },
|
|
34
|
-
{ source: 'productId' },
|
|
35
|
-
{ source: 'subscriber' }, // Pass through nested subscriber object directly
|
|
36
|
-
{ source: 'subscriptionId' },
|
|
37
|
-
{
|
|
38
|
-
source: 'responseQualityScore',
|
|
39
|
-
transform: (value: unknown) => {
|
|
40
|
-
// Ensure quality score is between 0 and 1
|
|
41
|
-
if (typeof value === 'number') return Math.max(0, Math.min(1, value));
|
|
42
|
-
return value;
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Build metadata object for payload inclusion
|
|
49
|
-
*
|
|
50
|
-
* This function eliminates the repetitive spreading pattern and provides
|
|
51
|
-
* a clean, testable way to handle metadata transformation.
|
|
52
|
-
* Subscriber object is passed through directly without transformation.
|
|
53
|
-
*
|
|
54
|
-
* @param usageMetadata - Source metadata from request
|
|
55
|
-
* @returns Clean metadata object for payload
|
|
56
|
-
*/
|
|
57
|
-
export function buildMetadataFields(usageMetadata?: UsageMetadata): Record<string, unknown> {
|
|
58
|
-
if (!usageMetadata) return {};
|
|
59
|
-
const result: Record<string, unknown> = {};
|
|
60
|
-
|
|
61
|
-
// Process all metadata fields including nested subscriber object
|
|
62
|
-
for (const config of METADATA_FIELD_MAP) {
|
|
63
|
-
const value = usageMetadata[config.source];
|
|
64
|
-
|
|
65
|
-
// Skip undefined values (but allow null, empty strings, objects, etc.)
|
|
66
|
-
if (value === undefined) continue;
|
|
67
|
-
|
|
68
|
-
// Apply transformation if configured
|
|
69
|
-
const transformedValue = config.transform ? config.transform(value) : value;
|
|
70
|
-
|
|
71
|
-
// Use target field name or default to source
|
|
72
|
-
const targetField = config.target || config.source;
|
|
73
|
-
|
|
74
|
-
result[targetField] = transformedValue;
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Validate metadata completeness for specific use cases
|
|
81
|
-
*
|
|
82
|
-
* @param usageMetadata - Metadata to validate
|
|
83
|
-
* @param requiredFields - List of required field names
|
|
84
|
-
* @returns Validation result
|
|
85
|
-
*/
|
|
86
|
-
export function validateMetadata(
|
|
87
|
-
usageMetadata?: UsageMetadata,
|
|
88
|
-
requiredFields: (keyof UsageMetadata)[] = []
|
|
89
|
-
): {
|
|
90
|
-
isValid: boolean;
|
|
91
|
-
missingFields: string[];
|
|
92
|
-
warnings: string[];
|
|
93
|
-
} {
|
|
94
|
-
const missingFields: string[] = [];
|
|
95
|
-
const warnings: string[] = [];
|
|
96
|
-
|
|
97
|
-
if (!usageMetadata && requiredFields.length > 0) {
|
|
98
|
-
return {
|
|
99
|
-
isValid: false,
|
|
100
|
-
missingFields: requiredFields as string[],
|
|
101
|
-
warnings: ['No metadata provided'],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (usageMetadata) {
|
|
106
|
-
// Check required fields
|
|
107
|
-
for (const field of requiredFields) {
|
|
108
|
-
if (!usageMetadata[field]) missingFields.push(String(field));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Check for common issues
|
|
112
|
-
if (usageMetadata.responseQualityScore) {
|
|
113
|
-
const score = usageMetadata.responseQualityScore;
|
|
114
|
-
if (typeof score !== 'number' || score < 0 || score > 1) {
|
|
115
|
-
warnings.push('responseQualityScore should be a number between 0 and 1');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (usageMetadata.subscriber?.email && !usageMetadata.subscriber.email.includes('@')) {
|
|
120
|
-
warnings.push('subscriber.email does not appear to be a valid email address');
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
isValid: missingFields.length === 0,
|
|
125
|
-
missingFields,
|
|
126
|
-
warnings,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Merge multiple metadata sources with priority
|
|
132
|
-
*
|
|
133
|
-
* @param sources - Metadata sources in priority order (first wins)
|
|
134
|
-
* @returns Merged metadata object
|
|
135
|
-
*/
|
|
136
|
-
export function mergeMetadata(...sources: (UsageMetadata | undefined)[]): UsageMetadata {
|
|
137
|
-
const result: UsageMetadata = {};
|
|
138
|
-
|
|
139
|
-
// Process sources in reverse order so first source wins
|
|
140
|
-
for (const source of sources.reverse()) {
|
|
141
|
-
if (source) Object.assign(result, source);
|
|
142
|
-
}
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Extract metadata from request parameters safely
|
|
148
|
-
*
|
|
149
|
-
* @param params - Request parameters that might contain usageMetadata
|
|
150
|
-
* @returns Extracted metadata and cleaned parameters
|
|
151
|
-
*/
|
|
152
|
-
export function extractMetadata<T extends Record<string, unknown>>(
|
|
153
|
-
params: T & { usageMetadata?: UsageMetadata }
|
|
154
|
-
): {
|
|
155
|
-
metadata: UsageMetadata | undefined;
|
|
156
|
-
cleanParams: Omit<T, 'usageMetadata'>;
|
|
157
|
-
} {
|
|
158
|
-
const { usageMetadata, ...cleanParams } = params;
|
|
159
|
-
return {
|
|
160
|
-
metadata: usageMetadata,
|
|
161
|
-
cleanParams: cleanParams as Omit<T, 'usageMetadata'>,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Create a metadata context for consistent logging
|
|
167
|
-
*
|
|
168
|
-
* @param usageMetadata - Source metadata
|
|
169
|
-
* @returns Logging context object
|
|
170
|
-
*/
|
|
171
|
-
export function createLoggingContext(usageMetadata?: UsageMetadata): Record<string, unknown> {
|
|
172
|
-
if (!usageMetadata) return {};
|
|
173
|
-
return {
|
|
174
|
-
traceId: usageMetadata.traceId,
|
|
175
|
-
taskType: usageMetadata.taskType,
|
|
176
|
-
subscriberId: usageMetadata.subscriber?.id,
|
|
177
|
-
subscriberEmail: usageMetadata.subscriber?.email,
|
|
178
|
-
organizationId: usageMetadata.organizationId,
|
|
179
|
-
productId: usageMetadata.productId,
|
|
180
|
-
agent: usageMetadata.agent,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Sanitize metadata for logging (remove sensitive fields)
|
|
186
|
-
*
|
|
187
|
-
* @param usageMetadata - Source metadata
|
|
188
|
-
* @returns Sanitized metadata safe for logging
|
|
189
|
-
*/
|
|
190
|
-
export function sanitizeMetadataForLogging(usageMetadata?: UsageMetadata): Record<string, unknown> {
|
|
191
|
-
if (!usageMetadata) return {};
|
|
192
|
-
|
|
193
|
-
// Create a copy and handle nested subscriber object
|
|
194
|
-
const { subscriber, ...safeMetadata } = usageMetadata;
|
|
195
|
-
|
|
196
|
-
const result = { ...safeMetadata };
|
|
197
|
-
|
|
198
|
-
// Sanitize subscriber object if present
|
|
199
|
-
if (subscriber) {
|
|
200
|
-
const sanitizedSubscriber: any = {};
|
|
201
|
-
|
|
202
|
-
if (subscriber.id) {
|
|
203
|
-
sanitizedSubscriber.id = subscriber.id;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (subscriber.email) {
|
|
207
|
-
sanitizedSubscriber.email = subscriber.email.replace(/(.{2}).*(@.*)/, '$1***$2');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (subscriber.credential) {
|
|
211
|
-
sanitizedSubscriber.credential = {
|
|
212
|
-
name: subscriber.credential.name,
|
|
213
|
-
value: '[REDACTED]',
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
result.subscriber = sanitizedSubscriber;
|
|
217
|
-
}
|
|
218
|
-
return result;
|
|
219
|
-
}
|