@private.me/xbind 3.0.2 → 3.0.4

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 (222) hide show
  1. package/README.md +2366 -204
  2. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  3. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  4. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  5. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  6. package/dist-standalone/_deps/shared/errors.js +1 -244
  7. package/dist-standalone/_deps/shared/index.js +1 -72
  8. package/dist-standalone/_deps/shared/types.js +1 -86
  9. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  10. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  20. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  21. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  28. package/dist-standalone/_deps/xchange/errors.js +1 -1
  29. package/dist-standalone/_deps/xchange/index.js +1 -1
  30. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  31. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  32. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  33. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  34. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  40. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  41. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  42. package/dist-standalone/_deps/xregistry/index.js +1 -1
  43. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  44. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  45. package/dist-standalone/_deps/xregistry/types.js +1 -1
  46. package/dist-standalone/agent-call.d.ts +2 -2
  47. package/dist-standalone/agent-call.js +1 -659
  48. package/dist-standalone/agent-sdk.js +1 -328
  49. package/dist-standalone/agent.d.ts +2 -0
  50. package/dist-standalone/agent.js +1 -1800
  51. package/dist-standalone/approval.js +1 -193
  52. package/dist-standalone/async-iterators.d.ts +3 -3
  53. package/dist-standalone/async-iterators.js +1 -382
  54. package/dist-standalone/auth.js +1 -219
  55. package/dist-standalone/auto-accept.js +1 -229
  56. package/dist-standalone/backup-config.js +1 -201
  57. package/dist-standalone/backup.js +1 -326
  58. package/dist-standalone/batch-operations.js +1 -388
  59. package/dist-standalone/cancellation.js +1 -477
  60. package/dist-standalone/checkpoint.js +1 -186
  61. package/dist-standalone/circuit-breaker.js +1 -468
  62. package/dist-standalone/cjs/agent-call.js +1 -701
  63. package/dist-standalone/cjs/agent-sdk.js +1 -332
  64. package/dist-standalone/cjs/agent.js +1 -1837
  65. package/dist-standalone/cjs/approval.js +1 -199
  66. package/dist-standalone/cjs/async-iterators.js +1 -392
  67. package/dist-standalone/cjs/auth.js +1 -225
  68. package/dist-standalone/cjs/auto-accept.js +1 -233
  69. package/dist-standalone/cjs/backup-config.js +1 -207
  70. package/dist-standalone/cjs/backup.js +1 -330
  71. package/dist-standalone/cjs/batch-operations.js +1 -397
  72. package/dist-standalone/cjs/cancellation.js +1 -490
  73. package/dist-standalone/cjs/checkpoint.js +1 -193
  74. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  75. package/dist-standalone/cjs/cli/init.js +1 -492
  76. package/dist-standalone/cjs/config-validation.js +1 -522
  77. package/dist-standalone/cjs/connect.js +1 -312
  78. package/dist-standalone/cjs/connection-pool.js +1 -506
  79. package/dist-standalone/cjs/correlation-id.js +1 -339
  80. package/dist-standalone/cjs/crypto-utils.js +1 -176
  81. package/dist-standalone/cjs/debug-mode.js +1 -534
  82. package/dist-standalone/cjs/did-document.js +1 -101
  83. package/dist-standalone/cjs/did-privateme.js +1 -130
  84. package/dist-standalone/cjs/did-web.js +1 -201
  85. package/dist-standalone/cjs/discovery.js +1 -462
  86. package/dist-standalone/cjs/dual-mode.js +1 -251
  87. package/dist-standalone/cjs/email-templates.js +1 -313
  88. package/dist-standalone/cjs/email-transport.js +1 -239
  89. package/dist-standalone/cjs/envelope.js +1 -538
  90. package/dist-standalone/cjs/errors.js +1 -913
  91. package/dist-standalone/cjs/event-emitter.js +1 -461
  92. package/dist-standalone/cjs/gateway-state.js +1 -55
  93. package/dist-standalone/cjs/gateway-transport.js +1 -120
  94. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  95. package/dist-standalone/cjs/guardrails.js +1 -223
  96. package/dist-standalone/cjs/health-check.js +1 -336
  97. package/dist-standalone/cjs/http-compat.js +1 -272
  98. package/dist-standalone/cjs/http-status-map.js +1 -571
  99. package/dist-standalone/cjs/identity.js +1 -645
  100. package/dist-standalone/cjs/index.js +1 -406
  101. package/dist-standalone/cjs/invitation.js +1 -421
  102. package/dist-standalone/cjs/invite.js +1 -328
  103. package/dist-standalone/cjs/key-agreement.js +1 -335
  104. package/dist-standalone/cjs/lazy-init.js +1 -300
  105. package/dist-standalone/cjs/logger.js +1 -291
  106. package/dist-standalone/cjs/loopback-transport.js +1 -0
  107. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  108. package/dist-standalone/cjs/nonce-store.js +1 -80
  109. package/dist-standalone/cjs/pairing-manager.js +1 -223
  110. package/dist-standalone/cjs/plugin-system.js +1 -264
  111. package/dist-standalone/cjs/plugins/logging.js +1 -168
  112. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  113. package/dist-standalone/cjs/plugins/validation.js +1 -302
  114. package/dist-standalone/cjs/policy.js +1 -320
  115. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  116. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  117. package/dist-standalone/cjs/registry-middleware.js +1 -50
  118. package/dist-standalone/cjs/retry-strategies.js +1 -544
  119. package/dist-standalone/cjs/retry-transport.js +1 -102
  120. package/dist-standalone/cjs/runtime/browser.js +1 -533
  121. package/dist-standalone/cjs/runtime/edge.js +1 -526
  122. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  123. package/dist-standalone/cjs/security-policy.js +1 -245
  124. package/dist-standalone/cjs/serialization.js +1 -1040
  125. package/dist-standalone/cjs/split-channel.js +1 -225
  126. package/dist-standalone/cjs/subscription-proof.js +1 -230
  127. package/dist-standalone/cjs/succession.js +1 -148
  128. package/dist-standalone/cjs/timeouts.js +1 -412
  129. package/dist-standalone/cjs/trace-context.js +1 -424
  130. package/dist-standalone/cjs/trace-spans.js +1 -495
  131. package/dist-standalone/cjs/transport.js +1 -63
  132. package/dist-standalone/cjs/trust-registry.js +1 -991
  133. package/dist-standalone/cjs/types/error-response.js +1 -56
  134. package/dist-standalone/cjs/vault-auth.js +1 -178
  135. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  136. package/dist-standalone/cjs/verify.js +1 -25
  137. package/dist-standalone/cjs/version-info.js +1 -543
  138. package/dist-standalone/cjs/xfetch.js +1 -340
  139. package/dist-standalone/cli/init.js +1 -455
  140. package/dist-standalone/cli/setup.js +1 -514
  141. package/dist-standalone/cli/types.js +1 -27
  142. package/dist-standalone/cli/xbind.js +1 -148
  143. package/dist-standalone/config-validation.js +1 -513
  144. package/dist-standalone/connect.js +1 -274
  145. package/dist-standalone/connection-pool.js +1 -500
  146. package/dist-standalone/correlation-id.js +1 -326
  147. package/dist-standalone/crypto-utils.d.ts +2 -7
  148. package/dist-standalone/crypto-utils.js +1 -157
  149. package/dist-standalone/debug-mode.js +1 -510
  150. package/dist-standalone/did-document.js +1 -96
  151. package/dist-standalone/did-privateme.js +1 -121
  152. package/dist-standalone/did-web.js +1 -196
  153. package/dist-standalone/discovery.js +1 -458
  154. package/dist-standalone/dual-mode.js +1 -247
  155. package/dist-standalone/email-templates.js +1 -309
  156. package/dist-standalone/email-transport.d.ts +2 -2
  157. package/dist-standalone/email-transport.js +1 -232
  158. package/dist-standalone/envelope.js +1 -525
  159. package/dist-standalone/errors.d.ts +13 -3
  160. package/dist-standalone/errors.js +1 -896
  161. package/dist-standalone/event-emitter.js +1 -456
  162. package/dist-standalone/gateway-state.d.ts +1 -1
  163. package/dist-standalone/gateway-state.js +1 -51
  164. package/dist-standalone/gateway-transport.js +1 -116
  165. package/dist-standalone/graceful-degradation.js +1 -396
  166. package/dist-standalone/guardrails.js +1 -216
  167. package/dist-standalone/health-check.d.ts +5 -1
  168. package/dist-standalone/health-check.js +1 -332
  169. package/dist-standalone/http-compat.d.ts +1 -1
  170. package/dist-standalone/http-compat.js +1 -267
  171. package/dist-standalone/http-status-map.js +1 -561
  172. package/dist-standalone/identity.js +1 -619
  173. package/dist-standalone/index.d.ts +15 -4
  174. package/dist-standalone/index.js +1 -78
  175. package/dist-standalone/invitation.js +1 -415
  176. package/dist-standalone/invite.js +1 -324
  177. package/dist-standalone/key-agreement.js +1 -325
  178. package/dist-standalone/lazy-init.d.ts +11 -6
  179. package/dist-standalone/lazy-init.js +1 -295
  180. package/dist-standalone/logger.js +1 -285
  181. package/dist-standalone/loopback-transport.d.ts +87 -0
  182. package/dist-standalone/loopback-transport.js +1 -0
  183. package/dist-standalone/mdns-discovery.js +1 -195
  184. package/dist-standalone/nonce-store.js +1 -76
  185. package/dist-standalone/pairing-manager.js +1 -219
  186. package/dist-standalone/plugin-system.js +1 -257
  187. package/dist-standalone/plugins/logging.js +1 -163
  188. package/dist-standalone/plugins/metrics.d.ts +4 -4
  189. package/dist-standalone/plugins/metrics.js +1 -176
  190. package/dist-standalone/plugins/validation.js +1 -297
  191. package/dist-standalone/policy.js +1 -315
  192. package/dist-standalone/progress-callbacks.js +1 -576
  193. package/dist-standalone/redis-nonce-store.js +1 -72
  194. package/dist-standalone/registry-middleware.js +1 -47
  195. package/dist-standalone/retry-strategies.js +1 -534
  196. package/dist-standalone/retry-transport.js +1 -98
  197. package/dist-standalone/runtime/browser.js +1 -516
  198. package/dist-standalone/runtime/edge.js +1 -511
  199. package/dist-standalone/runtime/react-native.d.ts +1 -1
  200. package/dist-standalone/runtime/react-native.js +1 -383
  201. package/dist-standalone/security-policy.js +1 -239
  202. package/dist-standalone/serialization.js +1 -1031
  203. package/dist-standalone/split-channel.d.ts +1 -1
  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.d.ts +1 -1
  211. package/dist-standalone/transport.js +1 -59
  212. package/dist-standalone/trust-registry.d.ts +3 -3
  213. package/dist-standalone/trust-registry.js +1 -950
  214. package/dist-standalone/types/error-response.js +1 -52
  215. package/dist-standalone/vault-auth.js +1 -174
  216. package/dist-standalone/vault-store-loader.d.ts +9 -0
  217. package/dist-standalone/vault-store-loader.js +1 -187
  218. package/dist-standalone/verify.js +1 -16
  219. package/dist-standalone/version-info.js +1 -530
  220. package/dist-standalone/xfetch.js +1 -335
  221. package/package.json +1 -1
  222. 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)}