@private.me/xbind 3.0.2 → 3.0.3

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 (221) hide show
  1. package/README.md +2366 -204
  2. package/README.md.backup +2121 -0
  3. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  4. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  5. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  6. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  7. package/dist-standalone/_deps/shared/errors.js +1 -244
  8. package/dist-standalone/_deps/shared/index.js +1 -72
  9. package/dist-standalone/_deps/shared/types.js +1 -86
  10. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  20. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  21. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  28. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  29. package/dist-standalone/_deps/xchange/errors.js +1 -1
  30. package/dist-standalone/_deps/xchange/index.js +1 -1
  31. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  32. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  33. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  34. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  40. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  41. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  42. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  43. package/dist-standalone/_deps/xregistry/index.js +1 -1
  44. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  45. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  46. package/dist-standalone/_deps/xregistry/types.js +1 -1
  47. package/dist-standalone/agent-call.d.ts +2 -2
  48. package/dist-standalone/agent-call.js +1 -659
  49. package/dist-standalone/agent-sdk.js +1 -328
  50. package/dist-standalone/agent.d.ts +2 -0
  51. package/dist-standalone/agent.js +1 -1800
  52. package/dist-standalone/approval.js +1 -193
  53. package/dist-standalone/async-iterators.d.ts +3 -3
  54. package/dist-standalone/async-iterators.js +1 -382
  55. package/dist-standalone/auth.js +1 -219
  56. package/dist-standalone/auto-accept.js +1 -229
  57. package/dist-standalone/backup-config.js +1 -201
  58. package/dist-standalone/backup.js +1 -326
  59. package/dist-standalone/batch-operations.js +1 -388
  60. package/dist-standalone/cancellation.js +1 -477
  61. package/dist-standalone/checkpoint.js +1 -186
  62. package/dist-standalone/circuit-breaker.js +1 -468
  63. package/dist-standalone/cjs/agent-call.js +1 -701
  64. package/dist-standalone/cjs/agent-sdk.js +1 -332
  65. package/dist-standalone/cjs/agent.js +1 -1837
  66. package/dist-standalone/cjs/approval.js +1 -199
  67. package/dist-standalone/cjs/async-iterators.js +1 -392
  68. package/dist-standalone/cjs/auth.js +1 -225
  69. package/dist-standalone/cjs/auto-accept.js +1 -233
  70. package/dist-standalone/cjs/backup-config.js +1 -207
  71. package/dist-standalone/cjs/backup.js +1 -330
  72. package/dist-standalone/cjs/batch-operations.js +1 -397
  73. package/dist-standalone/cjs/cancellation.js +1 -490
  74. package/dist-standalone/cjs/checkpoint.js +1 -193
  75. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  76. package/dist-standalone/cjs/cli/init.js +1 -492
  77. package/dist-standalone/cjs/config-validation.js +1 -522
  78. package/dist-standalone/cjs/connect.js +1 -312
  79. package/dist-standalone/cjs/connection-pool.js +1 -506
  80. package/dist-standalone/cjs/correlation-id.js +1 -339
  81. package/dist-standalone/cjs/crypto-utils.js +1 -176
  82. package/dist-standalone/cjs/debug-mode.js +1 -534
  83. package/dist-standalone/cjs/did-document.js +1 -101
  84. package/dist-standalone/cjs/did-privateme.js +1 -130
  85. package/dist-standalone/cjs/did-web.js +1 -201
  86. package/dist-standalone/cjs/discovery.js +1 -462
  87. package/dist-standalone/cjs/dual-mode.js +1 -251
  88. package/dist-standalone/cjs/email-templates.js +1 -313
  89. package/dist-standalone/cjs/email-transport.js +1 -239
  90. package/dist-standalone/cjs/envelope.js +1 -538
  91. package/dist-standalone/cjs/errors.js +1 -913
  92. package/dist-standalone/cjs/event-emitter.js +1 -461
  93. package/dist-standalone/cjs/gateway-state.js +1 -55
  94. package/dist-standalone/cjs/gateway-transport.js +1 -120
  95. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  96. package/dist-standalone/cjs/guardrails.js +1 -223
  97. package/dist-standalone/cjs/health-check.js +1 -336
  98. package/dist-standalone/cjs/http-compat.js +1 -272
  99. package/dist-standalone/cjs/http-status-map.js +1 -571
  100. package/dist-standalone/cjs/identity.js +1 -645
  101. package/dist-standalone/cjs/index.js +1 -406
  102. package/dist-standalone/cjs/invitation.js +1 -421
  103. package/dist-standalone/cjs/invite.js +1 -328
  104. package/dist-standalone/cjs/key-agreement.js +1 -335
  105. package/dist-standalone/cjs/lazy-init.js +1 -300
  106. package/dist-standalone/cjs/logger.js +1 -291
  107. package/dist-standalone/cjs/loopback-transport.js +1 -0
  108. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  109. package/dist-standalone/cjs/nonce-store.js +1 -80
  110. package/dist-standalone/cjs/pairing-manager.js +1 -223
  111. package/dist-standalone/cjs/plugin-system.js +1 -264
  112. package/dist-standalone/cjs/plugins/logging.js +1 -168
  113. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  114. package/dist-standalone/cjs/plugins/validation.js +1 -302
  115. package/dist-standalone/cjs/policy.js +1 -320
  116. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  117. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  118. package/dist-standalone/cjs/registry-middleware.js +1 -50
  119. package/dist-standalone/cjs/retry-strategies.js +1 -544
  120. package/dist-standalone/cjs/retry-transport.js +1 -102
  121. package/dist-standalone/cjs/runtime/browser.js +1 -533
  122. package/dist-standalone/cjs/runtime/edge.js +1 -526
  123. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  124. package/dist-standalone/cjs/security-policy.js +1 -245
  125. package/dist-standalone/cjs/serialization.js +1 -1040
  126. package/dist-standalone/cjs/split-channel.js +1 -225
  127. package/dist-standalone/cjs/subscription-proof.js +1 -230
  128. package/dist-standalone/cjs/succession.js +1 -148
  129. package/dist-standalone/cjs/timeouts.js +1 -412
  130. package/dist-standalone/cjs/trace-context.js +1 -424
  131. package/dist-standalone/cjs/trace-spans.js +1 -495
  132. package/dist-standalone/cjs/transport.js +1 -63
  133. package/dist-standalone/cjs/trust-registry.js +1 -991
  134. package/dist-standalone/cjs/types/error-response.js +1 -56
  135. package/dist-standalone/cjs/vault-auth.js +1 -178
  136. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  137. package/dist-standalone/cjs/verify.js +1 -25
  138. package/dist-standalone/cjs/version-info.js +1 -543
  139. package/dist-standalone/cjs/xfetch.js +1 -340
  140. package/dist-standalone/cli/init.js +1 -455
  141. package/dist-standalone/cli/setup.js +1 -514
  142. package/dist-standalone/cli/types.js +1 -27
  143. package/dist-standalone/cli/xbind.js +1 -148
  144. package/dist-standalone/config-validation.js +1 -513
  145. package/dist-standalone/connect.js +1 -274
  146. package/dist-standalone/connection-pool.js +1 -500
  147. package/dist-standalone/correlation-id.js +1 -326
  148. package/dist-standalone/crypto-utils.d.ts +2 -7
  149. package/dist-standalone/crypto-utils.js +1 -157
  150. package/dist-standalone/debug-mode.js +1 -510
  151. package/dist-standalone/did-document.js +1 -96
  152. package/dist-standalone/did-privateme.js +1 -121
  153. package/dist-standalone/did-web.js +1 -196
  154. package/dist-standalone/discovery.js +1 -458
  155. package/dist-standalone/dual-mode.js +1 -247
  156. package/dist-standalone/email-templates.js +1 -309
  157. package/dist-standalone/email-transport.d.ts +2 -2
  158. package/dist-standalone/email-transport.js +1 -232
  159. package/dist-standalone/envelope.js +1 -525
  160. package/dist-standalone/errors.d.ts +13 -3
  161. package/dist-standalone/errors.js +1 -896
  162. package/dist-standalone/event-emitter.js +1 -456
  163. package/dist-standalone/gateway-state.d.ts +1 -1
  164. package/dist-standalone/gateway-state.js +1 -51
  165. package/dist-standalone/gateway-transport.js +1 -116
  166. package/dist-standalone/graceful-degradation.js +1 -396
  167. package/dist-standalone/guardrails.js +1 -216
  168. package/dist-standalone/health-check.d.ts +5 -1
  169. package/dist-standalone/health-check.js +1 -332
  170. package/dist-standalone/http-compat.d.ts +1 -1
  171. package/dist-standalone/http-compat.js +1 -267
  172. package/dist-standalone/http-status-map.js +1 -561
  173. package/dist-standalone/identity.js +1 -619
  174. package/dist-standalone/index.d.ts +15 -4
  175. package/dist-standalone/index.js +1 -78
  176. package/dist-standalone/invitation.js +1 -415
  177. package/dist-standalone/invite.js +1 -324
  178. package/dist-standalone/key-agreement.js +1 -325
  179. package/dist-standalone/lazy-init.d.ts +11 -6
  180. package/dist-standalone/lazy-init.js +1 -295
  181. package/dist-standalone/logger.js +1 -285
  182. package/dist-standalone/loopback-transport.d.ts +87 -0
  183. package/dist-standalone/loopback-transport.js +1 -0
  184. package/dist-standalone/mdns-discovery.js +1 -195
  185. package/dist-standalone/nonce-store.js +1 -76
  186. package/dist-standalone/pairing-manager.js +1 -219
  187. package/dist-standalone/plugin-system.js +1 -257
  188. package/dist-standalone/plugins/logging.js +1 -163
  189. package/dist-standalone/plugins/metrics.d.ts +4 -4
  190. package/dist-standalone/plugins/metrics.js +1 -176
  191. package/dist-standalone/plugins/validation.js +1 -297
  192. package/dist-standalone/policy.js +1 -315
  193. package/dist-standalone/progress-callbacks.js +1 -576
  194. package/dist-standalone/redis-nonce-store.js +1 -72
  195. package/dist-standalone/registry-middleware.js +1 -47
  196. package/dist-standalone/retry-strategies.js +1 -534
  197. package/dist-standalone/retry-transport.js +1 -98
  198. package/dist-standalone/runtime/browser.js +1 -516
  199. package/dist-standalone/runtime/edge.js +1 -511
  200. package/dist-standalone/runtime/react-native.d.ts +1 -1
  201. package/dist-standalone/runtime/react-native.js +1 -383
  202. package/dist-standalone/security-policy.js +1 -239
  203. package/dist-standalone/serialization.js +1 -1031
  204. package/dist-standalone/split-channel.js +1 -219
  205. package/dist-standalone/subscription-proof.js +1 -224
  206. package/dist-standalone/succession.js +1 -142
  207. package/dist-standalone/timeouts.js +1 -398
  208. package/dist-standalone/trace-context.js +1 -414
  209. package/dist-standalone/trace-spans.js +1 -488
  210. package/dist-standalone/transport.js +1 -59
  211. package/dist-standalone/trust-registry.d.ts +3 -3
  212. package/dist-standalone/trust-registry.js +1 -950
  213. package/dist-standalone/types/error-response.js +1 -52
  214. package/dist-standalone/vault-auth.js +1 -174
  215. package/dist-standalone/vault-store-loader.d.ts +9 -0
  216. package/dist-standalone/vault-store-loader.js +1 -187
  217. package/dist-standalone/verify.js +1 -16
  218. package/dist-standalone/version-info.js +1 -530
  219. package/dist-standalone/xfetch.js +1 -335
  220. package/package.json +1 -1
  221. package/share1.dat +0 -0
@@ -1,506 +1 @@
1
- "use strict";
2
- /**
3
- * @module connection-pool
4
- * HTTP connection pooling for xBind registry/gateway requests
5
- *
6
- * Provides connection reuse, keep-alive support, and automatic cleanup
7
- * to enhance performance for applications making frequent requests.
8
- *
9
- * @example
10
- * ```typescript
11
- * const pool = new ConnectionPool({
12
- * maxConnections: 50,
13
- * keepAliveTimeout: 30000,
14
- * });
15
- *
16
- * const response = await pool.fetch('https://api.example.com/data');
17
- * const data = await response.json();
18
- * ```
19
- */
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.ConnectionPool = void 0;
22
- exports.getGlobalPool = getGlobalPool;
23
- exports.resetGlobalPool = resetGlobalPool;
24
- /**
25
- * Connection pool for HTTP requests
26
- *
27
- * Manages connection lifecycle, keep-alive, and automatic cleanup
28
- * to optimize performance for frequent requests to the same origins.
29
- */
30
- class ConnectionPool {
31
- options;
32
- connections = new Map();
33
- metrics;
34
- cleanupInterval = null;
35
- /**
36
- * Create a new connection pool
37
- *
38
- * @param options - Pool configuration options
39
- */
40
- constructor(options = {}) {
41
- this.options = {
42
- maxConnections: options.maxConnections ?? 10,
43
- minConnections: options.minConnections ?? 2,
44
- keepAliveTimeout: options.keepAliveTimeout ?? 30000,
45
- idleTimeout: options.idleTimeout ?? 60000,
46
- requestTimeout: options.requestTimeout ?? 30000,
47
- enableMetrics: options.enableMetrics ?? true,
48
- retryOnFailure: options.retryOnFailure ?? true,
49
- maxRetries: options.maxRetries ?? 3,
50
- };
51
- this.metrics = {
52
- totalRequests: 0,
53
- reuseCount: 0,
54
- failedRequests: 0,
55
- requestDurations: [],
56
- byOrigin: new Map(),
57
- };
58
- // Start automatic cleanup
59
- this.startCleanup();
60
- }
61
- /**
62
- * Make an HTTP request using the connection pool
63
- *
64
- * @param url - Target URL
65
- * @param init - Fetch options
66
- * @returns Response promise
67
- *
68
- * @example
69
- * ```typescript
70
- * const response = await pool.fetch('https://api.example.com/data', {
71
- * method: 'POST',
72
- * headers: { 'Content-Type': 'application/json' },
73
- * body: JSON.stringify({ key: 'value' }),
74
- * });
75
- * ```
76
- */
77
- async fetch(url, init) {
78
- const startTime = Date.now();
79
- const origin = this.getOrigin(url);
80
- try {
81
- // Get or create connection
82
- const connection = await this.acquireConnection(origin);
83
- // Update metrics
84
- if (this.options.enableMetrics) {
85
- this.metrics.totalRequests++;
86
- if (connection.requestCount > 0) {
87
- this.metrics.reuseCount++;
88
- }
89
- }
90
- // Make request with keep-alive
91
- const requestInit = {
92
- ...init,
93
- signal: init?.signal ?? connection.controller.signal,
94
- // @ts-ignore - keepalive is a valid fetch option
95
- keepalive: true,
96
- };
97
- const response = await fetch(url, requestInit);
98
- // Update connection state
99
- connection.requestCount++;
100
- connection.lastUsedAt = Date.now();
101
- connection.state = 'idle';
102
- // Record metrics
103
- if (this.options.enableMetrics) {
104
- const duration = Date.now() - startTime;
105
- this.recordMetrics(origin, duration);
106
- }
107
- return response;
108
- }
109
- catch (error) {
110
- // Record failure
111
- if (this.options.enableMetrics) {
112
- this.metrics.failedRequests++;
113
- }
114
- // Retry if enabled
115
- if (this.options.retryOnFailure && init?.signal?.aborted !== true) {
116
- return this.retryRequest(url, init, 1);
117
- }
118
- throw error;
119
- }
120
- }
121
- /**
122
- * Retry a failed request with exponential backoff
123
- */
124
- async retryRequest(url, init, attempt) {
125
- if (attempt > this.options.maxRetries) {
126
- throw new Error(`Request failed after ${this.options.maxRetries} retries: ${url}`);
127
- }
128
- // Exponential backoff: 100ms, 200ms, 400ms...
129
- const delay = 100 * Math.pow(2, attempt - 1);
130
- await new Promise(resolve => setTimeout(resolve, delay));
131
- const origin = this.getOrigin(url);
132
- try {
133
- // Get or create connection
134
- const connection = await this.acquireConnection(origin);
135
- // Make request with keep-alive
136
- const requestInit = {
137
- ...init,
138
- signal: init?.signal ?? connection.controller.signal,
139
- // @ts-ignore - keepalive is a valid fetch option
140
- keepalive: true,
141
- };
142
- const response = await fetch(url, requestInit);
143
- // Update connection state
144
- connection.requestCount++;
145
- connection.lastUsedAt = Date.now();
146
- connection.state = 'idle';
147
- return response;
148
- }
149
- catch (error) {
150
- if (attempt >= this.options.maxRetries) {
151
- throw new Error(`Request failed after ${this.options.maxRetries} retries: ${url}`);
152
- }
153
- return this.retryRequest(url, init, attempt + 1);
154
- }
155
- }
156
- /**
157
- * Acquire a connection from the pool or create a new one
158
- */
159
- async acquireConnection(origin) {
160
- let pool = this.connections.get(origin);
161
- if (!pool) {
162
- pool = [];
163
- this.connections.set(origin, pool);
164
- }
165
- // Find idle connection
166
- const idleConnection = pool.find(conn => conn.state === 'idle');
167
- if (idleConnection) {
168
- idleConnection.state = 'active';
169
- return idleConnection;
170
- }
171
- // Check if we can create a new connection
172
- if (pool.length < this.options.maxConnections) {
173
- const connection = this.createConnection(origin);
174
- pool.push(connection);
175
- return connection;
176
- }
177
- // Wait for an available connection
178
- return this.waitForConnection(origin);
179
- }
180
- /**
181
- * Wait for a connection to become available
182
- */
183
- async waitForConnection(origin) {
184
- const startTime = Date.now();
185
- const timeout = this.options.requestTimeout;
186
- while (Date.now() - startTime < timeout) {
187
- const pool = this.connections.get(origin);
188
- if (!pool) {
189
- throw new Error(`Connection pool for ${origin} disappeared`);
190
- }
191
- const idleConnection = pool.find(conn => conn.state === 'idle');
192
- if (idleConnection) {
193
- idleConnection.state = 'active';
194
- return idleConnection;
195
- }
196
- // Wait a bit before checking again
197
- await new Promise(resolve => setTimeout(resolve, 10));
198
- }
199
- throw new Error(`Timeout waiting for connection to ${origin} after ${timeout}ms`);
200
- }
201
- /**
202
- * Create a new connection
203
- */
204
- createConnection(origin) {
205
- const randomBytes = new Uint8Array(8);
206
- crypto.getRandomValues(randomBytes);
207
- const id = Array.from(randomBytes)
208
- .map(b => b.toString(16).padStart(2, '0'))
209
- .join('');
210
- return {
211
- id: `conn_${id}`,
212
- origin,
213
- createdAt: Date.now(),
214
- lastUsedAt: Date.now(),
215
- requestCount: 0,
216
- state: 'active',
217
- controller: new AbortController(),
218
- };
219
- }
220
- /**
221
- * Get origin from URL
222
- */
223
- getOrigin(url) {
224
- try {
225
- const parsed = new URL(url);
226
- return `${parsed.protocol}//${parsed.host}`;
227
- }
228
- catch (error) {
229
- throw new Error(`Invalid URL: ${url}`);
230
- }
231
- }
232
- /**
233
- * Record request metrics
234
- */
235
- recordMetrics(origin, duration) {
236
- this.metrics.requestDurations.push(duration);
237
- // Limit stored durations to last 1000 requests
238
- if (this.metrics.requestDurations.length > 1000) {
239
- this.metrics.requestDurations.shift();
240
- }
241
- // Record origin-specific metrics
242
- let originMetrics = this.metrics.byOrigin.get(origin);
243
- if (!originMetrics) {
244
- originMetrics = { requests: 0, durations: [] };
245
- this.metrics.byOrigin.set(origin, originMetrics);
246
- }
247
- originMetrics.requests++;
248
- originMetrics.durations.push(duration);
249
- // Limit origin durations
250
- if (originMetrics.durations.length > 100) {
251
- originMetrics.durations.shift();
252
- }
253
- }
254
- /**
255
- * Get connection pool metrics
256
- *
257
- * @returns Current metrics snapshot
258
- *
259
- * @example
260
- * ```typescript
261
- * const metrics = pool.getMetrics();
262
- * console.log(`Hit rate: ${(metrics.hitRate * 100).toFixed(1)}%`);
263
- * console.log(`Avg duration: ${metrics.avgRequestDuration}ms`);
264
- * ```
265
- */
266
- getMetrics() {
267
- let totalConnections = 0;
268
- let activeConnections = 0;
269
- let idleConnections = 0;
270
- const byOrigin = new Map();
271
- for (const [origin, pool] of this.connections.entries()) {
272
- totalConnections += pool.length;
273
- activeConnections += pool.filter(c => c.state === 'active').length;
274
- idleConnections += pool.filter(c => c.state === 'idle').length;
275
- const originMetrics = this.metrics.byOrigin.get(origin);
276
- if (originMetrics) {
277
- const avgDuration = originMetrics.durations.length > 0
278
- ? originMetrics.durations.reduce((a, b) => a + b, 0) /
279
- originMetrics.durations.length
280
- : 0;
281
- byOrigin.set(origin, {
282
- connections: pool.length,
283
- requests: originMetrics.requests,
284
- avgDuration: Math.round(avgDuration),
285
- });
286
- }
287
- }
288
- const avgRequestDuration = this.metrics.requestDurations.length > 0
289
- ? Math.round(this.metrics.requestDurations.reduce((a, b) => a + b, 0) /
290
- this.metrics.requestDurations.length)
291
- : 0;
292
- const hitRate = this.metrics.totalRequests > 0
293
- ? this.metrics.reuseCount / this.metrics.totalRequests
294
- : 0;
295
- return {
296
- totalConnections,
297
- activeConnections,
298
- idleConnections,
299
- totalRequests: this.metrics.totalRequests,
300
- reuseCount: this.metrics.reuseCount,
301
- failedRequests: this.metrics.failedRequests,
302
- avgRequestDuration,
303
- hitRate,
304
- byOrigin,
305
- };
306
- }
307
- /**
308
- * Reset metrics counters
309
- *
310
- * @example
311
- * ```typescript
312
- * pool.resetMetrics();
313
- * // Start fresh measurements
314
- * ```
315
- */
316
- resetMetrics() {
317
- this.metrics = {
318
- totalRequests: 0,
319
- reuseCount: 0,
320
- failedRequests: 0,
321
- requestDurations: [],
322
- byOrigin: new Map(),
323
- };
324
- }
325
- /**
326
- * Start automatic connection cleanup
327
- */
328
- startCleanup() {
329
- // Run cleanup every 10 seconds
330
- this.cleanupInterval = setInterval(() => {
331
- this.cleanup();
332
- }, 10000);
333
- }
334
- /**
335
- * Clean up idle and expired connections
336
- */
337
- cleanup() {
338
- const now = Date.now();
339
- for (const [origin, pool] of this.connections.entries()) {
340
- // Remove expired connections
341
- const activePool = pool.filter(conn => {
342
- const isExpired = now - conn.lastUsedAt > this.options.idleTimeout &&
343
- conn.state === 'idle';
344
- if (isExpired) {
345
- conn.controller.abort();
346
- conn.state = 'closed';
347
- return false;
348
- }
349
- return conn.state !== 'closed';
350
- });
351
- // Ensure minimum connections are maintained
352
- while (activePool.length < this.options.minConnections &&
353
- activePool.length < this.options.maxConnections) {
354
- const conn = this.createConnection(origin);
355
- conn.state = 'idle';
356
- activePool.push(conn);
357
- }
358
- if (activePool.length > 0) {
359
- this.connections.set(origin, activePool);
360
- }
361
- else {
362
- this.connections.delete(origin);
363
- }
364
- }
365
- }
366
- /**
367
- * Manually trigger connection cleanup
368
- *
369
- * @example
370
- * ```typescript
371
- * // Force cleanup of idle connections
372
- * pool.cleanupNow();
373
- * ```
374
- */
375
- cleanupNow() {
376
- this.cleanup();
377
- }
378
- /**
379
- * Close all connections and shutdown the pool
380
- *
381
- * @example
382
- * ```typescript
383
- * // Cleanup on application shutdown
384
- * await pool.close();
385
- * ```
386
- */
387
- async close() {
388
- // Stop cleanup interval
389
- if (this.cleanupInterval) {
390
- clearInterval(this.cleanupInterval);
391
- this.cleanupInterval = null;
392
- }
393
- // Close all connections
394
- for (const [_origin, pool] of this.connections.entries()) {
395
- for (const conn of pool) {
396
- conn.controller.abort();
397
- conn.state = 'closed';
398
- }
399
- }
400
- this.connections.clear();
401
- }
402
- /**
403
- * Get the number of connections for a specific origin
404
- *
405
- * @param origin - Target origin (e.g., "https://api.example.com")
406
- * @returns Number of connections
407
- *
408
- * @example
409
- * ```typescript
410
- * const count = pool.getConnectionCount('https://api.example.com');
411
- * console.log(`Active connections: ${count}`);
412
- * ```
413
- */
414
- getConnectionCount(origin) {
415
- const pool = this.connections.get(origin);
416
- return pool ? pool.length : 0;
417
- }
418
- /**
419
- * Get all origins with active connections
420
- *
421
- * @returns Array of origins
422
- *
423
- * @example
424
- * ```typescript
425
- * const origins = pool.getOrigins();
426
- * console.log(`Connected to ${origins.length} origins`);
427
- * ```
428
- */
429
- getOrigins() {
430
- return Array.from(this.connections.keys());
431
- }
432
- /**
433
- * Check if the pool is healthy
434
- *
435
- * @returns True if pool is operating normally
436
- *
437
- * @example
438
- * ```typescript
439
- * if (!pool.isHealthy()) {
440
- * console.warn('Connection pool degraded');
441
- * }
442
- * ```
443
- */
444
- isHealthy() {
445
- const metrics = this.getMetrics();
446
- // Check if failure rate is too high
447
- const failureRate = metrics.totalRequests > 0
448
- ? metrics.failedRequests / metrics.totalRequests
449
- : 0;
450
- if (failureRate > 0.1) {
451
- // More than 10% failure rate
452
- return false;
453
- }
454
- // Check if we have reasonable response times
455
- if (metrics.avgRequestDuration > 5000) {
456
- // Average over 5 seconds
457
- return false;
458
- }
459
- return true;
460
- }
461
- }
462
- exports.ConnectionPool = ConnectionPool;
463
- /**
464
- * Create a global connection pool instance
465
- *
466
- * Useful for sharing a single pool across your application.
467
- *
468
- * @param options - Pool configuration
469
- * @returns Singleton connection pool instance
470
- *
471
- * @example
472
- * ```typescript
473
- * import { getGlobalPool } from '@private.me/xbind/connection-pool';
474
- *
475
- * const pool = getGlobalPool({
476
- * maxConnections: 50,
477
- * keepAliveTimeout: 30000,
478
- * });
479
- *
480
- * const response = await pool.fetch('https://api.example.com/data');
481
- * ```
482
- */
483
- let globalPool = null;
484
- function getGlobalPool(options) {
485
- if (!globalPool) {
486
- globalPool = new ConnectionPool(options);
487
- }
488
- return globalPool;
489
- }
490
- /**
491
- * Reset the global connection pool
492
- *
493
- * Closes the current pool and allows a new one to be created.
494
- *
495
- * @example
496
- * ```typescript
497
- * await resetGlobalPool();
498
- * // Next getGlobalPool() call will create a fresh instance
499
- * ```
500
- */
501
- async function resetGlobalPool() {
502
- if (globalPool) {
503
- await globalPool.close();
504
- globalPool = null;
505
- }
506
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionPool=void 0,exports.getGlobalPool=getGlobalPool,exports.resetGlobalPool=resetGlobalPool;class ConnectionPool{options;connections=new Map;metrics;cleanupInterval=null;constructor(t={}){this.options={maxConnections:t.maxConnections??10,minConnections:t.minConnections??2,keepAliveTimeout:t.keepAliveTimeout??3e4,idleTimeout:t.idleTimeout??6e4,requestTimeout:t.requestTimeout??3e4,enableMetrics:t.enableMetrics??!0,retryOnFailure:t.retryOnFailure??!0,maxRetries:t.maxRetries??3},this.metrics={totalRequests:0,reuseCount:0,failedRequests:0,requestDurations:[],byOrigin:new Map},this.startCleanup()}async fetch(t,e){const s=Date.now(),n=this.getOrigin(t);try{const o=await this.acquireConnection(n);this.options.enableMetrics&&(this.metrics.totalRequests++,o.requestCount>0&&this.metrics.reuseCount++);const i={...e,signal:e?.signal??o.controller.signal,keepalive:!0},r=await fetch(t,i);if(o.requestCount++,o.lastUsedAt=Date.now(),o.state="idle",this.options.enableMetrics){const t=Date.now()-s;this.recordMetrics(n,t)}return r}catch(s){if(this.options.enableMetrics&&this.metrics.failedRequests++,this.options.retryOnFailure&&!0!==e?.signal?.aborted)return this.retryRequest(t,e,1);throw s}}async retryRequest(t,e,s){if(s>this.options.maxRetries)throw new Error(`Request failed after ${this.options.maxRetries} retries: ${t}`);const n=100*Math.pow(2,s-1);await new Promise(t=>setTimeout(t,n));const o=this.getOrigin(t);try{const s=await this.acquireConnection(o),n={...e,signal:e?.signal??s.controller.signal,keepalive:!0},i=await fetch(t,n);return s.requestCount++,s.lastUsedAt=Date.now(),s.state="idle",i}catch{if(s>=this.options.maxRetries)throw new Error(`Request failed after ${this.options.maxRetries} retries: ${t}`);return this.retryRequest(t,e,s+1)}}async acquireConnection(t){let e=this.connections.get(t);e||(e=[],this.connections.set(t,e));const s=e.find(t=>"idle"===t.state);if(s)return s.state="active",s;if(e.length<this.options.maxConnections){const s=this.createConnection(t);return e.push(s),s}return this.waitForConnection(t)}async waitForConnection(t){const e=Date.now(),s=this.options.requestTimeout;for(;Date.now()-e<s;){const e=this.connections.get(t);if(!e)throw new Error(`Connection pool for ${t} disappeared`);const s=e.find(t=>"idle"===t.state);if(s)return s.state="active",s;await new Promise(t=>setTimeout(t,10))}throw new Error(`Timeout waiting for connection to ${t} after ${s}ms`)}createConnection(t){const e=new Uint8Array(8);crypto.getRandomValues(e);return{id:`conn_${Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}`,origin:t,createdAt:Date.now(),lastUsedAt:Date.now(),requestCount:0,state:"active",controller:new AbortController}}getOrigin(t){try{const e=new URL(t);return`${e.protocol}//${e.host}`}catch{throw new Error(`Invalid URL: ${t}`)}}recordMetrics(t,e){this.metrics.requestDurations.push(e),this.metrics.requestDurations.length>1e3&&this.metrics.requestDurations.shift();let s=this.metrics.byOrigin.get(t);s||(s={requests:0,durations:[]},this.metrics.byOrigin.set(t,s)),s.requests++,s.durations.push(e),s.durations.length>100&&s.durations.shift()}getMetrics(){let t=0,e=0,s=0;const n=new Map;for(const[o,i]of this.connections.entries()){t+=i.length,e+=i.filter(t=>"active"===t.state).length,s+=i.filter(t=>"idle"===t.state).length;const r=this.metrics.byOrigin.get(o);if(r){const t=r.durations.length>0?r.durations.reduce((t,e)=>t+e,0)/r.durations.length:0;n.set(o,{connections:i.length,requests:r.requests,avgDuration:Math.round(t)})}}const o=this.metrics.requestDurations.length>0?Math.round(this.metrics.requestDurations.reduce((t,e)=>t+e,0)/this.metrics.requestDurations.length):0,i=this.metrics.totalRequests>0?this.metrics.reuseCount/this.metrics.totalRequests:0;return{totalConnections:t,activeConnections:e,idleConnections:s,totalRequests:this.metrics.totalRequests,reuseCount:this.metrics.reuseCount,failedRequests:this.metrics.failedRequests,avgRequestDuration:o,hitRate:i,byOrigin:n}}resetMetrics(){this.metrics={totalRequests:0,reuseCount:0,failedRequests:0,requestDurations:[],byOrigin:new Map}}startCleanup(){this.cleanupInterval=setInterval(()=>{this.cleanup()},1e4)}cleanup(){const t=Date.now();for(const[e,s]of this.connections.entries()){const n=s.filter(e=>t-e.lastUsedAt>this.options.idleTimeout&&"idle"===e.state?(e.controller.abort(),e.state="closed",!1):"closed"!==e.state);for(;n.length<this.options.minConnections&&n.length<this.options.maxConnections;){const t=this.createConnection(e);t.state="idle",n.push(t)}n.length>0?this.connections.set(e,n):this.connections.delete(e)}}cleanupNow(){this.cleanup()}async close(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null);for(const[t,e]of this.connections.entries())for(const t of e)t.controller.abort(),t.state="closed";this.connections.clear()}getConnectionCount(t){const e=this.connections.get(t);return e?e.length:0}getOrigins(){return Array.from(this.connections.keys())}isHealthy(){const t=this.getMetrics();return!((t.totalRequests>0?t.failedRequests/t.totalRequests:0)>.1)&&!(t.avgRequestDuration>5e3)}}exports.ConnectionPool=ConnectionPool;let globalPool=null;function getGlobalPool(t){return globalPool||(globalPool=new ConnectionPool(t)),globalPool}async function resetGlobalPool(){globalPool&&(await globalPool.close(),globalPool=null)}