@devilsdev/rag-pipeline-utils 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +244 -11
  2. package/contracts/contract-schema.json +189 -0
  3. package/dist/index.cjs +19 -0
  4. package/dist/index.mjs +15 -1
  5. package/package.json +3 -2
  6. package/src/cli/commands/wizard.js +627 -0
  7. package/src/cli/input-sanitization-middleware.js +356 -0
  8. package/src/cli/templates/development.template.json +64 -0
  9. package/src/cli/templates/minimal.template.json +33 -0
  10. package/src/cli/templates/production.template.json +104 -0
  11. package/src/cli/templates/testing.template.json +45 -0
  12. package/src/config/connection-pool-config.json +259 -0
  13. package/src/config/memory-optimization.js +414 -0
  14. package/src/config/redaction-patterns.json +150 -0
  15. package/src/config/sanitization-rules.json +323 -0
  16. package/src/core/plugin-registry.js +266 -20
  17. package/src/dag/core/error-context.js +391 -0
  18. package/src/dag/core/execution-scheduler.js +350 -0
  19. package/src/dag/core/topology-validation.js +415 -0
  20. package/src/dag/dag-engine.js +26 -424
  21. package/src/dev/README.md +126 -0
  22. package/src/dev/dev-server.js +356 -0
  23. package/src/dev/examples/hot-reload-usage.js +355 -0
  24. package/src/dev/hot-reload.js +807 -0
  25. package/src/enterprise/sso-integration.js +67 -25
  26. package/src/index.js +19 -0
  27. package/src/observability/event-logger.js +62 -2
  28. package/src/plugins/optimized-openai-embedder.js +169 -0
  29. package/src/security/jwt-config.js +431 -0
  30. package/src/security/jwt-validator.js +701 -0
  31. package/src/utils/api-client-pool-integration.js +436 -0
  32. package/src/utils/batch-processor.js +710 -0
  33. package/src/utils/connection-pool.js +605 -0
  34. package/src/utils/contract-validator.js +460 -0
  35. package/src/utils/error-formatter.js +603 -0
  36. package/src/utils/examples/error-formatter-usage.js +351 -0
  37. package/src/utils/input-sanitizer.js +967 -0
  38. package/src/utils/memory-monitor.js +800 -0
  39. package/src/utils/secure-logger-config.js +352 -0
  40. package/src/utils/secure-logger.js +576 -0
@@ -0,0 +1,436 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * API Client Connection Pool Integration
5
+ *
6
+ * Provides seamless integration of connection pooling with popular
7
+ * API clients (OpenAI, Anthropic, Pinecone, etc.) and HTTP libraries.
8
+ *
9
+ * @module utils/api-client-pool-integration
10
+ * @since 2.3.0
11
+ */
12
+
13
+ const { getGlobalPool } = require('./connection-pool');
14
+
15
+ /**
16
+ * Create OpenAI client with connection pooling
17
+ *
18
+ * @param {Object} OpenAI - OpenAI constructor
19
+ * @param {Object} config - OpenAI configuration
20
+ * @param {ConnectionPoolManager} pool - Connection pool (optional, uses global if not provided)
21
+ * @returns {Object} OpenAI client with pooling
22
+ *
23
+ * @example
24
+ * const { OpenAI } = require('openai');
25
+ * const { createPooledOpenAIClient } = require('./api-client-pool-integration');
26
+ *
27
+ * const client = createPooledOpenAIClient(OpenAI, {
28
+ * apiKey: process.env.OPENAI_API_KEY,
29
+ * });
30
+ */
31
+ function createPooledOpenAIClient(OpenAI, config = {}, pool = null) {
32
+ const connectionPool =
33
+ pool ||
34
+ getGlobalPool({
35
+ maxSockets: 30,
36
+ maxFreeSockets: 10,
37
+ timeout: 60000, // 60s for LLM calls
38
+ });
39
+
40
+ // Get HTTPS agent from pool
41
+ const httpsAgent = connectionPool.getHttpsAgent();
42
+
43
+ // Create OpenAI client with pooled agent
44
+ const client = new OpenAI({
45
+ ...config,
46
+ httpAgent: httpsAgent,
47
+ // Some OpenAI SDKs might use different property names
48
+ fetch: createPooledFetchWrapper(connectionPool),
49
+ });
50
+
51
+ // Wrap methods to track metrics
52
+ return wrapClientWithMetrics(client, connectionPool, 'openai');
53
+ }
54
+
55
+ /**
56
+ * Create Anthropic client with connection pooling
57
+ *
58
+ * @param {Object} Anthropic - Anthropic constructor
59
+ * @param {Object} config - Anthropic configuration
60
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
61
+ * @returns {Object} Anthropic client with pooling
62
+ */
63
+ function createPooledAnthropicClient(Anthropic, config = {}, pool = null) {
64
+ const connectionPool =
65
+ pool ||
66
+ getGlobalPool({
67
+ maxSockets: 30,
68
+ maxFreeSockets: 10,
69
+ timeout: 60000,
70
+ });
71
+
72
+ const httpsAgent = connectionPool.getHttpsAgent();
73
+
74
+ const client = new Anthropic({
75
+ ...config,
76
+ httpAgent: httpsAgent,
77
+ fetch: createPooledFetchWrapper(connectionPool),
78
+ });
79
+
80
+ return wrapClientWithMetrics(client, connectionPool, 'anthropic');
81
+ }
82
+
83
+ /**
84
+ * Create pooled fetch wrapper
85
+ *
86
+ * @param {ConnectionPoolManager} pool - Connection pool
87
+ * @returns {Function} Fetch function with pooling
88
+ */
89
+ function createPooledFetchWrapper(pool) {
90
+ return async function pooledFetch(url, options = {}) {
91
+ const agent = pool.getAgentForUrl(url);
92
+ const startTime = Date.now();
93
+
94
+ try {
95
+ // Check if native fetch is available
96
+ if (typeof fetch === 'undefined') {
97
+ // Fallback to https/http module
98
+ return makeRequestWithAgent(url, options, agent);
99
+ }
100
+
101
+ // Use native fetch with agent
102
+ const response = await fetch(url, {
103
+ ...options,
104
+ agent,
105
+ });
106
+
107
+ // Track successful request
108
+ const duration = Date.now() - startTime;
109
+ pool.trackRequest(duration);
110
+
111
+ return response;
112
+ } catch (error) {
113
+ // Track error
114
+ const errorType =
115
+ error.code === 'ETIMEDOUT' || error.code === 'ESOCKETTIMEDOUT'
116
+ ? 'timeout'
117
+ : 'error';
118
+ pool.trackError(error, errorType);
119
+
120
+ throw error;
121
+ }
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Make HTTP request with agent (fallback for environments without fetch)
127
+ * @private
128
+ */
129
+ async function makeRequestWithAgent(url, options, agent) {
130
+ const https = require('https');
131
+ const http = require('http');
132
+ const { URL } = require('url');
133
+
134
+ const parsedUrl = new URL(url);
135
+ const protocol = parsedUrl.protocol === 'https:' ? https : http;
136
+
137
+ return new Promise((resolve, reject) => {
138
+ const requestOptions = {
139
+ ...options,
140
+ hostname: parsedUrl.hostname,
141
+ port: parsedUrl.port,
142
+ path: parsedUrl.pathname + parsedUrl.search,
143
+ method: options.method || 'GET',
144
+ headers: options.headers || {},
145
+ agent,
146
+ };
147
+
148
+ const req = protocol.request(requestOptions, (res) => {
149
+ let data = '';
150
+
151
+ res.on('data', (chunk) => {
152
+ data += chunk;
153
+ });
154
+
155
+ res.on('end', () => {
156
+ resolve({
157
+ ok: res.statusCode >= 200 && res.statusCode < 300,
158
+ status: res.statusCode,
159
+ statusText: res.statusMessage,
160
+ headers: res.headers,
161
+ json: async () => JSON.parse(data),
162
+ text: async () => data,
163
+ });
164
+ });
165
+ });
166
+
167
+ req.on('error', reject);
168
+
169
+ if (options.body) {
170
+ req.write(
171
+ typeof options.body === 'string'
172
+ ? options.body
173
+ : JSON.stringify(options.body),
174
+ );
175
+ }
176
+
177
+ req.end();
178
+ });
179
+ }
180
+
181
+ /**
182
+ * Wrap client methods with metrics tracking
183
+ * @private
184
+ */
185
+ function wrapClientWithMetrics(client, pool, clientName) {
186
+ // Create proxy to intercept method calls
187
+ return new Proxy(client, {
188
+ get(target, prop) {
189
+ const original = target[prop];
190
+
191
+ // Only wrap async methods
192
+ if (typeof original === 'function') {
193
+ return async function (...args) {
194
+ const startTime = Date.now();
195
+
196
+ try {
197
+ const result = await original.apply(target, args);
198
+
199
+ // Track successful call
200
+ const duration = Date.now() - startTime;
201
+ pool.trackRequest(duration);
202
+
203
+ return result;
204
+ } catch (error) {
205
+ // Track error
206
+ pool.trackError(error, 'api_error');
207
+ throw error;
208
+ }
209
+ };
210
+ }
211
+
212
+ return original;
213
+ },
214
+ });
215
+ }
216
+
217
+ /**
218
+ * Create pooled HTTP client (generic)
219
+ *
220
+ * @param {Object} options - HTTP client options
221
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
222
+ * @returns {Object} HTTP client with pooling
223
+ */
224
+ function createPooledHttpClient(options = {}, pool = null) {
225
+ const connectionPool = pool || getGlobalPool();
226
+
227
+ return {
228
+ get: (url, config) => makePooledRequest('GET', url, config, connectionPool),
229
+ post: (url, data, config) =>
230
+ makePooledRequest('POST', url, { ...config, data }, connectionPool),
231
+ put: (url, data, config) =>
232
+ makePooledRequest('PUT', url, { ...config, data }, connectionPool),
233
+ patch: (url, data, config) =>
234
+ makePooledRequest('PATCH', url, { ...config, data }, connectionPool),
235
+ delete: (url, config) =>
236
+ makePooledRequest('DELETE', url, config, connectionPool),
237
+ request: (config) =>
238
+ makePooledRequest(
239
+ config.method || 'GET',
240
+ config.url,
241
+ config,
242
+ connectionPool,
243
+ ),
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Make pooled HTTP request
249
+ * @private
250
+ */
251
+ async function makePooledRequest(method, url, config = {}, pool) {
252
+ const agent = pool.getAgentForUrl(url);
253
+ const startTime = Date.now();
254
+
255
+ try {
256
+ const options = {
257
+ method,
258
+ headers: config.headers || {},
259
+ agent,
260
+ };
261
+
262
+ if (config.data) {
263
+ options.body =
264
+ typeof config.data === 'string'
265
+ ? config.data
266
+ : JSON.stringify(config.data);
267
+
268
+ if (!options.headers['Content-Type']) {
269
+ options.headers['Content-Type'] = 'application/json';
270
+ }
271
+ }
272
+
273
+ const response = await makeRequestWithAgent(url, options, agent);
274
+
275
+ // Track successful request
276
+ const duration = Date.now() - startTime;
277
+ pool.trackRequest(duration);
278
+
279
+ return response;
280
+ } catch (error) {
281
+ // Track error
282
+ const errorType =
283
+ error.code === 'ETIMEDOUT' || error.code === 'ESOCKETTIMEDOUT'
284
+ ? 'timeout'
285
+ : 'error';
286
+ pool.trackError(error, errorType);
287
+
288
+ throw error;
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Axios interceptor for connection pooling
294
+ *
295
+ * @param {Object} axios - Axios instance
296
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
297
+ * @returns {Object} Axios instance with pooling
298
+ *
299
+ * @example
300
+ * const axios = require('axios');
301
+ * const { addAxiosPoolingInterceptor } = require('./api-client-pool-integration');
302
+ *
303
+ * const pooledAxios = addAxiosPoolingInterceptor(axios);
304
+ */
305
+ function addAxiosPoolingInterceptor(axios, pool = null) {
306
+ const connectionPool = pool || getGlobalPool();
307
+
308
+ // Add default agents
309
+ axios.defaults.httpAgent = connectionPool.getHttpAgent();
310
+ axios.defaults.httpsAgent = connectionPool.getHttpsAgent();
311
+
312
+ // Add request interceptor to track timing
313
+ axios.interceptors.request.use(
314
+ (config) => {
315
+ config.metadata = { startTime: Date.now() };
316
+ return config;
317
+ },
318
+ (error) => {
319
+ return Promise.reject(error);
320
+ },
321
+ );
322
+
323
+ // Add response interceptor to track metrics
324
+ axios.interceptors.response.use(
325
+ (response) => {
326
+ const duration = Date.now() - response.config.metadata.startTime;
327
+ connectionPool.trackRequest(duration);
328
+ return response;
329
+ },
330
+ (error) => {
331
+ if (error.config && error.config.metadata) {
332
+ const duration = Date.now() - error.config.metadata.startTime;
333
+
334
+ const errorType =
335
+ error.code === 'ECONNABORTED' || error.message.includes('timeout')
336
+ ? 'timeout'
337
+ : 'error';
338
+
339
+ connectionPool.trackError(error, errorType);
340
+ }
341
+
342
+ return Promise.reject(error);
343
+ },
344
+ );
345
+
346
+ return axios;
347
+ }
348
+
349
+ /**
350
+ * node-fetch wrapper with connection pooling
351
+ *
352
+ * @param {Function} nodeFetch - node-fetch function
353
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
354
+ * @returns {Function} Pooled fetch function
355
+ *
356
+ * @example
357
+ * const fetch = require('node-fetch');
358
+ * const { createPooledNodeFetch } = require('./api-client-pool-integration');
359
+ *
360
+ * const pooledFetch = createPooledNodeFetch(fetch);
361
+ */
362
+ function createPooledNodeFetch(nodeFetch, pool = null) {
363
+ const connectionPool = pool || getGlobalPool();
364
+
365
+ return async function pooledNodeFetch(url, options = {}) {
366
+ const agent = connectionPool.getAgentForUrl(url);
367
+ const startTime = Date.now();
368
+
369
+ try {
370
+ const response = await nodeFetch(url, {
371
+ ...options,
372
+ agent,
373
+ });
374
+
375
+ // Track successful request
376
+ const duration = Date.now() - startTime;
377
+ connectionPool.trackRequest(duration);
378
+
379
+ return response;
380
+ } catch (error) {
381
+ // Track error
382
+ const errorType =
383
+ error.type === 'request-timeout' || error.code === 'ETIMEDOUT'
384
+ ? 'timeout'
385
+ : 'error';
386
+ connectionPool.trackError(error, errorType);
387
+
388
+ throw error;
389
+ }
390
+ };
391
+ }
392
+
393
+ /**
394
+ * Get connection pool metrics for monitoring
395
+ *
396
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
397
+ * @returns {Object} Pool metrics
398
+ */
399
+ function getPoolMetrics(pool = null) {
400
+ const connectionPool = pool || getGlobalPool();
401
+ return connectionPool.getMetrics();
402
+ }
403
+
404
+ /**
405
+ * Get connection pool status
406
+ *
407
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
408
+ * @returns {Object} Pool status
409
+ */
410
+ function getPoolStatus(pool = null) {
411
+ const connectionPool = pool || getGlobalPool();
412
+ return connectionPool.getStatus();
413
+ }
414
+
415
+ /**
416
+ * Get connection pool report
417
+ *
418
+ * @param {ConnectionPoolManager} pool - Connection pool (optional)
419
+ * @returns {string} Human-readable pool report
420
+ */
421
+ function getPoolReport(pool = null) {
422
+ const connectionPool = pool || getGlobalPool();
423
+ return connectionPool.getReport();
424
+ }
425
+
426
+ module.exports = {
427
+ createPooledOpenAIClient,
428
+ createPooledAnthropicClient,
429
+ createPooledHttpClient,
430
+ createPooledFetchWrapper,
431
+ createPooledNodeFetch,
432
+ addAxiosPoolingInterceptor,
433
+ getPoolMetrics,
434
+ getPoolStatus,
435
+ getPoolReport,
436
+ };