@j0hanz/fetch-url-mcp 1.3.1 → 1.5.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 (205) hide show
  1. package/README.md +24 -21
  2. package/dist/cli.d.ts +3 -3
  3. package/dist/cli.js +15 -8
  4. package/dist/http/auth.d.ts +6 -6
  5. package/dist/http/auth.js +78 -23
  6. package/dist/http/health.d.ts +1 -2
  7. package/dist/http/health.js +7 -18
  8. package/dist/http/helpers.d.ts +3 -11
  9. package/dist/http/helpers.js +28 -26
  10. package/dist/http/native.d.ts +0 -1
  11. package/dist/http/native.js +63 -41
  12. package/dist/http/rate-limit.d.ts +2 -2
  13. package/dist/http/rate-limit.js +11 -16
  14. package/dist/index.d.ts +0 -1
  15. package/dist/index.js +17 -20
  16. package/dist/{markdown-cleanup.d.ts → lib/content.d.ts} +4 -2
  17. package/dist/lib/content.js +1356 -0
  18. package/dist/lib/core.d.ts +253 -0
  19. package/dist/lib/core.js +1228 -0
  20. package/dist/{tool-pipeline.d.ts → lib/fetch-pipeline.d.ts} +1 -3
  21. package/dist/{tool-pipeline.js → lib/fetch-pipeline.js} +18 -44
  22. package/dist/{fetch.d.ts → lib/http.d.ts} +7 -9
  23. package/dist/{fetch.js → lib/http.js} +721 -1004
  24. package/dist/lib/mcp-tools.d.ts +28 -0
  25. package/dist/lib/mcp-tools.js +107 -0
  26. package/dist/{tool-progress.d.ts → lib/progress.d.ts} +0 -2
  27. package/dist/{tool-progress.js → lib/progress.js} +9 -14
  28. package/dist/lib/task-handlers.d.ts +5 -0
  29. package/dist/{mcp.js → lib/task-handlers.js} +95 -31
  30. package/dist/lib/url.d.ts +70 -0
  31. package/dist/lib/url.js +686 -0
  32. package/dist/lib/utils.d.ts +58 -0
  33. package/dist/lib/utils.js +304 -0
  34. package/dist/{prompts.d.ts → prompts/index.d.ts} +0 -1
  35. package/dist/{prompts.js → prompts/index.js} +1 -2
  36. package/dist/{resources.d.ts → resources/index.d.ts} +0 -1
  37. package/dist/{resources.js → resources/index.js} +87 -64
  38. package/dist/{instructions.d.ts → resources/instructions.d.ts} +0 -1
  39. package/dist/{instructions.js → resources/instructions.js} +5 -3
  40. package/dist/schemas/inputs.d.ts +7 -0
  41. package/dist/schemas/inputs.js +24 -0
  42. package/dist/schemas/outputs.d.ts +23 -0
  43. package/dist/schemas/outputs.js +77 -0
  44. package/dist/server.d.ts +0 -1
  45. package/dist/server.js +26 -25
  46. package/dist/tasks/execution.d.ts +0 -1
  47. package/dist/tasks/execution.js +106 -70
  48. package/dist/tasks/manager.d.ts +11 -3
  49. package/dist/tasks/manager.js +97 -73
  50. package/dist/tasks/owner.d.ts +3 -3
  51. package/dist/tasks/owner.js +2 -2
  52. package/dist/tasks/tool-registry.d.ts +11 -0
  53. package/dist/tasks/tool-registry.js +13 -0
  54. package/dist/tools/fetch-url.d.ts +28 -0
  55. package/dist/{tools.js → tools/fetch-url.js} +95 -147
  56. package/dist/tools/index.d.ts +2 -0
  57. package/dist/tools/index.js +4 -0
  58. package/dist/transform/html-translators.d.ts +1 -0
  59. package/dist/transform/html-translators.js +454 -0
  60. package/dist/transform/metadata.d.ts +4 -0
  61. package/dist/transform/metadata.js +183 -0
  62. package/dist/transform/transform.d.ts +0 -1
  63. package/dist/transform/transform.js +44 -679
  64. package/dist/transform/types.d.ts +9 -12
  65. package/dist/transform/types.js +0 -1
  66. package/dist/transform/worker-pool.d.ts +0 -1
  67. package/dist/transform/worker-pool.js +7 -16
  68. package/dist/transform/workers/shared.d.ts +7 -0
  69. package/dist/transform/workers/shared.js +130 -0
  70. package/dist/transform/workers/transform-child.d.ts +0 -1
  71. package/dist/transform/workers/transform-child.js +5 -135
  72. package/dist/transform/workers/transform-worker.d.ts +0 -1
  73. package/dist/transform/workers/transform-worker.js +7 -128
  74. package/package.json +11 -7
  75. package/dist/cache.d.ts +0 -54
  76. package/dist/cache.d.ts.map +0 -1
  77. package/dist/cache.js +0 -261
  78. package/dist/cache.js.map +0 -1
  79. package/dist/cli.d.ts.map +0 -1
  80. package/dist/cli.js.map +0 -1
  81. package/dist/config.d.ts +0 -141
  82. package/dist/config.d.ts.map +0 -1
  83. package/dist/config.js +0 -473
  84. package/dist/config.js.map +0 -1
  85. package/dist/crypto.d.ts +0 -4
  86. package/dist/crypto.d.ts.map +0 -1
  87. package/dist/crypto.js +0 -56
  88. package/dist/crypto.js.map +0 -1
  89. package/dist/dom-noise-removal.d.ts +0 -2
  90. package/dist/dom-noise-removal.d.ts.map +0 -1
  91. package/dist/dom-noise-removal.js +0 -494
  92. package/dist/dom-noise-removal.js.map +0 -1
  93. package/dist/download.d.ts +0 -4
  94. package/dist/download.d.ts.map +0 -1
  95. package/dist/download.js +0 -106
  96. package/dist/download.js.map +0 -1
  97. package/dist/errors.d.ts +0 -11
  98. package/dist/errors.d.ts.map +0 -1
  99. package/dist/errors.js +0 -65
  100. package/dist/errors.js.map +0 -1
  101. package/dist/examples/mcp-fetch-url-client.js +0 -329
  102. package/dist/examples/mcp-fetch-url-client.js.map +0 -1
  103. package/dist/fetch-content.d.ts +0 -5
  104. package/dist/fetch-content.d.ts.map +0 -1
  105. package/dist/fetch-content.js +0 -164
  106. package/dist/fetch-content.js.map +0 -1
  107. package/dist/fetch-stream.d.ts +0 -5
  108. package/dist/fetch-stream.d.ts.map +0 -1
  109. package/dist/fetch-stream.js +0 -29
  110. package/dist/fetch-stream.js.map +0 -1
  111. package/dist/fetch.d.ts.map +0 -1
  112. package/dist/fetch.js.map +0 -1
  113. package/dist/host-normalization.d.ts +0 -2
  114. package/dist/host-normalization.d.ts.map +0 -1
  115. package/dist/host-normalization.js +0 -91
  116. package/dist/host-normalization.js.map +0 -1
  117. package/dist/http/auth.d.ts.map +0 -1
  118. package/dist/http/auth.js.map +0 -1
  119. package/dist/http/health.d.ts.map +0 -1
  120. package/dist/http/health.js.map +0 -1
  121. package/dist/http/helpers.d.ts.map +0 -1
  122. package/dist/http/helpers.js.map +0 -1
  123. package/dist/http/native.d.ts.map +0 -1
  124. package/dist/http/native.js.map +0 -1
  125. package/dist/http/rate-limit.d.ts.map +0 -1
  126. package/dist/http/rate-limit.js.map +0 -1
  127. package/dist/index.d.ts.map +0 -1
  128. package/dist/index.js.map +0 -1
  129. package/dist/instructions.d.ts.map +0 -1
  130. package/dist/instructions.js.map +0 -1
  131. package/dist/ip-blocklist.d.ts +0 -9
  132. package/dist/ip-blocklist.d.ts.map +0 -1
  133. package/dist/ip-blocklist.js +0 -79
  134. package/dist/ip-blocklist.js.map +0 -1
  135. package/dist/json.d.ts +0 -2
  136. package/dist/json.d.ts.map +0 -1
  137. package/dist/json.js +0 -45
  138. package/dist/json.js.map +0 -1
  139. package/dist/language-detection.d.ts +0 -3
  140. package/dist/language-detection.d.ts.map +0 -1
  141. package/dist/language-detection.js +0 -355
  142. package/dist/language-detection.js.map +0 -1
  143. package/dist/markdown-cleanup.d.ts.map +0 -1
  144. package/dist/markdown-cleanup.js +0 -534
  145. package/dist/markdown-cleanup.js.map +0 -1
  146. package/dist/mcp-validator.d.ts +0 -17
  147. package/dist/mcp-validator.d.ts.map +0 -1
  148. package/dist/mcp-validator.js +0 -45
  149. package/dist/mcp-validator.js.map +0 -1
  150. package/dist/mcp.d.ts +0 -4
  151. package/dist/mcp.d.ts.map +0 -1
  152. package/dist/mcp.js.map +0 -1
  153. package/dist/observability.d.ts +0 -23
  154. package/dist/observability.d.ts.map +0 -1
  155. package/dist/observability.js +0 -238
  156. package/dist/observability.js.map +0 -1
  157. package/dist/prompts.d.ts.map +0 -1
  158. package/dist/prompts.js.map +0 -1
  159. package/dist/resources.d.ts.map +0 -1
  160. package/dist/resources.js.map +0 -1
  161. package/dist/server-tuning.d.ts +0 -15
  162. package/dist/server-tuning.d.ts.map +0 -1
  163. package/dist/server-tuning.js +0 -49
  164. package/dist/server-tuning.js.map +0 -1
  165. package/dist/server.d.ts.map +0 -1
  166. package/dist/server.js.map +0 -1
  167. package/dist/session.d.ts +0 -42
  168. package/dist/session.d.ts.map +0 -1
  169. package/dist/session.js +0 -255
  170. package/dist/session.js.map +0 -1
  171. package/dist/tasks/execution.d.ts.map +0 -1
  172. package/dist/tasks/execution.js.map +0 -1
  173. package/dist/tasks/manager.d.ts.map +0 -1
  174. package/dist/tasks/manager.js.map +0 -1
  175. package/dist/tasks/owner.d.ts.map +0 -1
  176. package/dist/tasks/owner.js.map +0 -1
  177. package/dist/timer-utils.d.ts +0 -6
  178. package/dist/timer-utils.d.ts.map +0 -1
  179. package/dist/timer-utils.js +0 -27
  180. package/dist/timer-utils.js.map +0 -1
  181. package/dist/tool-errors.d.ts +0 -12
  182. package/dist/tool-errors.d.ts.map +0 -1
  183. package/dist/tool-errors.js +0 -55
  184. package/dist/tool-errors.js.map +0 -1
  185. package/dist/tool-pipeline.d.ts.map +0 -1
  186. package/dist/tool-pipeline.js.map +0 -1
  187. package/dist/tool-progress.d.ts.map +0 -1
  188. package/dist/tool-progress.js.map +0 -1
  189. package/dist/tools.d.ts +0 -54
  190. package/dist/tools.d.ts.map +0 -1
  191. package/dist/tools.js.map +0 -1
  192. package/dist/transform/transform.d.ts.map +0 -1
  193. package/dist/transform/transform.js.map +0 -1
  194. package/dist/transform/types.d.ts.map +0 -1
  195. package/dist/transform/types.js.map +0 -1
  196. package/dist/transform/worker-pool.d.ts.map +0 -1
  197. package/dist/transform/worker-pool.js.map +0 -1
  198. package/dist/transform/workers/transform-child.d.ts.map +0 -1
  199. package/dist/transform/workers/transform-child.js.map +0 -1
  200. package/dist/transform/workers/transform-worker.d.ts.map +0 -1
  201. package/dist/transform/workers/transform-worker.js.map +0 -1
  202. package/dist/type-guards.d.ts +0 -16
  203. package/dist/type-guards.d.ts.map +0 -1
  204. package/dist/type-guards.js +0 -13
  205. package/dist/type-guards.js.map +0 -1
@@ -1,20 +1,21 @@
1
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
2
- import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
3
1
  import { randomUUID } from 'node:crypto';
4
2
  import { readFileSync } from 'node:fs';
5
3
  import { createServer, } from 'node:http';
6
4
  import { createServer as createHttpsServer, } from 'node:https';
7
5
  import { hostname } from 'node:os';
8
6
  import process from 'node:process';
9
- import { config, enableHttpMode } from '../config.js';
10
- import { handleDownload } from '../download.js';
11
- import { acceptsEventStream, acceptsJsonAndEventStream, isJsonRpcBatchRequest, isMcpRequestBody, } from '../mcp-validator.js';
12
- import { cancelTasksForOwner } from '../mcp.js';
13
- import { logError, logInfo, registerMcpSessionServer, resolveMcpSessionIdByServer, runWithRequestContext, unregisterMcpSessionServer, unregisterMcpSessionServerByServer, } from '../observability.js';
14
- import { applyHttpServerTuning, drainConnectionsOnShutdown, } from '../server-tuning.js';
7
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
8
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
9
+ import { config, enableHttpMode } from '../lib/core.js';
10
+ import { logError, logInfo, registerMcpSessionServer, resolveMcpSessionIdByServer, runWithRequestContext, unregisterMcpSessionServer, unregisterMcpSessionServerByServer, } from '../lib/core.js';
11
+ import { composeCloseHandlers, createSessionStore, createSlotTracker, ensureSessionCapacity, reserveSessionSlot, startSessionCleanupLoop, } from '../lib/core.js';
12
+ import { handleDownload } from '../lib/http.js';
13
+ import { acceptsEventStream, acceptsJsonAndEventStream, isJsonRpcBatchRequest, isMcpRequestBody, } from '../lib/mcp-tools.js';
14
+ import { cancelTasksForOwner } from '../lib/mcp-tools.js';
15
+ import { toError } from '../lib/utils.js';
16
+ import { applyHttpServerTuning, drainConnectionsOnShutdown, } from '../lib/utils.js';
17
+ import { isObject } from '../lib/utils.js';
15
18
  import { createMcpServerForHttpSession } from '../server.js';
16
- import { composeCloseHandlers, createSessionStore, createSlotTracker, ensureSessionCapacity, reserveSessionSlot, startSessionCleanupLoop, } from '../session.js';
17
- import { isObject } from '../type-guards.js';
18
19
  import { applyUnauthorizedAuthHeaders, assertHttpModeConfiguration, authService, buildAuthFingerprint, buildProtectedResourceMetadataDocument, corsPolicy, ensureMcpProtocolVersion, hostOriginPolicy, isProtectedResourceMetadataPath, SUPPORTED_MCP_PROTOCOL_VERSIONS, } from './auth.js';
19
20
  import { disableEventLoopMonitoring, resetEventLoopMonitoring, sendHealthRouteResponse, shouldHandleHealthRoute, } from './health.js';
20
21
  import { buildRequestContext, closeMcpServerBestEffort, closeTransportBestEffort, createRequestAbortSignal, createTransportAdapter, DEFAULT_BODY_LIMIT_BYTES, drainRequest, findDuplicateSingleValueHeader, getHeaderValue, getMcpSessionId, jsonBodyReader, registerInboundBlockList, sendError, sendJson, sendText, } from './helpers.js';
@@ -36,7 +37,7 @@ function resolveRequestedProtocolVersion(body) {
36
37
  if (normalized.length === 0)
37
38
  return DEFAULT_MCP_PROTOCOL_VERSION;
38
39
  if (!SUPPORTED_MCP_PROTOCOL_VERSIONS.has(normalized)) {
39
- return DEFAULT_MCP_PROTOCOL_VERSION;
40
+ return null;
40
41
  }
41
42
  return normalized;
42
43
  }
@@ -70,13 +71,22 @@ class McpSessionGateway {
70
71
  return;
71
72
  }
72
73
  const requestId = body.id ?? null;
73
- const isInitNotification = isInitializedNotification(body.method);
74
+ const isInitializedMethod = isInitializedNotification(body.method);
75
+ const isInitNotification = isInitializedMethod && body.id === undefined;
74
76
  const sessionId = getMcpSessionId(ctx.req);
75
- let session = sessionId ? this.store.get(sessionId) : undefined;
77
+ if (isInitializedMethod && !isInitNotification) {
78
+ sendError(ctx.res, -32600, 'notifications/initialized must be sent as a notification', 400, requestId);
79
+ return;
80
+ }
81
+ const session = sessionId ? this.store.get(sessionId) : undefined;
76
82
  if (sessionId && !session) {
77
83
  sendError(ctx.res, -32600, 'Session not found', 404, requestId);
78
84
  return;
79
85
  }
86
+ if (!session && isInitNotification) {
87
+ sendError(ctx.res, -32600, 'Missing session ID', 400, requestId);
88
+ return;
89
+ }
80
90
  if (session) {
81
91
  if (!ensureMcpProtocolVersion(ctx.req, ctx.res, {
82
92
  requireHeader: true,
@@ -91,17 +101,20 @@ class McpSessionGateway {
91
101
  return;
92
102
  }
93
103
  }
94
- if (isInitNotification && !session.protocolInitialized) {
95
- session.protocolInitialized = true;
96
- if (sessionId)
97
- this.store.touch(sessionId);
98
- }
99
104
  }
100
105
  else {
101
- if (!ensureMcpProtocolVersion(ctx.req, ctx.res))
106
+ if (!ensureMcpProtocolVersion(ctx.req, ctx.res, {
107
+ requireHeader: config.server.http.requireProtocolVersionHeaderOnSessionInit,
108
+ })) {
102
109
  return;
110
+ }
103
111
  }
104
- if (isInitNotification && body.id === undefined) {
112
+ if (session && isInitNotification) {
113
+ if (!session.protocolInitialized) {
114
+ session.protocolInitialized = true;
115
+ }
116
+ if (sessionId)
117
+ this.store.touch(sessionId);
105
118
  sendText(ctx.res, 200, '');
106
119
  return;
107
120
  }
@@ -114,13 +127,6 @@ class McpSessionGateway {
114
127
  if (!transport)
115
128
  return;
116
129
  await transport.handleRequest(ctx.req, ctx.res, body);
117
- if (sessionId && isInitNotification) {
118
- session = this.store.get(sessionId);
119
- if (session) {
120
- session.protocolInitialized = true;
121
- this.store.touch(sessionId);
122
- }
123
- }
124
130
  }
125
131
  async handleGet(ctx) {
126
132
  const sessionId = getMcpSessionId(ctx.req);
@@ -179,6 +185,10 @@ class McpSessionGateway {
179
185
  return null;
180
186
  }
181
187
  const negotiatedProtocolVersion = resolveRequestedProtocolVersion(ctx.body);
188
+ if (!negotiatedProtocolVersion) {
189
+ sendError(ctx.res, -32602, `Unsupported protocolVersion; supported versions: ${[...SUPPORTED_MCP_PROTOCOL_VERSIONS].join(', ')}`, 400, requestId);
190
+ return null;
191
+ }
182
192
  return this.createNewSession(ctx, requestId, negotiatedProtocolVersion);
183
193
  }
184
194
  getExistingTransport(sessionId, authFingerprint, res, requestId) {
@@ -288,6 +298,7 @@ class McpSessionGateway {
288
298
  sendError(res, -32000, 'Server busy', 503, requestId);
289
299
  return false;
290
300
  }
301
+ // Double-check: capacity may have changed during the async eviction window above.
291
302
  if (!reserveSessionSlot(this.store, config.server.maxSessions)) {
292
303
  sendError(res, -32000, 'Server busy', 503, requestId);
293
304
  return false;
@@ -360,7 +371,7 @@ class HttpDispatcher {
360
371
  if (!auth)
361
372
  return;
362
373
  const authCtx = { ...ctx, auth };
363
- if (this.tryHandleDownloadRoute(ctx))
374
+ if (this.tryHandleDownloadRoute(authCtx))
364
375
  return;
365
376
  if (ctx.url.pathname === '/mcp') {
366
377
  const handled = await this.handleMcpRoutes(authCtx);
@@ -370,7 +381,7 @@ class HttpDispatcher {
370
381
  sendJson(ctx.res, 404, { error: 'Not Found' });
371
382
  }
372
383
  catch (err) {
373
- const error = err instanceof Error ? err : new Error(String(err));
384
+ const error = toError(err);
374
385
  logError('Request failed', error);
375
386
  if (!ctx.res.writableEnded) {
376
387
  sendJson(ctx.res, 500, { error: 'Internal Server Error' });
@@ -398,9 +409,7 @@ class HttpDispatcher {
398
409
  }
399
410
  catch (err) {
400
411
  applyUnauthorizedAuthHeaders(ctx.req, ctx.res);
401
- sendJson(ctx.res, 401, {
402
- error: err instanceof Error ? err.message : 'Unauthorized',
403
- });
412
+ sendError(ctx.res, -32000, err instanceof Error ? err.message : 'Unauthorized', 401);
404
413
  return null;
405
414
  }
406
415
  }
@@ -500,7 +509,7 @@ class HttpRequestPipeline {
500
509
  // Server bootstrap
501
510
  // ---------------------------------------------------------------------------
502
511
  function handlePipelineError(error, res) {
503
- logError('Request pipeline failed', error instanceof Error ? error : new Error(String(error)));
512
+ logError('Request pipeline failed', toError(error));
504
513
  if (res.writableEnded)
505
514
  return;
506
515
  if (!res.headersSent) {
@@ -518,12 +527,18 @@ function createNetworkServer(listener) {
518
527
  if (!keyFile || !certFile) {
519
528
  throw new Error('HTTPS enabled but SERVER_TLS_KEY_FILE / SERVER_TLS_CERT_FILE are missing');
520
529
  }
521
- const tlsOptions = {
522
- key: readFileSync(keyFile),
523
- cert: readFileSync(certFile),
524
- };
525
- if (caFile) {
526
- tlsOptions.ca = readFileSync(caFile);
530
+ let tlsOptions;
531
+ try {
532
+ tlsOptions = {
533
+ key: readFileSync(keyFile),
534
+ cert: readFileSync(certFile),
535
+ };
536
+ if (caFile) {
537
+ tlsOptions.ca = readFileSync(caFile);
538
+ }
539
+ }
540
+ catch (err) {
541
+ throw new Error(`Failed to read TLS files (key=${keyFile}, cert=${certFile}): ${err instanceof Error ? err.message : String(err)}`, { cause: err });
527
542
  }
528
543
  return createHttpsServer(tlsOptions, listener);
529
544
  }
@@ -584,7 +599,15 @@ export async function startHttpServer() {
584
599
  resetEventLoopMonitoring();
585
600
  const rateLimiter = createRateLimitManagerImpl(config.rateLimit);
586
601
  const sessionStore = createSessionStore(config.server.sessionTtlMs);
587
- const sessionCleanup = startSessionCleanupLoop(sessionStore, config.server.sessionTtlMs);
602
+ const sessionCleanup = startSessionCleanupLoop(sessionStore, config.server.sessionTtlMs, {
603
+ onEvictSession: (session) => {
604
+ const sessionId = resolveMcpSessionIdByServer(session.server);
605
+ if (!sessionId)
606
+ return;
607
+ cancelTasksForOwner(`session:${sessionId}`, 'The task was cancelled because the MCP session expired.');
608
+ unregisterMcpSessionServer(sessionId);
609
+ },
610
+ });
588
611
  const mcpGateway = new McpSessionGateway(sessionStore, createMcpServerForHttpSession);
589
612
  const dispatcher = new HttpDispatcher(sessionStore, mcpGateway);
590
613
  const pipeline = new HttpRequestPipeline(rateLimiter, dispatcher);
@@ -615,4 +638,3 @@ export async function startHttpServer() {
615
638
  }),
616
639
  };
617
640
  }
618
- //# sourceMappingURL=native.js.map
@@ -1,5 +1,5 @@
1
1
  import { type RequestContext } from './helpers.js';
2
- export interface RateLimitConfig {
2
+ interface RateLimitConfig {
3
3
  maxRequests: number;
4
4
  windowMs: number;
5
5
  cleanupIntervalMs: number;
@@ -10,4 +10,4 @@ export interface RateLimitManagerImpl {
10
10
  stop(): void;
11
11
  }
12
12
  export declare function createRateLimitManagerImpl(options: RateLimitConfig): RateLimitManagerImpl;
13
- //# sourceMappingURL=rate-limit.d.ts.map
13
+ export {};
@@ -1,9 +1,7 @@
1
- import { setInterval as setIntervalPromise } from 'node:timers/promises';
2
- import { logWarn } from '../observability.js';
1
+ import { logWarn } from '../lib/core.js';
2
+ import { isAbortError } from '../lib/utils.js';
3
+ import { startAbortableIntervalLoop } from '../lib/utils.js';
3
4
  import { sendJson } from './helpers.js';
4
- function isAbortError(error) {
5
- return error instanceof Error && error.name === 'AbortError';
6
- }
7
5
  // ---------------------------------------------------------------------------
8
6
  // Rate limiter
9
7
  // ---------------------------------------------------------------------------
@@ -16,19 +14,17 @@ class RateLimiter {
16
14
  this.startCleanupLoop();
17
15
  }
18
16
  startCleanupLoop() {
19
- const interval = setIntervalPromise(this.options.cleanupIntervalMs, Date.now, { signal: this.cleanup.signal, ref: false });
20
- void (async () => {
21
- try {
22
- for await (const getNow of interval) {
23
- this.cleanupEntries(getNow());
24
- }
25
- }
26
- catch (err) {
17
+ startAbortableIntervalLoop(this.options.cleanupIntervalMs, Date.now, {
18
+ signal: this.cleanup.signal,
19
+ onTick: (getNow) => {
20
+ this.cleanupEntries(getNow());
21
+ },
22
+ onError: (err) => {
27
23
  if (!isAbortError(err)) {
28
24
  logWarn('Rate limit cleanup failed', { error: err });
29
25
  }
30
- }
31
- })();
26
+ },
27
+ });
32
28
  }
33
29
  cleanupEntries(now) {
34
30
  const maxIdle = this.options.windowMs * 2;
@@ -89,4 +85,3 @@ class RateLimiter {
89
85
  export function createRateLimitManagerImpl(options) {
90
86
  return new RateLimiter(options);
91
87
  }
92
- //# sourceMappingURL=rate-limit.js.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  export {};
3
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process';
3
+ import { serverVersion } from './lib/core.js';
4
+ import { logError } from './lib/core.js';
5
+ import { toError } from './lib/utils.js';
3
6
  import { parseCliArgs, renderCliUsage } from './cli.js';
4
- import { serverVersion } from './config.js';
5
7
  import { startHttpServer } from './http/native.js';
6
- import { logError } from './observability.js';
7
8
  import { startStdioServer } from './server.js';
8
9
  const FORCE_EXIT_TIMEOUT_MS = 10_000;
9
10
  let forcedExitTimer;
10
- function toError(value) {
11
- return value instanceof Error ? value : new Error(String(value));
11
+ function writeAndExit(stream, text, code) {
12
+ stream.write(text);
13
+ process.exit(code);
12
14
  }
13
15
  function scheduleForcedExit(reason) {
14
16
  if (forcedExitTimer)
@@ -21,20 +23,16 @@ function scheduleForcedExit(reason) {
21
23
  }
22
24
  const parseResult = parseCliArgs(process.argv.slice(2));
23
25
  if (!parseResult.ok) {
24
- process.stderr.write(`Invalid arguments: ${parseResult.message}\n\n`);
25
- process.stderr.write(renderCliUsage());
26
- process.exit(1);
26
+ writeAndExit(process.stderr, `Invalid arguments: ${parseResult.message}\n\n${renderCliUsage()}`, 1);
27
27
  }
28
28
  const { values } = parseResult;
29
29
  if (values.help) {
30
- process.stdout.write(renderCliUsage());
31
- process.exit(0);
30
+ writeAndExit(process.stdout, renderCliUsage(), 0);
32
31
  }
33
32
  if (values.version) {
34
- process.stdout.write(`${serverVersion}\n`);
35
- process.exit(0);
33
+ writeAndExit(process.stdout, `${serverVersion}\n`, 0);
36
34
  }
37
- const isStdioMode = values.stdio;
35
+ const isStdioMode = !values.http;
38
36
  let isShuttingDown = false;
39
37
  const shutdownHandlerRef = {};
40
38
  function shouldAttemptShutdown() {
@@ -47,19 +45,19 @@ function attemptShutdown(signal) {
47
45
  process.stderr.write('Attempting graceful shutdown...\n');
48
46
  void shutdownHandlerRef.current(signal);
49
47
  }
50
- function registerOnceSignal(signal, handler) {
51
- process.once(signal, () => {
52
- handler(signal);
53
- });
48
+ function registerSignalHandlers(signals, handler) {
49
+ for (const signal of signals) {
50
+ process.once(signal, () => {
51
+ handler(signal);
52
+ });
53
+ }
54
54
  }
55
55
  function registerHttpSignalHandlers() {
56
56
  const tryShutdown = (signal) => {
57
57
  if (shouldAttemptShutdown())
58
58
  attemptShutdown(signal);
59
59
  };
60
- for (const signal of ['SIGINT', 'SIGTERM']) {
61
- registerOnceSignal(signal, tryShutdown);
62
- }
60
+ registerSignalHandlers(['SIGINT', 'SIGTERM'], tryShutdown);
63
61
  }
64
62
  function writeStartupError(error) {
65
63
  logError('Failed to start server', error);
@@ -97,4 +95,3 @@ try {
97
95
  catch (error) {
98
96
  writeStartupError(toError(error));
99
97
  }
100
- //# sourceMappingURL=index.js.map
@@ -1,4 +1,7 @@
1
- import type { MetadataBlock } from './transform/types.js';
1
+ import { type MetadataBlock } from '../transform/types.js';
2
+ export declare function removeNoiseFromHtml(html: string, document?: Document, baseUrl?: string, signal?: AbortSignal): string;
3
+ export declare function resolveLanguageFromAttributes(className: string, dataLang: string): string | undefined;
4
+ export declare function detectLanguageFromCode(code: string): string | undefined;
2
5
  interface CleanupOptions {
3
6
  signal?: AbortSignal;
4
7
  url?: string;
@@ -9,4 +12,3 @@ export declare function addSourceToMarkdown(content: string, url: string): strin
9
12
  export declare function isRawTextContent(content: string): boolean;
10
13
  export declare function buildMetadataFooter(metadata?: MetadataBlock, fallbackUrl?: string): string;
11
14
  export {};
12
- //# sourceMappingURL=markdown-cleanup.d.ts.map