@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.
- package/README.md +24 -21
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +15 -8
- package/dist/http/auth.d.ts +6 -6
- package/dist/http/auth.js +78 -23
- package/dist/http/health.d.ts +1 -2
- package/dist/http/health.js +7 -18
- package/dist/http/helpers.d.ts +3 -11
- package/dist/http/helpers.js +28 -26
- package/dist/http/native.d.ts +0 -1
- package/dist/http/native.js +63 -41
- package/dist/http/rate-limit.d.ts +2 -2
- package/dist/http/rate-limit.js +11 -16
- package/dist/index.d.ts +0 -1
- package/dist/index.js +17 -20
- package/dist/{markdown-cleanup.d.ts → lib/content.d.ts} +4 -2
- package/dist/lib/content.js +1356 -0
- package/dist/lib/core.d.ts +253 -0
- package/dist/lib/core.js +1228 -0
- package/dist/{tool-pipeline.d.ts → lib/fetch-pipeline.d.ts} +1 -3
- package/dist/{tool-pipeline.js → lib/fetch-pipeline.js} +18 -44
- package/dist/{fetch.d.ts → lib/http.d.ts} +7 -9
- package/dist/{fetch.js → lib/http.js} +721 -1004
- package/dist/lib/mcp-tools.d.ts +28 -0
- package/dist/lib/mcp-tools.js +107 -0
- package/dist/{tool-progress.d.ts → lib/progress.d.ts} +0 -2
- package/dist/{tool-progress.js → lib/progress.js} +9 -14
- package/dist/lib/task-handlers.d.ts +5 -0
- package/dist/{mcp.js → lib/task-handlers.js} +95 -31
- package/dist/lib/url.d.ts +70 -0
- package/dist/lib/url.js +686 -0
- package/dist/lib/utils.d.ts +58 -0
- package/dist/lib/utils.js +304 -0
- package/dist/{prompts.d.ts → prompts/index.d.ts} +0 -1
- package/dist/{prompts.js → prompts/index.js} +1 -2
- package/dist/{resources.d.ts → resources/index.d.ts} +0 -1
- package/dist/{resources.js → resources/index.js} +87 -64
- package/dist/{instructions.d.ts → resources/instructions.d.ts} +0 -1
- package/dist/{instructions.js → resources/instructions.js} +5 -3
- package/dist/schemas/inputs.d.ts +7 -0
- package/dist/schemas/inputs.js +24 -0
- package/dist/schemas/outputs.d.ts +23 -0
- package/dist/schemas/outputs.js +77 -0
- package/dist/server.d.ts +0 -1
- package/dist/server.js +26 -25
- package/dist/tasks/execution.d.ts +0 -1
- package/dist/tasks/execution.js +106 -70
- package/dist/tasks/manager.d.ts +11 -3
- package/dist/tasks/manager.js +97 -73
- package/dist/tasks/owner.d.ts +3 -3
- package/dist/tasks/owner.js +2 -2
- package/dist/tasks/tool-registry.d.ts +11 -0
- package/dist/tasks/tool-registry.js +13 -0
- package/dist/tools/fetch-url.d.ts +28 -0
- package/dist/{tools.js → tools/fetch-url.js} +95 -147
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +4 -0
- package/dist/transform/html-translators.d.ts +1 -0
- package/dist/transform/html-translators.js +454 -0
- package/dist/transform/metadata.d.ts +4 -0
- package/dist/transform/metadata.js +183 -0
- package/dist/transform/transform.d.ts +0 -1
- package/dist/transform/transform.js +44 -679
- package/dist/transform/types.d.ts +9 -12
- package/dist/transform/types.js +0 -1
- package/dist/transform/worker-pool.d.ts +0 -1
- package/dist/transform/worker-pool.js +7 -16
- package/dist/transform/workers/shared.d.ts +7 -0
- package/dist/transform/workers/shared.js +130 -0
- package/dist/transform/workers/transform-child.d.ts +0 -1
- package/dist/transform/workers/transform-child.js +5 -135
- package/dist/transform/workers/transform-worker.d.ts +0 -1
- package/dist/transform/workers/transform-worker.js +7 -128
- package/package.json +11 -7
- package/dist/cache.d.ts +0 -54
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -261
- package/dist/cache.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.d.ts +0 -141
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -473
- package/dist/config.js.map +0 -1
- package/dist/crypto.d.ts +0 -4
- package/dist/crypto.d.ts.map +0 -1
- package/dist/crypto.js +0 -56
- package/dist/crypto.js.map +0 -1
- package/dist/dom-noise-removal.d.ts +0 -2
- package/dist/dom-noise-removal.d.ts.map +0 -1
- package/dist/dom-noise-removal.js +0 -494
- package/dist/dom-noise-removal.js.map +0 -1
- package/dist/download.d.ts +0 -4
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js +0 -106
- package/dist/download.js.map +0 -1
- package/dist/errors.d.ts +0 -11
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -65
- package/dist/errors.js.map +0 -1
- package/dist/examples/mcp-fetch-url-client.js +0 -329
- package/dist/examples/mcp-fetch-url-client.js.map +0 -1
- package/dist/fetch-content.d.ts +0 -5
- package/dist/fetch-content.d.ts.map +0 -1
- package/dist/fetch-content.js +0 -164
- package/dist/fetch-content.js.map +0 -1
- package/dist/fetch-stream.d.ts +0 -5
- package/dist/fetch-stream.d.ts.map +0 -1
- package/dist/fetch-stream.js +0 -29
- package/dist/fetch-stream.js.map +0 -1
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js.map +0 -1
- package/dist/host-normalization.d.ts +0 -2
- package/dist/host-normalization.d.ts.map +0 -1
- package/dist/host-normalization.js +0 -91
- package/dist/host-normalization.js.map +0 -1
- package/dist/http/auth.d.ts.map +0 -1
- package/dist/http/auth.js.map +0 -1
- package/dist/http/health.d.ts.map +0 -1
- package/dist/http/health.js.map +0 -1
- package/dist/http/helpers.d.ts.map +0 -1
- package/dist/http/helpers.js.map +0 -1
- package/dist/http/native.d.ts.map +0 -1
- package/dist/http/native.js.map +0 -1
- package/dist/http/rate-limit.d.ts.map +0 -1
- package/dist/http/rate-limit.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/instructions.d.ts.map +0 -1
- package/dist/instructions.js.map +0 -1
- package/dist/ip-blocklist.d.ts +0 -9
- package/dist/ip-blocklist.d.ts.map +0 -1
- package/dist/ip-blocklist.js +0 -79
- package/dist/ip-blocklist.js.map +0 -1
- package/dist/json.d.ts +0 -2
- package/dist/json.d.ts.map +0 -1
- package/dist/json.js +0 -45
- package/dist/json.js.map +0 -1
- package/dist/language-detection.d.ts +0 -3
- package/dist/language-detection.d.ts.map +0 -1
- package/dist/language-detection.js +0 -355
- package/dist/language-detection.js.map +0 -1
- package/dist/markdown-cleanup.d.ts.map +0 -1
- package/dist/markdown-cleanup.js +0 -534
- package/dist/markdown-cleanup.js.map +0 -1
- package/dist/mcp-validator.d.ts +0 -17
- package/dist/mcp-validator.d.ts.map +0 -1
- package/dist/mcp-validator.js +0 -45
- package/dist/mcp-validator.js.map +0 -1
- package/dist/mcp.d.ts +0 -4
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js.map +0 -1
- package/dist/observability.d.ts +0 -23
- package/dist/observability.d.ts.map +0 -1
- package/dist/observability.js +0 -238
- package/dist/observability.js.map +0 -1
- package/dist/prompts.d.ts.map +0 -1
- package/dist/prompts.js.map +0 -1
- package/dist/resources.d.ts.map +0 -1
- package/dist/resources.js.map +0 -1
- package/dist/server-tuning.d.ts +0 -15
- package/dist/server-tuning.d.ts.map +0 -1
- package/dist/server-tuning.js +0 -49
- package/dist/server-tuning.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/session.d.ts +0 -42
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -255
- package/dist/session.js.map +0 -1
- package/dist/tasks/execution.d.ts.map +0 -1
- package/dist/tasks/execution.js.map +0 -1
- package/dist/tasks/manager.d.ts.map +0 -1
- package/dist/tasks/manager.js.map +0 -1
- package/dist/tasks/owner.d.ts.map +0 -1
- package/dist/tasks/owner.js.map +0 -1
- package/dist/timer-utils.d.ts +0 -6
- package/dist/timer-utils.d.ts.map +0 -1
- package/dist/timer-utils.js +0 -27
- package/dist/timer-utils.js.map +0 -1
- package/dist/tool-errors.d.ts +0 -12
- package/dist/tool-errors.d.ts.map +0 -1
- package/dist/tool-errors.js +0 -55
- package/dist/tool-errors.js.map +0 -1
- package/dist/tool-pipeline.d.ts.map +0 -1
- package/dist/tool-pipeline.js.map +0 -1
- package/dist/tool-progress.d.ts.map +0 -1
- package/dist/tool-progress.js.map +0 -1
- package/dist/tools.d.ts +0 -54
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js.map +0 -1
- package/dist/transform/transform.d.ts.map +0 -1
- package/dist/transform/transform.js.map +0 -1
- package/dist/transform/types.d.ts.map +0 -1
- package/dist/transform/types.js.map +0 -1
- package/dist/transform/worker-pool.d.ts.map +0 -1
- package/dist/transform/worker-pool.js.map +0 -1
- package/dist/transform/workers/transform-child.d.ts.map +0 -1
- package/dist/transform/workers/transform-child.js.map +0 -1
- package/dist/transform/workers/transform-worker.d.ts.map +0 -1
- package/dist/transform/workers/transform-worker.js.map +0 -1
- package/dist/type-guards.d.ts +0 -16
- package/dist/type-guards.d.ts.map +0 -1
- package/dist/type-guards.js +0 -13
- package/dist/type-guards.js.map +0 -1
package/dist/http/native.js
CHANGED
|
@@ -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 {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
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
|
|
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
|
|
74
|
+
const isInitializedMethod = isInitializedNotification(body.method);
|
|
75
|
+
const isInitNotification = isInitializedMethod && body.id === undefined;
|
|
74
76
|
const sessionId = getMcpSessionId(ctx.req);
|
|
75
|
-
|
|
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 (
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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',
|
|
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
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13
|
+
export {};
|
package/dist/http/rate-limit.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
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
|
|
11
|
-
|
|
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
|
|
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
|
|
31
|
-
process.exit(0);
|
|
30
|
+
writeAndExit(process.stdout, renderCliUsage(), 0);
|
|
32
31
|
}
|
|
33
32
|
if (values.version) {
|
|
34
|
-
process.stdout
|
|
35
|
-
process.exit(0);
|
|
33
|
+
writeAndExit(process.stdout, `${serverVersion}\n`, 0);
|
|
36
34
|
}
|
|
37
|
-
const isStdioMode = values.
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
|
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
|