@j0hanz/fetch-url-mcp 1.1.0 → 1.1.2
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/dist/cache.d.ts +5 -5
- package/dist/cache.js +5 -2
- package/dist/cli.js +12 -5
- package/dist/config.d.ts +1 -1
- package/dist/config.js +19 -18
- package/dist/crypto.js +7 -4
- package/dist/dom-noise-removal.js +14 -11
- package/dist/errors.js +5 -2
- package/dist/fetch.d.ts +4 -3
- package/dist/fetch.js +5 -2
- package/dist/host-normalization.js +7 -6
- package/dist/http-native.js +6 -4
- package/dist/index.js +7 -4
- package/dist/ip-blocklist.js +3 -3
- package/dist/json.js +3 -2
- package/dist/language-detection.js +1 -5
- package/dist/markdown-cleanup.d.ts +6 -1
- package/dist/markdown-cleanup.js +92 -30
- package/dist/mcp-validator.d.ts +3 -2
- package/dist/mcp-validator.js +7 -8
- package/dist/mcp.js +32 -17
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +9 -8
- package/dist/prompts.js +2 -10
- package/dist/resources.js +6 -4
- package/dist/server-tuning.d.ts +2 -1
- package/dist/server-tuning.js +20 -15
- package/dist/server.js +4 -8
- package/dist/session.d.ts +3 -2
- package/dist/session.js +7 -4
- package/dist/tasks.d.ts +1 -1
- package/dist/tasks.js +4 -4
- package/dist/timer-utils.js +4 -1
- package/dist/tools.d.ts +9 -14
- package/dist/tools.js +8 -8
- package/dist/transform-types.d.ts +5 -1
- package/dist/transform.d.ts +2 -2
- package/dist/transform.js +52 -6
- package/dist/type-guards.d.ts +2 -1
- package/dist/type-guards.js +3 -3
- package/dist/workers/transform-child.js +8 -4
- package/dist/workers/transform-worker.js +5 -3
- package/package.json +1 -1
package/dist/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import type { CallToolResult
|
|
3
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
4
4
|
import type { MarkdownTransformResult } from './transform-types.js';
|
|
5
5
|
export interface FetchUrlInput {
|
|
6
6
|
url: string;
|
|
@@ -8,12 +8,7 @@ export interface FetchUrlInput {
|
|
|
8
8
|
forceRefresh?: boolean | undefined;
|
|
9
9
|
maxInlineChars?: number | undefined;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
type: 'text';
|
|
13
|
-
text: string;
|
|
14
|
-
}
|
|
15
|
-
export type ToolContentBlockUnion = ContentBlock;
|
|
16
|
-
export type ToolErrorResponse = CallToolResult & {
|
|
11
|
+
type ToolErrorResponse = CallToolResult & {
|
|
17
12
|
structuredContent: {
|
|
18
13
|
error: string;
|
|
19
14
|
url: string;
|
|
@@ -22,10 +17,10 @@ export type ToolErrorResponse = CallToolResult & {
|
|
|
22
17
|
};
|
|
23
18
|
isError: true;
|
|
24
19
|
};
|
|
25
|
-
|
|
20
|
+
type ToolResponseBase = CallToolResult & {
|
|
26
21
|
structuredContent: Record<string, unknown>;
|
|
27
22
|
};
|
|
28
|
-
|
|
23
|
+
interface FetchPipelineOptions<T> {
|
|
29
24
|
url: string;
|
|
30
25
|
cacheNamespace: string;
|
|
31
26
|
signal?: AbortSignal;
|
|
@@ -39,7 +34,7 @@ export interface FetchPipelineOptions<T> {
|
|
|
39
34
|
serialize?: (result: T) => string;
|
|
40
35
|
deserialize?: (cached: string) => T | undefined;
|
|
41
36
|
}
|
|
42
|
-
|
|
37
|
+
interface PipelineResult<T> {
|
|
43
38
|
data: T;
|
|
44
39
|
fromCache: boolean;
|
|
45
40
|
url: string;
|
|
@@ -48,8 +43,8 @@ export interface PipelineResult<T> {
|
|
|
48
43
|
fetchedAt: string;
|
|
49
44
|
cacheKey?: string | null;
|
|
50
45
|
}
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
type ProgressToken = string | number;
|
|
47
|
+
interface RequestMeta {
|
|
53
48
|
progressToken?: ProgressToken | undefined;
|
|
54
49
|
[key: string]: unknown;
|
|
55
50
|
}
|
|
@@ -64,7 +59,7 @@ export interface ProgressNotification {
|
|
|
64
59
|
method: 'notifications/progress';
|
|
65
60
|
params: ProgressNotificationParams;
|
|
66
61
|
}
|
|
67
|
-
|
|
62
|
+
interface ToolHandlerExtra {
|
|
68
63
|
signal?: AbortSignal;
|
|
69
64
|
requestId?: string | number;
|
|
70
65
|
sessionId?: unknown;
|
|
@@ -89,7 +84,7 @@ interface InlineContentResult {
|
|
|
89
84
|
contentSize: number;
|
|
90
85
|
truncated?: boolean;
|
|
91
86
|
}
|
|
92
|
-
|
|
87
|
+
type InlineResult = ReturnType<InlineContentLimiter['apply']>;
|
|
93
88
|
declare class InlineContentLimiter {
|
|
94
89
|
apply(content: string, inlineLimitOverride?: number): InlineContentResult;
|
|
95
90
|
private resolveInlineLimit;
|
package/dist/tools.js
CHANGED
|
@@ -708,12 +708,7 @@ function serializeMarkdownResult(result) {
|
|
|
708
708
|
function buildStructuredContent(pipeline, inlineResult, inputUrl) {
|
|
709
709
|
const cacheResourceUri = resolveCacheResourceUri(pipeline.cacheKey);
|
|
710
710
|
const truncated = inlineResult.truncated ?? pipeline.data.truncated;
|
|
711
|
-
|
|
712
|
-
if (pipeline.data.truncated &&
|
|
713
|
-
!inlineResult.truncated &&
|
|
714
|
-
typeof markdown === 'string') {
|
|
715
|
-
markdown = appendTruncationMarker(markdown, TRUNCATION_MARKER);
|
|
716
|
-
}
|
|
711
|
+
const markdown = applyTruncationMarker(inlineResult.content, pipeline.data.truncated);
|
|
717
712
|
const { metadata } = pipeline.data;
|
|
718
713
|
return {
|
|
719
714
|
url: pipeline.originalUrl ?? pipeline.url,
|
|
@@ -730,6 +725,11 @@ function buildStructuredContent(pipeline, inlineResult, inputUrl) {
|
|
|
730
725
|
...(truncated ? { truncated: true } : {}),
|
|
731
726
|
};
|
|
732
727
|
}
|
|
728
|
+
function applyTruncationMarker(content, truncated) {
|
|
729
|
+
if (!truncated || typeof content !== 'string')
|
|
730
|
+
return content;
|
|
731
|
+
return appendTruncationMarker(content, TRUNCATION_MARKER);
|
|
732
|
+
}
|
|
733
733
|
function resolveCacheResourceUri(cacheKey) {
|
|
734
734
|
if (!cacheKey)
|
|
735
735
|
return undefined;
|
|
@@ -866,14 +866,14 @@ function resolveSessionIdFromExtra(extra) {
|
|
|
866
866
|
export function registerTools(server) {
|
|
867
867
|
if (!config.tools.enabled.includes(FETCH_URL_TOOL_NAME))
|
|
868
868
|
return;
|
|
869
|
-
server.registerTool(TOOL_DEFINITION.name, {
|
|
869
|
+
const registeredTool = server.registerTool(TOOL_DEFINITION.name, {
|
|
870
870
|
title: TOOL_DEFINITION.title,
|
|
871
871
|
description: TOOL_DEFINITION.description,
|
|
872
872
|
inputSchema: TOOL_DEFINITION.inputSchema,
|
|
873
873
|
outputSchema: TOOL_DEFINITION.outputSchema,
|
|
874
874
|
annotations: TOOL_DEFINITION.annotations,
|
|
875
875
|
execution: TOOL_DEFINITION.execution,
|
|
876
|
-
// Use specific tool icon here
|
|
877
876
|
icons: [TOOL_ICON],
|
|
878
877
|
}, withRequestContextIfMissing(TOOL_DEFINITION.handler));
|
|
878
|
+
registeredTool.execution = TOOL_DEFINITION.execution;
|
|
879
879
|
}
|
|
@@ -102,6 +102,10 @@ export interface TransformWorkerCancelMessage {
|
|
|
102
102
|
type: 'cancel';
|
|
103
103
|
id: string;
|
|
104
104
|
}
|
|
105
|
+
export interface TransformWorkerCancelledMessage {
|
|
106
|
+
type: 'cancelled';
|
|
107
|
+
id: string;
|
|
108
|
+
}
|
|
105
109
|
export interface TransformWorkerResultMessage {
|
|
106
110
|
type: 'result';
|
|
107
111
|
id: string;
|
|
@@ -123,4 +127,4 @@ export interface TransformWorkerErrorMessage {
|
|
|
123
127
|
details?: Record<string, unknown>;
|
|
124
128
|
};
|
|
125
129
|
}
|
|
126
|
-
export type TransformWorkerOutgoingMessage = TransformWorkerResultMessage | TransformWorkerErrorMessage;
|
|
130
|
+
export type TransformWorkerOutgoingMessage = TransformWorkerResultMessage | TransformWorkerErrorMessage | TransformWorkerCancelledMessage;
|
package/dist/transform.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtractedArticle, ExtractedMetadata, ExtractionResult, MarkdownTransformResult, MetadataBlock, TransformOptions, TransformStageContext } from './transform-types.js';
|
|
2
|
-
|
|
2
|
+
interface StageBudget {
|
|
3
3
|
totalBudgetMs: number;
|
|
4
4
|
elapsedMs: number;
|
|
5
5
|
}
|
|
@@ -21,7 +21,7 @@ export declare function isExtractionSufficient(article: ExtractedArticle | null,
|
|
|
21
21
|
export declare function determineContentExtractionSource(article: ExtractedArticle | null): article is ExtractedArticle;
|
|
22
22
|
export declare function createContentMetadataBlock(url: string, article: ExtractedArticle | null, extractedMeta: ExtractedMetadata, shouldExtractFromArticle: boolean, includeMetadata: boolean): MetadataBlock | undefined;
|
|
23
23
|
export declare function transformHtmlToMarkdownInProcess(html: string, url: string, options: TransformOptions): MarkdownTransformResult;
|
|
24
|
-
|
|
24
|
+
interface TransformPoolStats {
|
|
25
25
|
queueDepth: number;
|
|
26
26
|
activeWorkers: number;
|
|
27
27
|
capacity: number;
|
package/dist/transform.js
CHANGED
|
@@ -42,6 +42,9 @@ function getTagName(node) {
|
|
|
42
42
|
const raw = node.tagName;
|
|
43
43
|
return typeof raw === 'string' ? raw.toUpperCase() : '';
|
|
44
44
|
}
|
|
45
|
+
function asError(value) {
|
|
46
|
+
return value instanceof Error ? value : undefined;
|
|
47
|
+
}
|
|
45
48
|
function getAbortReason(signal) {
|
|
46
49
|
const record = isObject(signal) ? signal : null;
|
|
47
50
|
return record && 'reason' in record ? record['reason'] : undefined;
|
|
@@ -513,7 +516,7 @@ function extractArticle(document, url, signal) {
|
|
|
513
516
|
};
|
|
514
517
|
}
|
|
515
518
|
catch (error) {
|
|
516
|
-
logError('Failed to extract article with Readability', error
|
|
519
|
+
logError('Failed to extract article with Readability', asError(error));
|
|
517
520
|
return null;
|
|
518
521
|
}
|
|
519
522
|
}
|
|
@@ -573,7 +576,7 @@ function extractContentContext(html, url, options) {
|
|
|
573
576
|
if (error instanceof FetchError)
|
|
574
577
|
throw error;
|
|
575
578
|
abortPolicy.throwIfAborted(options.signal, url, 'extract:error');
|
|
576
|
-
logError('Failed to extract content', error
|
|
579
|
+
logError('Failed to extract content', asError(error));
|
|
577
580
|
const { document } = parseHTML('<html></html>');
|
|
578
581
|
return { article: null, metadata: {}, document };
|
|
579
582
|
}
|
|
@@ -1149,7 +1152,7 @@ function translateHtmlToMarkdown(params) {
|
|
|
1149
1152
|
abortPolicy.throwIfAborted(signal, url, 'markdown:cleaned');
|
|
1150
1153
|
const content = stageTracker.run(url, 'markdown:translate', () => translateHtmlFragmentToMarkdown(cleanedHtml));
|
|
1151
1154
|
abortPolicy.throwIfAborted(signal, url, 'markdown:translated');
|
|
1152
|
-
const cleaned = cleanupMarkdownArtifacts(content);
|
|
1155
|
+
const cleaned = cleanupMarkdownArtifacts(content, signal ? { signal, url } : { url });
|
|
1153
1156
|
return url ? resolveRelativeUrls(cleaned, url) : cleaned;
|
|
1154
1157
|
}
|
|
1155
1158
|
function appendMetadataFooter(content, metadata, url) {
|
|
@@ -1177,7 +1180,7 @@ export function htmlToMarkdown(html, metadata, options) {
|
|
|
1177
1180
|
catch (error) {
|
|
1178
1181
|
if (error instanceof FetchError)
|
|
1179
1182
|
throw error;
|
|
1180
|
-
logError('Failed to convert HTML to markdown', error
|
|
1183
|
+
logError('Failed to convert HTML to markdown', asError(error));
|
|
1181
1184
|
throw new FetchError('Failed to convert HTML to markdown', url, 500, {
|
|
1182
1185
|
reason: 'markdown_convert_failed',
|
|
1183
1186
|
});
|
|
@@ -1647,6 +1650,9 @@ function isWorkerResponse(raw) {
|
|
|
1647
1650
|
if (raw['type'] === 'error') {
|
|
1648
1651
|
return isWorkerErrorPayload(raw['error']);
|
|
1649
1652
|
}
|
|
1653
|
+
if (raw['type'] === 'cancelled') {
|
|
1654
|
+
return true;
|
|
1655
|
+
}
|
|
1650
1656
|
return false;
|
|
1651
1657
|
}
|
|
1652
1658
|
function createTaskContext() {
|
|
@@ -1836,6 +1842,7 @@ class WorkerPool {
|
|
|
1836
1842
|
queue = [];
|
|
1837
1843
|
queueHead = 0;
|
|
1838
1844
|
inflight = new Map();
|
|
1845
|
+
cancelAcks = new Map();
|
|
1839
1846
|
timeoutMs;
|
|
1840
1847
|
queueMax;
|
|
1841
1848
|
spawnWorkerImpl;
|
|
@@ -1963,7 +1970,7 @@ class WorkerPool {
|
|
|
1963
1970
|
}
|
|
1964
1971
|
const inflight = this.inflight.get(id);
|
|
1965
1972
|
if (inflight) {
|
|
1966
|
-
this.abortInflight(id, url, inflight.workerIndex);
|
|
1973
|
+
void this.abortInflight(id, url, inflight.workerIndex);
|
|
1967
1974
|
return;
|
|
1968
1975
|
}
|
|
1969
1976
|
const queuedIndex = this.findQueuedIndex(id);
|
|
@@ -1985,8 +1992,36 @@ class WorkerPool {
|
|
|
1985
1992
|
this.maybeCompactQueue();
|
|
1986
1993
|
}
|
|
1987
1994
|
}
|
|
1988
|
-
|
|
1995
|
+
resolveCancelAck(id) {
|
|
1996
|
+
const pending = this.cancelAcks.get(id);
|
|
1997
|
+
if (!pending)
|
|
1998
|
+
return;
|
|
1999
|
+
pending.timeout.cancel();
|
|
2000
|
+
pending.resolve();
|
|
2001
|
+
}
|
|
2002
|
+
waitForCancelAck(id) {
|
|
2003
|
+
const existing = this.cancelAcks.get(id);
|
|
2004
|
+
if (existing) {
|
|
2005
|
+
return existing.promise;
|
|
2006
|
+
}
|
|
2007
|
+
let resolve = () => { };
|
|
2008
|
+
const timeout = createUnrefTimeout(200, undefined);
|
|
2009
|
+
const racePromise = new Promise((finish) => {
|
|
2010
|
+
resolve = finish;
|
|
2011
|
+
});
|
|
2012
|
+
const promise = Promise.race([racePromise, timeout.promise]).finally(() => {
|
|
2013
|
+
this.cancelAcks.delete(id);
|
|
2014
|
+
timeout.cancel();
|
|
2015
|
+
});
|
|
2016
|
+
this.cancelAcks.set(id, { promise, resolve, timeout });
|
|
2017
|
+
return promise;
|
|
2018
|
+
}
|
|
2019
|
+
async abortInflight(id, url, workerIndex) {
|
|
1989
2020
|
const slot = this.workers[workerIndex];
|
|
2021
|
+
const inflight = this.inflight.get(id);
|
|
2022
|
+
if (inflight) {
|
|
2023
|
+
inflight.cancelPending = true;
|
|
2024
|
+
}
|
|
1990
2025
|
if (slot) {
|
|
1991
2026
|
try {
|
|
1992
2027
|
slot.host.postMessage({ type: 'cancel', id });
|
|
@@ -1995,6 +2030,7 @@ class WorkerPool {
|
|
|
1995
2030
|
// Worker may be unavailable; failure is acceptable during abort
|
|
1996
2031
|
}
|
|
1997
2032
|
}
|
|
2033
|
+
await this.waitForCancelAck(id);
|
|
1998
2034
|
this.failTask(id, abortPolicy.createAbortError(url, 'transform:signal-abort'));
|
|
1999
2035
|
if (slot)
|
|
2000
2036
|
this.restartWorker(workerIndex, slot);
|
|
@@ -2059,6 +2095,15 @@ class WorkerPool {
|
|
|
2059
2095
|
if (!isWorkerResponse(raw))
|
|
2060
2096
|
return;
|
|
2061
2097
|
const message = raw;
|
|
2098
|
+
if (message.type === 'cancelled') {
|
|
2099
|
+
this.resolveCancelAck(message.id);
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
const inflightPeek = this.inflight.get(message.id);
|
|
2103
|
+
if (inflightPeek?.cancelPending) {
|
|
2104
|
+
this.resolveCancelAck(message.id);
|
|
2105
|
+
return;
|
|
2106
|
+
}
|
|
2062
2107
|
const inflight = this.takeInflight(message.id);
|
|
2063
2108
|
if (!inflight)
|
|
2064
2109
|
return;
|
|
@@ -2208,6 +2253,7 @@ class WorkerPool {
|
|
|
2208
2253
|
abortListener: task.abortListener,
|
|
2209
2254
|
workerIndex,
|
|
2210
2255
|
context: task.context,
|
|
2256
|
+
cancelPending: false,
|
|
2211
2257
|
});
|
|
2212
2258
|
try {
|
|
2213
2259
|
const { message, transferList } = buildWorkerDispatchPayload(task, slot.host.supportsTransferList);
|
package/dist/type-guards.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare function isObject(value: unknown): value is Record<PropertyKey, unknown>;
|
|
2
2
|
export declare function isError(value: unknown): value is Error;
|
|
3
|
-
|
|
3
|
+
interface LikeNode {
|
|
4
4
|
readonly tagName?: string | undefined;
|
|
5
5
|
readonly nodeName?: string | undefined;
|
|
6
6
|
readonly nodeType?: number | undefined;
|
|
@@ -12,3 +12,4 @@ export interface LikeNode {
|
|
|
12
12
|
getAttribute?(name: string): string | null;
|
|
13
13
|
}
|
|
14
14
|
export declare function isLikeNode(value: unknown): value is LikeNode;
|
|
15
|
+
export {};
|
package/dist/type-guards.js
CHANGED
|
@@ -2,9 +2,9 @@ export function isObject(value) {
|
|
|
2
2
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
3
|
}
|
|
4
4
|
export function isError(value) {
|
|
5
|
-
const
|
|
6
|
-
if (typeof
|
|
7
|
-
return
|
|
5
|
+
const { isError: isErrorFn } = Error;
|
|
6
|
+
if (typeof isErrorFn === 'function') {
|
|
7
|
+
return isErrorFn(value);
|
|
8
8
|
}
|
|
9
9
|
return value instanceof Error;
|
|
10
10
|
}
|
|
@@ -4,11 +4,15 @@ import { transformHtmlToMarkdownInProcess } from '../transform.js';
|
|
|
4
4
|
const send = process.send?.bind(process);
|
|
5
5
|
if (!send)
|
|
6
6
|
throw new Error('transform-child started without IPC channel');
|
|
7
|
+
const sendMessage = send;
|
|
8
|
+
function postMessage(message) {
|
|
9
|
+
sendMessage(message);
|
|
10
|
+
}
|
|
7
11
|
const controllersById = new Map();
|
|
8
12
|
const decoder = new TextDecoder('utf-8');
|
|
9
13
|
function postError(id, url, error) {
|
|
10
14
|
if (error instanceof FetchError) {
|
|
11
|
-
|
|
15
|
+
postMessage({
|
|
12
16
|
type: 'error',
|
|
13
17
|
id,
|
|
14
18
|
error: {
|
|
@@ -21,7 +25,7 @@ function postError(id, url, error) {
|
|
|
21
25
|
});
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
24
|
-
|
|
28
|
+
postMessage({
|
|
25
29
|
type: 'error',
|
|
26
30
|
id,
|
|
27
31
|
error: {
|
|
@@ -52,7 +56,7 @@ function isValidMessage(msg) {
|
|
|
52
56
|
return true;
|
|
53
57
|
}
|
|
54
58
|
function postValidationError(id, url, message) {
|
|
55
|
-
|
|
59
|
+
postMessage({
|
|
56
60
|
type: 'error',
|
|
57
61
|
id,
|
|
58
62
|
error: { name: 'ValidationError', message, url },
|
|
@@ -94,7 +98,7 @@ function handleTransform(msg) {
|
|
|
94
98
|
...(inputTruncated ? { inputTruncated: true } : {}),
|
|
95
99
|
});
|
|
96
100
|
const { markdown, metadata, title, truncated } = result;
|
|
97
|
-
|
|
101
|
+
postMessage({
|
|
98
102
|
type: 'result',
|
|
99
103
|
id,
|
|
100
104
|
result: title === undefined
|
|
@@ -61,6 +61,9 @@ function decodeHtmlBuffer(htmlBuffer, encoding) {
|
|
|
61
61
|
return decoder.decode(htmlBuffer);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
function resolveHtmlContent(html, htmlBuffer, encoding) {
|
|
65
|
+
return htmlBuffer ? decodeHtmlBuffer(htmlBuffer, encoding) : (html ?? '');
|
|
66
|
+
}
|
|
64
67
|
function handleTransform(msg) {
|
|
65
68
|
if (!isValidMessage(msg))
|
|
66
69
|
return;
|
|
@@ -76,9 +79,7 @@ function handleTransform(msg) {
|
|
|
76
79
|
const controller = new AbortController();
|
|
77
80
|
controllersById.set(id, controller);
|
|
78
81
|
try {
|
|
79
|
-
const content = htmlBuffer
|
|
80
|
-
? decodeHtmlBuffer(htmlBuffer, encoding)
|
|
81
|
-
: (html ?? '');
|
|
82
|
+
const content = resolveHtmlContent(html, htmlBuffer, encoding);
|
|
82
83
|
const result = transformHtmlToMarkdownInProcess(content, url, {
|
|
83
84
|
includeMetadata,
|
|
84
85
|
signal: controller.signal,
|
|
@@ -121,6 +122,7 @@ port.on('message', (raw) => {
|
|
|
121
122
|
const controller = controllersById.get(id);
|
|
122
123
|
if (controller)
|
|
123
124
|
controller.abort(new Error('Canceled'));
|
|
125
|
+
port.postMessage({ type: 'cancelled', id });
|
|
124
126
|
return;
|
|
125
127
|
}
|
|
126
128
|
if (type === 'transform') {
|
package/package.json
CHANGED